M5:百工与司命——能力注册表、授契行契请命、禁域裁决与观察标证
- 百工域 domains/baigong:capabilities(统一能力契约:执行类型 builtin/qiankun/mcp/http + 四维风险标注 + 来源版本)、mandates(授契 grant / 行契 charter 预算时间窗,撤销立即生效)、tool_calls(净化摘要 + 观察标证);请命复用 pending_confirmations 加 expires_at/brief_json(超时=拒绝执行 HJ-1302,六要素说明) - 司命裁决器 siming.py:四维取最高档(能力/数据/后果/情境);禁域为代码常量不可配置(递归删根/格式化/写裸设备/fork 炸弹、file:// 协议、密钥材料外发)——专项测试断言恶意标注与篡改对象仍拒 HJ-1301 - 执行链:禁域→裁决(HJ-1303 未授契拒且双留痕)→请命→执行(乾坤经 SandboxClient HMAC;MCP 经 call_tool;内置无副作用)→净化标证(观察非事实,敏感遮蔽+体量截断)→行动账 - MCP 登记/启停/刷新自动派生与撤下 capabilities(博闻登记接入点);内置能力种子(echo/datetime/qiankun.shell/web.fetch) - 端点:/capabilities /mandates /petitions /tool-calls + /tools 兼容投影;前端百工页四区(能力目录四维标注/授契行契/请命批准拒绝/行动账观察标证) - 退役:modules/safety|skills|tool_runtime|agent、application/tool_runtime、services/skills|safety、tool_policies/skills/model_endpoint_overrides 表(迁移 006)、前端 SkillManager/ToolsConsole/旧 tools 页 - 验收(test_baigong_siming 四用例):未授契被拒留痕、请命超时不执行、禁域不可关闭、结果为观察不入忆;后端 454、前端 220、BFF 4、神识 5 包全绿(2 个预存环境失败不变)
This commit is contained in:
1 parent
144415247e
commit
684261f4b4
97 files changed
+3075
-5554
No files matched your search
@@ -1,14 +1,13 @@
|
||||
"""司命台管理聚合服务(api-spec §19.1–§19.3)。
|
||||
|
||||
九枢健康度由各枢运行/治理数据派生(不落长期状态,§19.1);朱批待办复用
|
||||
ConfirmationStore(§19.2);起居注审计复用 audit_events(§19.3)。
|
||||
待决请命(§19.2);起居注审计复用 audit_events(§19.3)。
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from app.application.tool_runtime.runtime import ToolRuntime
|
||||
from app.core.config import settings
|
||||
from app.core.security import redact_text
|
||||
from app.core.time import to_iso, utc_now
|
||||
@@ -23,8 +22,7 @@ from app.models.governance import (
|
||||
from app.models.idempotency import IdempotencyKey
|
||||
from app.models.xirang import Memory
|
||||
from app.models.runtime import Event, Run
|
||||
from app.models.safety import AuditEvent
|
||||
from app.modules.safety.confirmation import ConfirmationStore, PendingConfirmation
|
||||
from app.models.safety import AuditEvent, PendingConfirmationRecord
|
||||
from app.repositories import audit as audit_repo
|
||||
from app.repositories import characters as character_repo
|
||||
from app.repositories import governance as governance_repo
|
||||
@@ -66,12 +64,22 @@ def _summarize_input(value: dict | None) -> str:
|
||||
|
||||
async def get_pivots_health(
|
||||
*,
|
||||
confirmation_store: ConfirmationStore,
|
||||
tool_runtime: ToolRuntime | None,
|
||||
owner_scope: str = settings.default_owner_scope,
|
||||
) -> PivotHealthReport:
|
||||
async with AsyncSessionLocal() as session:
|
||||
pending_count = len(await confirmation_store.list_pending())
|
||||
pending_count = len(
|
||||
list(
|
||||
(
|
||||
await session.execute(
|
||||
select(PendingConfirmationRecord).where(
|
||||
PendingConfirmationRecord.status == "pending"
|
||||
)
|
||||
)
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
)
|
||||
goals_n = await governance_repo.count(session, Goal)
|
||||
world_n = await governance_repo.count(session, WorldEntity)
|
||||
plans_n = await governance_repo.count(session, Plan)
|
||||
@@ -80,7 +88,7 @@ async def get_pivots_health(
|
||||
memories_n = await governance_repo.count(session, Memory, Memory.status != "tombstoned")
|
||||
character = await character_repo.get_active_character(session, owner_scope)
|
||||
has_personality = bool(character and character.current_personality_version_id)
|
||||
tool_enabled = settings.enable_tool_runtime and tool_runtime is not None
|
||||
tool_enabled = True # 百工域常驻(乾坤可用性按端点区分)
|
||||
now = to_iso(utc_now())
|
||||
|
||||
raw: list[tuple[str, str, str, bool, str]] = [
|
||||
@@ -128,38 +136,42 @@ async def get_pivots_health(
|
||||
)
|
||||
|
||||
|
||||
async def get_pending_approvals(
|
||||
*,
|
||||
confirmation_store: ConfirmationStore,
|
||||
tool_runtime: ToolRuntime | None,
|
||||
) -> list[PendingApproval]:
|
||||
specs = {spec.name: spec for spec in tool_runtime.list_specs()} if tool_runtime else {}
|
||||
async def get_pending_approvals() -> list[PendingApproval]:
|
||||
async with AsyncSessionLocal() as session:
|
||||
records = (
|
||||
(
|
||||
await session.execute(
|
||||
select(PendingConfirmationRecord)
|
||||
.where(PendingConfirmationRecord.status == "pending")
|
||||
.order_by(PendingConfirmationRecord.created_at.asc())
|
||||
)
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
approvals: list[PendingApproval] = []
|
||||
for pending in await confirmation_store.list_pending():
|
||||
spec = specs.get(pending.tool)
|
||||
permission_policy = str(spec.permission_policy) if spec else "ask"
|
||||
possible_impact = "可能产生副作用" if (spec and spec.side_effect) else None
|
||||
approvals.append(_pending_to_approval(pending, permission_policy, possible_impact))
|
||||
for record in records:
|
||||
try:
|
||||
input_payload = json.loads(record.input_json) if record.input_json else {}
|
||||
except ValueError:
|
||||
input_payload = {}
|
||||
approvals.append(
|
||||
PendingApproval(
|
||||
confirmation_id=record.id,
|
||||
character_id=record.character_id,
|
||||
tool=record.tool,
|
||||
risk_level=record.risk_level,
|
||||
permission_policy="ask",
|
||||
action_summary=f"调用能力 {record.tool}",
|
||||
input_summary=_summarize_input(input_payload),
|
||||
possible_impact=None,
|
||||
reason=record.reason,
|
||||
created_at=record.created_at.isoformat() if record.created_at else "",
|
||||
)
|
||||
)
|
||||
return approvals
|
||||
|
||||
|
||||
def _pending_to_approval(
|
||||
pending: PendingConfirmation, permission_policy: str, possible_impact: str | None
|
||||
) -> PendingApproval:
|
||||
return PendingApproval(
|
||||
confirmation_id=pending.confirmation_id,
|
||||
character_id=pending.character_id,
|
||||
tool=pending.tool,
|
||||
risk_level=pending.risk_level,
|
||||
permission_policy=permission_policy,
|
||||
action_summary=f"调用工具 {pending.tool}",
|
||||
input_summary=_summarize_input(pending.input),
|
||||
possible_impact=possible_impact,
|
||||
reason=pending.reason,
|
||||
created_at=pending.created_at,
|
||||
)
|
||||
|
||||
|
||||
async def get_audit_timeline(
|
||||
*,
|
||||
pivot: str | None = None,
|
||||
|
||||
Reference in new issue
Block a user