@sema-agent/server 7.142.0 → 7.143.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +442 -0
- package/USAGE.md +41 -24
- package/dist/adoption/plan.js +22 -0
- package/dist/approval-ask-audit-store.d.ts +7 -5
- package/dist/approval-ask-audit-store.js +12 -6
- package/dist/approval-ask-machine.d.ts +15 -7
- package/dist/approval-ask-machine.js +10 -4
- package/dist/approval-card.d.ts +124 -25
- package/dist/approval-card.js +103 -23
- package/dist/approval-queue-kind.d.ts +27 -0
- package/dist/approval-queue-kind.js +6 -0
- package/dist/approval-reconciler.d.ts +8 -8
- package/dist/approval-reconciler.js +3 -3
- package/dist/audit.js +4 -2
- package/dist/boot/budget-tracing.d.ts +1 -1
- package/dist/boot/governance-seams.d.ts +26 -41
- package/dist/boot/governance-seams.js +61 -28
- package/dist/boot/late-binds.d.ts +7 -4
- package/dist/boot/late-binds.js +3 -1
- package/dist/boot/leader.js +2 -4
- package/dist/boot/memory-consolidation.d.ts +0 -8
- package/dist/boot/memory-consolidation.js +3 -3
- package/dist/boot/reapers.js +5 -4
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +8 -8
- package/dist/boot/runner-deps.d.ts +10 -7
- package/dist/boot/runner-deps.js +5 -17
- package/dist/boot/shutdown.d.ts +9 -0
- package/dist/boot/shutdown.js +16 -2
- package/dist/boot/stage-02-web-admin-pull.js +3 -0
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +1 -2
- package/dist/boot/stage-04-stores.d.ts +5 -2
- package/dist/boot/stage-04-stores.js +3 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -2
- package/dist/boot/stage-06-runners.d.ts +5 -2
- package/dist/boot/stage-06-runners.js +1 -3
- package/dist/boot/stage-07-capability-layer.d.ts +5 -2
- package/dist/boot/stage-07-capability-layer.js +5 -1
- package/dist/boot/stage-08-reapers.d.ts +5 -2
- package/dist/boot/stage-09-leader.d.ts +5 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -2
- package/dist/boot/stage-10-http-server.js +9 -1
- package/dist/boot/stores.d.ts +5 -2
- package/dist/boot/stores.js +7 -7
- package/dist/boot/web-admin.d.ts +5 -1
- package/dist/boot/web-admin.js +31 -19
- package/dist/capabilities/hands-lane.d.ts +9 -39
- package/dist/capabilities/hands-lane.js +8 -13
- package/dist/capabilities/mcp-probe.d.ts +3 -2
- package/dist/capabilities/scenarios.d.ts +11 -1
- package/dist/capabilities/scenarios.js +1 -0
- package/dist/capabilities/skills.d.ts +1 -17
- package/dist/capabilities/skills.js +0 -8
- package/dist/capability-facts.d.ts +8 -8
- package/dist/capability-facts.js +4 -4
- package/dist/card-void.d.ts +6 -9
- package/dist/config-catalog.js +1 -1
- package/dist/config-dir-trust.js +58 -29
- package/dist/config-invariants.d.ts +7 -1
- package/dist/config-invariants.js +7 -0
- package/dist/config-provider.d.ts +10 -0
- package/dist/config-provider.js +15 -4
- package/dist/config-root-migration.d.ts +13 -0
- package/dist/config-root-migration.js +99 -0
- package/dist/config-types.d.ts +5 -5
- package/dist/config.d.ts +4 -3
- package/dist/config.js +1 -1
- package/dist/delegated-session-owner.d.ts +5 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/env-model-table-gate.d.ts +53 -0
- package/dist/env-model-table-gate.js +53 -0
- package/dist/fleet/fleet-bus.d.ts +28 -52
- package/dist/fleet/fleet-bus.js +35 -100
- package/dist/fleet/fleet-reconciler.d.ts +4 -4
- package/dist/fleet/fleet-reconciler.js +1 -1
- package/dist/fleet/subagent-tail-bus.d.ts +14 -11
- package/dist/fleet/subagent-tail-bus.js +15 -28
- package/dist/hooks/hook-runner.js +28 -7
- package/dist/host-decision.d.ts +54 -20
- package/dist/host-decision.js +42 -14
- package/dist/http/admission.d.ts +1 -1
- package/dist/http/admission.js +7 -3
- package/dist/http/approval-sweeps.js +11 -8
- package/dist/http/caller-trust.d.ts +1 -1
- package/dist/http/durable-run-leg.js +2 -2
- package/dist/http/engine-refusal.d.ts +16 -0
- package/dist/http/engine-refusal.js +17 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
- package/dist/http/memory-compliance-failure-reply.js +4 -6
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +13 -0
- package/dist/http/resume-legs.d.ts +21 -7
- package/dist/http/resume-legs.js +71 -49
- package/dist/http/resume-restatement.d.ts +39 -0
- package/dist/http/resume-restatement.js +25 -0
- package/dist/http/route-ctx.d.ts +35 -10
- package/dist/http/route-ctx.js +1 -1
- package/dist/http/routes/approvals-assistant.d.ts +9 -1
- package/dist/http/routes/approvals-assistant.js +142 -31
- package/dist/http/routes/capabilities.js +11 -2
- package/dist/http/routes/memory-policy.d.ts +2 -2
- package/dist/http/routes/memory-policy.js +1 -1
- package/dist/http/routes/notify-wake.js +23 -25
- package/dist/http/routes/rules.js +48 -13
- package/dist/http/routes/runs.js +9 -8
- package/dist/http/routes/session-memory-sync.d.ts +34 -6
- package/dist/http/routes/session-memory-sync.js +27 -10
- package/dist/http/routes/session-sync.js +13 -20
- package/dist/http/routes/sessions.d.ts +2 -2
- package/dist/http/routes/sessions.js +22 -23
- package/dist/http/routes/tasks.js +27 -49
- package/dist/http/server.d.ts +13 -7
- package/dist/http/server.js +2 -2
- package/dist/http/stored-body-replay.js +15 -4
- package/dist/http/wire-types.d.ts +17 -7
- package/dist/leader/leader.js +5 -2
- package/dist/leader/wire.d.ts +7 -1
- package/dist/leader/wire.js +6 -5
- package/dist/leg-facts.d.ts +37 -0
- package/dist/leg-facts.js +15 -0
- package/dist/memory-bundle-engine.d.ts +1 -4
- package/dist/memory-bundle-engine.js +2 -2
- package/dist/memory-operator-faces.d.ts +30 -66
- package/dist/memory-operator-faces.js +17 -88
- package/dist/memory-scope-stores.d.ts +38 -40
- package/dist/memory-scope-stores.js +51 -36
- package/dist/memory-scope.d.ts +0 -9
- package/dist/memory-scope.js +0 -9
- package/dist/memory-sync-client.js +14 -3
- package/dist/memory-sync.d.ts +20 -4
- package/dist/memory-sync.js +23 -4
- package/dist/model-plane-face.d.ts +13 -7
- package/dist/model-plane-face.js +2 -1
- package/dist/observability/fail-open.d.ts +20 -4
- package/dist/observability/fail-open.js +17 -4
- package/dist/observability/run-terminal.js +4 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
- package/dist/orchestration/workflow-completion-inbox.js +0 -12
- package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
- package/dist/orchestration/workflow-park-decision.d.ts +8 -3
- package/dist/orchestration/workflow-park-decision.js +5 -3
- package/dist/org-delivery-gate.d.ts +11 -0
- package/dist/org-delivery-gate.js +19 -1
- package/dist/parked-decide.d.ts +13 -9
- package/dist/parked-decide.js +7 -7
- package/dist/parked-revive-surface.js +1 -1
- package/dist/peer-inbound-face.d.ts +127 -0
- package/dist/peer-inbound-face.js +158 -0
- package/dist/permission-rule-list.d.ts +13 -9
- package/dist/permission-rule-list.js +7 -3
- package/dist/plugins/approval-ask-store-file.js +18 -6
- package/dist/plugins/approval-ask-store-memory.js +8 -6
- package/dist/plugins/approval-ask-store-sql.d.ts +28 -13
- package/dist/plugins/approval-ask-store-sql.js +30 -11
- package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
- package/dist/plugins/checkpoint-store-sql.js +9 -7
- package/dist/plugins/file-history-store-sql.d.ts +24 -18
- package/dist/plugins/file-history-store-sql.js +24 -19
- package/dist/plugins/file-run-store.d.ts +29 -0
- package/dist/plugins/file-run-store.js +97 -8
- package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
- package/dist/plugins/imported-layer-root-retirement.js +96 -0
- package/dist/plugins/local-checkpoint-store.d.ts +1 -1
- package/dist/plugins/local-checkpoint-store.js +2 -2
- package/dist/plugins/local-session-store.d.ts +6 -2
- package/dist/plugins/local-session-store.js +8 -2
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
- package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
- package/dist/plugins/mailbox-store-sql.d.ts +12 -8
- package/dist/plugins/mailbox-store-sql.js +76 -7
- package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
- package/dist/plugins/memory-sync-store-pg.js +21 -0
- package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
- package/dist/plugins/memory-sync-store-tidb.js +13 -1
- package/dist/plugins/one-time-migrations.d.ts +32 -2
- package/dist/plugins/one-time-migrations.js +106 -3
- package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
- package/dist/plugins/org-delivery-quota-store.js +2 -12
- package/dist/plugins/park-commit-watch.d.ts +1 -1
- package/dist/plugins/permission-rule-store-file.d.ts +10 -1
- package/dist/plugins/permission-rule-store-file.js +15 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
- package/dist/plugins/permission-rule-store-sql.js +35 -2
- package/dist/plugins/remote-env-device.d.ts +8 -11
- package/dist/plugins/remote-env-device.js +6 -3
- package/dist/plugins/remote-env-k8s.d.ts +37 -24
- package/dist/plugins/remote-env-k8s.js +50 -17
- package/dist/plugins/retention-store-sql.d.ts +2 -2
- package/dist/plugins/sandbox-read-floor.d.ts +5 -7
- package/dist/plugins/sandbox-read-floor.js +2 -7
- package/dist/plugins/sql-errors.d.ts +10 -1
- package/dist/plugins/sql-errors.js +13 -0
- package/dist/plugins/store-backend.d.ts +23 -28
- package/dist/plugins/store-backend.js +9 -1
- package/dist/plugins/store-contracts.d.ts +29 -5
- package/dist/plugins/store-contracts.js +4 -1
- package/dist/plugins/task-attachment-store.d.ts +2 -2
- package/dist/plugins/task-attachment-store.js +37 -52
- package/dist/plugins/tool-result-store-sql.d.ts +9 -8
- package/dist/plugins/tool-result-store-sql.js +23 -2
- package/dist/plugins/wiring-section-codec.d.ts +32 -0
- package/dist/plugins/wiring-section-codec.js +55 -0
- package/dist/plugins/workspace-fill.d.ts +1 -1
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +5 -1
- package/dist/rules-consent.d.ts +28 -5
- package/dist/rules-consent.js +40 -28
- package/dist/run-local.js +9 -5
- package/dist/runs.d.ts +12 -8
- package/dist/runs.js +6 -7
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/server-secret-env.d.ts +4 -0
- package/dist/session-error-wire.d.ts +12 -0
- package/dist/session-error-wire.js +6 -0
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-notify-door.d.ts +106 -0
- package/dist/session-notify-door.js +93 -0
- package/dist/session-sync.d.ts +9 -14
- package/dist/session-sync.js +5 -5
- package/dist/session-workspace.d.ts +3 -13
- package/dist/session-workspace.js +0 -9
- package/dist/standing-answer-grant.d.ts +5 -0
- package/dist/standing-answer-grant.js +10 -0
- package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
- package/dist/stores-sql/session-policy-store-sql.js +3 -13
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +11 -8
- package/dist/task-settings.js +31 -11
- package/dist/tool-approval.d.ts +52 -34
- package/dist/tool-approval.js +66 -57
- package/dist/trace/core-keyset-guard.d.ts +11 -8
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +3 -1
- package/dist/trace/exit-seat.d.ts +7 -1
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +2 -2
- package/dist/trace/model-segment.d.ts +55 -25
- package/dist/trace/model-segment.js +101 -33
- package/dist/trace/project.d.ts +7 -4
- package/dist/trace/project.js +6 -0
- package/dist/trace/redact.d.ts +61 -9
- package/dist/trace/redact.js +1490 -468
- package/dist/trace/self-minted-wire.d.ts +510 -38
- package/dist/trace/self-minted-wire.js +165 -17
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/verifier-pause-card.d.ts +33 -5
- package/dist/verifier-pause-card.js +15 -10
- package/dist/web-admin-client/apply-effective.d.ts +12 -16
- package/dist/web-admin-client/apply-effective.js +90 -10
- package/dist/workspace-space.d.ts +19 -3
- package/dist/workspace-space.js +8 -4
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
- package/package.json +3 -2
- package/wire-changes/server@7.143.0.json +1167 -0
package/dist/tool-approval.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExecutionLane } from "./execution-lane-caps.js";
|
|
2
|
-
import { type
|
|
2
|
+
import { type ApprovalDecider, type HostSettledBy, type HostSource, type RetiredDecisionKeyFacts } from "./host-decision.js";
|
|
3
3
|
import type { IncomingMessage } from "node:http";
|
|
4
4
|
import { type AskClass, type AskRequest, type AskOutcome, type PermissionResult, type CheckpointGate, type PendingAction, type PersistedRuleMandate, type ReadRootGrantCandidate, type RuleOffer, type AutoModeFallbackCause, type BoundGrantAbsence, type BoundSkillGrants, type ToolApprovalCard, type ReopenReason } from "@sema-agent/core";
|
|
5
5
|
import { type CardRulePersisted, type RuleConsentLane } from "./rules-consent.js";
|
|
@@ -78,7 +78,7 @@ export type ToolApprovalReadBody = ({
|
|
|
78
78
|
} & AskRowReadProjection);
|
|
79
79
|
/**
|
|
80
80
|
* 结算一张卡的**判决** —— 判别联合,逼每个调用点说清「这次等待是怎么结束的」:
|
|
81
|
-
* · `by:"human"` —— 一次**决议**到了(人答,或从问账行读回来的决议,含部署政策拒落成的 `DECIDED` 行,`
|
|
81
|
+
* · `by:"human"` —— 一次**决议**到了(人答,或从问账行读回来的决议,含部署政策拒落成的 `DECIDED` 行,`hostSource` 记它的来源词与机器座位):`allowed` 说方向;审计 settle 行
|
|
82
82
|
* `outcome` = `allowed` / `denied`,**没有 `cause`**;
|
|
83
83
|
* · `by:"system"` —— 这次等待**没有等到决议就结束了**(非人结局):必须点名一个 {@link SettleCause};审计 settle 行 `outcome:"expired"` + 该 `cause`。
|
|
84
84
|
* 成因**只从事实读**(窗钟到 / 中止信号 / emit 零接收 / 腿作用域退出 / 兄弟被原子撤卡 / 有序关停锁存位 / 问账行的列),不从拒句散文判;
|
|
@@ -88,14 +88,14 @@ export type SettleVerdict = {
|
|
|
88
88
|
readonly by: "human";
|
|
89
89
|
readonly allowed: boolean;
|
|
90
90
|
readonly updatedInput?: unknown;
|
|
91
|
-
/** 宿主自报来源(
|
|
92
|
-
readonly
|
|
91
|
+
/** 宿主自报来源(`AskOutcome` 的 `settledBy` / `decidedVia` 一只值,见 {@link HostSource};缺席 = 人)。 */
|
|
92
|
+
readonly hostSource?: HostSource;
|
|
93
93
|
readonly denyReason?: string;
|
|
94
94
|
readonly readRootGrant?: string;
|
|
95
95
|
} | {
|
|
96
96
|
readonly by: "system";
|
|
97
97
|
readonly cause: SettleCause;
|
|
98
|
-
readonly
|
|
98
|
+
readonly hostSource?: HostSource;
|
|
99
99
|
};
|
|
100
100
|
/**
|
|
101
101
|
* 🔴 [ref](案A)追记 F6 —— durable 回决口(`POST /v1/tasks/:taskId/asks/:askId/decision`)的 **200 体
|
|
@@ -139,10 +139,10 @@ export interface ParkedAskRedeemRequest {
|
|
|
139
139
|
decision: "approve" | "deny";
|
|
140
140
|
/** [ref] 同源的人写理由(deny 时 core 把它交给模型;allow 只进审计面)。 */
|
|
141
141
|
note?: string;
|
|
142
|
-
/** [ref]:决定体的**出处位**(已过 `
|
|
142
|
+
/** [ref]:决定体的**出处位**(已过 `readDecider` 的 wire 词,缺席已落成 `"person"`),经 `hostDecisionFacts` 落到停驻座的
|
|
143
143
|
* `hostDecision.decidedBy`。live 命中臂与本 PARKED 臂读**同一格** —— 同一份体落在哪条臂上只取决于副本与时序;两臂各走自己座的
|
|
144
|
-
* 那一只映射(live = `
|
|
145
|
-
|
|
144
|
+
* 那一只映射(live = `liveHostSource`,停驻 = 恒等),词表只有一份。 */
|
|
145
|
+
decider: ApprovalDecider;
|
|
146
146
|
/** [ref] ctrl+g 编辑放行的实参整体替换(approve 才有意义)。 */
|
|
147
147
|
updatedInput?: unknown;
|
|
148
148
|
/** 发起本次 respond 的**已验证**调用方(live 腿 `gatedPrincipal` 的那一把)。席在赎回之前拿它与
|
|
@@ -362,7 +362,12 @@ export interface ToolApprovalFrame {
|
|
|
362
362
|
* [ref] MED-1 后不再是判别式,core JSDoc 钉明「不是子代判别键」)。值 = 子代的 core session id
|
|
363
363
|
* (与 task_progress.taskId / bg_notification.sessionId 同值域,可关联子代行)。旧壳(< fromSubagent
|
|
364
364
|
* 接线)兜底按在场性渲染归属标仍然正确。 */
|
|
365
|
-
|
|
365
|
+
sourceSessionId?: string;
|
|
366
|
+
/** core 7.61.0:发起这一问的委派腿的 agent id(后台子代 = 注册表行 id `a…`;前台子代 = 它的会话 id)—— **在场即委派事实**(直接起跑的
|
|
367
|
+
* workflow 的 agent 带它而不带 `fromSubagent`),宿主的问缺席。消费方按它把审批归到后台行(一个键相等)。 */
|
|
368
|
+
agentId?: string;
|
|
369
|
+
/** core 7.61.0:谁问的、为什么问(`readAskReasons` 窄读;卡与运维队列行同一只读口)。结构化审批面按它渲理由行,`message` 照旧逐字给只读文本的消费方。 */
|
|
370
|
+
askReasons?: readonly import("./approval-card.js").AskReasonProjection[];
|
|
366
371
|
/** [ref] [ref]②:core 1.378 显式判别键——委派子代 gate 发起的 ask 恒带 `true`,受信 internals 事实
|
|
367
372
|
* (worker 不可自造/不可抑制)。取代 [ref] MED-1 的「在场 ∧ ≠ 宿主 sessionId」权宜判别式。 */
|
|
368
373
|
fromSubagent?: true;
|
|
@@ -418,9 +423,10 @@ export interface ToolApprovalFrame {
|
|
|
418
423
|
* 🔴 **真才带,缺席绝不编 `false`**(`governanceForced` / `requiresRealApproval` 同形)。缺席覆盖「不是强制」「老引擎」
|
|
419
424
|
* 两形。**本仓从不自铸本键**:活卡帧(与 `livePending` 行顶层,T4①)只读 `AskRequest.mandated`;耐久面(运维队列行 / inbox 行)
|
|
420
425
|
* 自 core 7.31.0 [ref] 起读 core 在 park 行上铸的孪生座(`PendingAction.tool_approval.mandated` / `CheckpointSummary.mandated`,
|
|
421
|
-
* [ref] 二段),同样只投 core 给的那一位 —— 自铸一个就是本仓成了这个事实的第二个源。⚠️ **`card_json`
|
|
422
|
-
* (`ApprovalCardSchema` 没有这一位,`.strict()`)
|
|
423
|
-
*
|
|
426
|
+
* [ref] 二段),同样只投 core 给的那一位 —— 自铸一个就是本仓成了这个事实的第二个源。⚠️ **`card_json` 的卡面不带本键**
|
|
427
|
+
* (`ApprovalCardSchema` 没有这一位,`.strict()`);7.143.0 起卡信封旁的活面事实座(`liveFacts`)存着呈卡帧上同一位(同一只帧对象挑出,不是自铸)
|
|
428
|
+
* ⇒ 断连重放的 `approval_request` 帧与活铸帧同值;本版之前铸的行没有那一座 ⇒ 重放帧带 `liveFactsUnknown`(8D-6:此前这里写的
|
|
429
|
+
* 「`card_json` 只读 `AskRequest.mandated`」是错句,T4② 车OC 改真)。
|
|
424
430
|
* 🔴 **server 不判「是不是强制」**(判定属主在 core 的闸站),只**读**闸站盖好的这一位 —— 读者恰一个:
|
|
425
431
|
* [ref] 起的会话级放行判据 {@link standingAnswerHome}(会话授权是**上一次**应答记下的站着的答案,
|
|
426
432
|
* 不是对这一次调用的应答 ⇒ 强制卡上既不被既有 grant 代答、也不铸 grant)。上一段「一揽子 `onAsk:"allow"`
|
|
@@ -481,7 +487,7 @@ export interface ToolApprovalFrame {
|
|
|
481
487
|
* `{ kind: "extension", name }`,卡上「扩展 X 想跑 …」那一行的出处。模型消息带来的调用上缺席。display 事实,不是裁决输入。
|
|
482
488
|
* 读法与 `tool_start` / `tool_end` 上的同名键是同一只(`trace/extension-call-face.ts`:注册名过注册方文本的出口纪律,与 `wiring_manifest.mods[]` 的 `name`
|
|
483
489
|
* 逐字节同;形不对 ⇒ 丢 + 计一次)。呈卡腿上它是 `approval_request` 顶层的卡外座之一(`APPROVAL_REQUEST_LIVE_FACT_KEYS`,同一只帧对象的值);
|
|
484
|
-
* ⚠️ `card_json` 卡面不带本键(卡的键集属主在契约包)
|
|
490
|
+
* ⚠️ `card_json` 卡面不带本键(卡的键集属主在契约包);7.143.0 起卡信封的活面事实座同存一份 ⇒ 断连重放帧与活铸帧同值(与其余卡外座同)。
|
|
485
491
|
*/
|
|
486
492
|
requestedBy?: ExtensionRequesterFace;
|
|
487
493
|
/**
|
|
@@ -540,9 +546,11 @@ export interface ToolApprovalFrame {
|
|
|
540
546
|
* 把提议的根放回读边界又走了一遍才递出来,下游再判一遍就是同一事实的第二个判官(与 `origin` /
|
|
541
547
|
* `denialLimitFallback` 两条顶注的同一条禁令)。
|
|
542
548
|
*
|
|
543
|
-
* 🔴
|
|
544
|
-
* 一只 PARKED 的根外读 ask
|
|
545
|
-
* 自铸一个(自铸 = 同一事实的第二个源,而且那个源会在 park 兑现时说谎)
|
|
549
|
+
* 🔴 **停驻面没有孪生**:core 的负控逐字写着「the durable park row has no twin of this seat in this version」——
|
|
550
|
+
* 一只 PARKED 的根外读 ask 渲的仍是单独那张确认卡。所以停驻行 / 运维队列行 / inbox 行**没有**这一座,本仓也不
|
|
551
|
+
* 自铸一个(自铸 = 同一事实的第二个源,而且那个源会在 park 兑现时说谎)。问行卡信封的活面事实座(7.143.0)不是自铸:
|
|
552
|
+
* 它是呈卡帧上这一格的同一份值、同一条写落下,只供同一只还在流上的问的重放帧读(断流续读 / 开流 preamble),
|
|
553
|
+
* 射程与卡上 `ruleOffers` 同一句(回授经重放帧自己的 `approvalId` 走活应答口)。
|
|
546
554
|
*/
|
|
547
555
|
readRootCandidate?: ReadRootGrantCandidate;
|
|
548
556
|
/**
|
|
@@ -689,7 +697,8 @@ export interface ToolApprovalFrame {
|
|
|
689
697
|
*
|
|
690
698
|
* 🔴 **在场才带**(缺席绝不编空串;缺席 ≠「没有原因」);窄读单点 = `approval-card.ts` 的 `readProbeReason`
|
|
691
699
|
* (非串 / 空白 ⇒ 缺席;超信封 ⇒ **整只丢不截**;内容族 ⇒ 脱敏,与耐久面同一规则 ⇒ 对同一句话两面同值)。
|
|
692
|
-
* 🔴
|
|
700
|
+
* 🔴 **不在卡上**:`ApprovalCardSchema`(`.strict()`)没有它;呈卡帧 `approval_request` 顶层带它(活面事实座),7.143.0 起卡信封的
|
|
701
|
+
* `liveFacts` 座同存一份 ⇒ 断连重放帧与活铸帧同值。
|
|
693
702
|
* 🔴 **展示 / 分诊元数据,永不是裁决输入**;永不进 `message`(那是分类器 / 模型的输入面)。
|
|
694
703
|
* `\p{Cf}` 展示重排类字符(方向 / 零宽标记):core 在这个座上**不剥**(同值契约下 core 自己披露的残余,[ref]);本仓脱敏器
|
|
695
704
|
* (`redactSecrets`)入口剥全部 `\p{Cf}`(7.70.0 起),活卡帧与耐久面**都过它** ⇒ 两面同值、且都是剥后字节(`test/approval-probe-reason-wire.test.ts` 钉)。
|
|
@@ -767,23 +776,30 @@ export interface LivePendingRow {
|
|
|
767
776
|
requiresRealApproval?: true;
|
|
768
777
|
governanceForced?: true;
|
|
769
778
|
/** T4①(八病审计 8D-5,车OC / 7.101.0):强制位([ref],`AskRequest.mandated`)—— 与上两位**同层同形**(真才带,缺席不编 false),
|
|
770
|
-
* 值 =
|
|
771
|
-
* `frame` 里:同一个 `GET /v1/approvals` 响应的 durable `pending[]`
|
|
779
|
+
* 值 = 内嵌帧 {@link frame} 上的同名键(同一个值,不另读;7.143.0 起):活登记 = 这只问的活铸帧;接管登记 = 从问行卡信封回读的重放帧
|
|
780
|
+
* (行上记着才在,存量行缺席并带 {@link liveFactsUnknown})。此前只在 `frame` 里:同一个 `GET /v1/approvals` 响应的 durable `pending[]` 行顶层
|
|
781
|
+
* 带它([ref] 二段),live 行却要进帧里读。 */
|
|
772
782
|
mandated?: true;
|
|
773
783
|
/** 7.116.0(审计修复批 S4):这张卡上的「本会话放行」不会被记住 —— 与 {@link ToolApprovalFrame.rememberRefused} 同名同义同源
|
|
774
784
|
* (同一只判据,读条目上的四位事实);真才带。 */
|
|
775
785
|
rememberRefused?: true;
|
|
776
|
-
/** [ref](core 7.32.0 [ref]):强制位站在哪一个词上 —— 与 `mandated` 同层同形(在场逐字,缺席不编词),值 =
|
|
777
|
-
* (
|
|
786
|
+
/** [ref](core 7.32.0 [ref]):强制位站在哪一个词上 —— 与 `mandated` 同层同形(在场逐字,缺席不编词),值 = 内嵌帧 {@link frame} 上的同名键
|
|
787
|
+
* (读法同 `mandated`;帧型该键顶注是全文)。 */
|
|
778
788
|
mandate?: PersistedRuleMandate;
|
|
779
789
|
/** [ref](cli [ref] / [ref]):ask 的**出身词**(谁提的这一问,core `ASK_ORIGINS` 闭集一词)—— 与 `mandate` 同层同形(在场逐字,
|
|
780
|
-
* 缺席不编词),值 =
|
|
790
|
+
* 缺席不编词),值 = 内嵌帧 {@link frame} 上的同名键(读法同 `mandated`;帧型该键顶注是全文)。同一个
|
|
781
791
|
* `GET /v1/approvals` 响应里 durable `pending[]` 行的 `origin` 也在顶层(park 行孪生座),两族行同一种读法。 */
|
|
782
792
|
origin?: string;
|
|
793
|
+
/**
|
|
794
|
+
* 7.143.0:**这一行的活面事实不在问行上** —— 与内嵌帧 {@link frame} 上的同名标记位同值(`ApprovalRequestFrame.liveFactsUnknown`,只读那一格)。
|
|
795
|
+
* 只有接管登记会带(行是本版之前铸的,卡信封上没有活面事实座;或那一座读不出):这时顶层的 `mandated` / `mandate` / `origin` 缺席的意思是「不知道」,
|
|
796
|
+
* 不是「不强制 / 没有出身」—— 消费方按不知道读(强制与否不知道 ⇒ 按强制)。活登记恒不带(活铸帧上恒有事实);只记真。
|
|
797
|
+
*/
|
|
798
|
+
liveFactsUnknown?: true;
|
|
783
799
|
/** 发起者为委派子代(originTaskId 在场)。 */
|
|
784
800
|
fromSubagent?: true;
|
|
785
801
|
/** [ref] C2(additive):委派子代的 **canonical taskId**。值域精确成文(codex R1-F3 问询后按 core dist
|
|
786
|
-
* 亲证):值 = `AskRequest.
|
|
802
|
+
* 亲证):值 = `AskRequest.sourceSessionId` = 发起 task 的 sessionId(core prepare-task `askSourceIdentity`);
|
|
787
803
|
* 而 core 的 canonical taskId = `spec.taskId ?? sessionId`(runtask.js `runSourceTaskId`),Runner 铸的
|
|
788
804
|
* 委派子代 spec **不带** taskId ⇒ 子代 canonical taskId ≡ 子代 sessionId ≡ 本键 ≡
|
|
789
805
|
* `task_progress.taskId`(同一 `runSourceTaskId` 铸)—— 关联 join 在本键存在的唯一面(`fromSubagent`
|
|
@@ -878,7 +894,7 @@ interface ToolApprovalRunContextBase {
|
|
|
878
894
|
abortSignal?: AbortSignal;
|
|
879
895
|
/** [ref]([ref] §3.1 askId 派生的腿轴;车3 刀 3a 换轴:原 `leg?: number` → `legKey?: string`)。
|
|
880
896
|
* = `sha256(resume checkpoint token)` 的 hex,**首腿缺席折空串**(空串是首腿的真值,不是「未知」)。
|
|
881
|
-
* 与 `ToolApprovalRunContext.taskId`(= 派生里的 `runId` 轴)一起,使同一 `(
|
|
897
|
+
* 与 `ToolApprovalRunContext.taskId`(= 派生里的 `runId` 轴)一起,使同一 `(sourceSessionId, toolCallId)`
|
|
882
898
|
* 在不同 run / 不同 resume 腿下铸出不同持久行(不会被上一腿或上一 run 已终结的行绊住)。
|
|
883
899
|
* 换轴动机与残留边界见 `approval-ask-machine.ts` 的 `deriveAskId` 头注。
|
|
884
900
|
* 真值由装配点(刀 3b)供给,本刀只立形 + 折空串兜底。 */
|
|
@@ -981,7 +997,7 @@ type ParsedToolApproval = {
|
|
|
981
997
|
updatedInput?: unknown;
|
|
982
998
|
persistRule?: ParsedPersistRule;
|
|
983
999
|
note?: string;
|
|
984
|
-
|
|
1000
|
+
decider: ApprovalDecider;
|
|
985
1001
|
readRootGrant?: string;
|
|
986
1002
|
};
|
|
987
1003
|
/**
|
|
@@ -1274,7 +1290,7 @@ export declare function approvalPreambleReplays(input: Omit<ApprovalLegInput, "n
|
|
|
1274
1290
|
* 从定义上不是「投递面拿走了它」)。{@link ToolApprovalCoordinator.notifyExternalDecision} 收的就是它。 */
|
|
1275
1291
|
export type DecidedAskOutcome = Exclude<AskOutcome, "unavailable">;
|
|
1276
1292
|
/** 铸点的入参形 = 行上与**这条决议本身**有关的三格。整行(`AskRow`)与 claim 败方读数都满足。 */
|
|
1277
|
-
type DecidedRowFacts = Pick<AskRow, "decision" | "settledBy"> & {
|
|
1293
|
+
type DecidedRowFacts = Pick<AskRow, "decision" | "settledBy" | "decidedVia"> & {
|
|
1278
1294
|
updatedInput?: unknown;
|
|
1279
1295
|
};
|
|
1280
1296
|
/**
|
|
@@ -1326,11 +1342,11 @@ export declare class ToolApprovalCoordinator {
|
|
|
1326
1342
|
/** [ref] 车2(codex 交叉复审 round3 抓获真 finding,round5 精化成 Set):次级索引,键 = 持久层 askId
|
|
1327
1343
|
* (与 {@link pending} 的 wire-面 uuidv7 `id` 是两条独立的身份轴,顶注同精神)——只在 askStore 在场且
|
|
1328
1344
|
* 这只 ask 真有 askId 时才登记。**同一 askId 下可能同时挂着不止一条本地条目**(round5 抓获:
|
|
1329
|
-
* `ensureAsk` 是幂等 upsert,若 core 对同一 (
|
|
1345
|
+
* `ensureAsk` 是幂等 upsert,若 core 对同一 (sourceSessionId,runId,toolCallId,legKey) 真发起过两次并发调用——如
|
|
1330
1346
|
* 重试/failover 场景,round4 finding2 的顶注同源——两次 `askBroadcast` 各自的调用栈都会在行仍是
|
|
1331
1347
|
* STREAM_PENDING 时各自注册一条独立的本地 pending 条目,值形若是单值 Map 会被后到者覆盖前者的登记,
|
|
1332
1348
|
* 前者从此再也没有任何本地事件会驱动它 settle),故值形是 `Set`,不是单个 `PendingApproval`。
|
|
1333
|
-
* 存在理由(两类真实成因共用同一套修复):①同一批(相同
|
|
1349
|
+
* 存在理由(两类真实成因共用同一套修复):①同一批(相同 sourceSessionId+leg)下若有多只**不同** ask 并发
|
|
1334
1350
|
* 在飞(不同 toolCallId,同一 batchId),`expireAsk` 赢家的同一次持久事务会把批内其余 STREAM_PENDING
|
|
1335
1351
|
* 兄弟原子撤成 VOID 并把它们的 askId 列在 `voidedSiblings` 里;②同一 askId 的**重复本地注册**(见上)。
|
|
1336
1352
|
* 两类情形下,那些"没赢"的本地条目各自独立的 timer/settle 闭包都对"这只 askId 其实已经有了终局"一无
|
|
@@ -2241,8 +2257,8 @@ export declare class ToolApprovalCoordinator {
|
|
|
2241
2257
|
adoptOpenAsks(): Promise<OpenAskAdoption>;
|
|
2242
2258
|
/**
|
|
2243
2259
|
* [ref]:由一条待决行铸一条接管登记并放进活集合(唯一铸点;读法见 {@link AdoptedRegistrationPart})。事实全部取自行与行上的卡:属主 / 会话(adhoc 替身
|
|
2244
|
-
* = taskId 时不投,与按问读口的行投影同读)/ 子代出身(卡 `fromSubagent` ⇒ 行 `
|
|
2245
|
-
*
|
|
2260
|
+
* = taskId 时不投,与按问读口的行投影同读)/ 子代出身(卡 `fromSubagent` ⇒ 行 `sourceSessionId`)/ 窗死线 / 铸造时刻取行;工具名、要人位、治理位、类集取卡;
|
|
2261
|
+
* 强制位 / 强制词 / 出身词取重放帧顶层(= 信封事实座,7.143.0;存量行缺席);授予绑定按 `unreadable` 读(于是站着的答案判据答 `none`:`rememberRefused`,`allow_session` 只放行这一次 —— 既有律);规则素材不在 ⇒ `persistRule`
|
|
2246
2262
|
* 答 `rule_lane_unavailable`(晚答腿同一个词)。卡面的 `rememberRefused` 与条目同一只判据(活登记那一处的同一条纪律)。
|
|
2247
2263
|
*/
|
|
2248
2264
|
private registerAdopted;
|
|
@@ -2262,11 +2278,13 @@ export declare class ToolApprovalCoordinator {
|
|
|
2262
2278
|
* [ref]:某只委派子代此刻有没有**待决**的活卡 —— fleet 对账腿「子代活性由属主说了算」的属主②读口(另一只是
|
|
2263
2279
|
* bg registry 账)。子代卡在一张没人答的卡上时当然不出帧,只看「静默」就会把它当孤儿扫下面板(报案的真形)。
|
|
2264
2280
|
* 只答是非、不交出 Map(与 `isRunLiveOnThisReplica` 同姿势);纯读,零锁零结算语义。
|
|
2265
|
-
*
|
|
2266
|
-
*
|
|
2267
|
-
*
|
|
2281
|
+
* 入参 = 一条腿的名字(fleet 行 → 名字的换算在 `FleetEventBus.childOwnerKeys`);活卡帧上带着发起腿的名字:`agentId`(core 7.61.0:
|
|
2282
|
+
* 委派腿的腿 task id —— 后台子代 = 它的注册表行 id;前台子代 = 它的会话 id;workflow agent = 脚本声明的 task id,否则会话 id;在场即委派事实,
|
|
2283
|
+
* 直接起跑的 workflow 的 agent 带它而不带 `fromSubagent`;宿主的问缺席),委派子代的问另带发起会话 `sourceSessionId`(帧上只出委派子代的问)。
|
|
2284
|
+
* 任一个落在入参里 ⇒ 这一问是那条腿的。只看本副本的内存登记:子代跑在本副本,它的活卡就登记在本副本;耐久 park 的卡由 bg registry 的
|
|
2285
|
+
* `parked` 态作保(见 fleet-reconciler.ts `bgAgentVouches`)。
|
|
2268
2286
|
*/
|
|
2269
|
-
|
|
2287
|
+
hasLivePendingFromLeg(names: readonly string[]): boolean;
|
|
2270
2288
|
/**
|
|
2271
2289
|
* 🔴 [ref](案A)追记 F4 —— **跨副本决议的执行通知**(悬挂行的一次终态轮询)。
|
|
2272
2290
|
*
|
package/dist/tool-approval.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readApprovalCard } from "./approval-content-kind.js";
|
|
2
|
-
import { heldAskOf,
|
|
2
|
+
import { heldAskOf, liveHostSource, readDecider, retiredDecisionKeyFacts, POLICY_CANNOT_ALLOW_PERSON_ASK } from "./host-decision.js";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
import { uuidv7, classifyAsk, foldArbitrationRow, policyCannotAnswer, screenAskClassMembers, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, parseRuleText, pathConfinableWriteToolNames } from "@sema-agent/core";
|
|
5
5
|
import { precheckCardRuleText } from "./rules-consent.js";
|
|
@@ -12,14 +12,14 @@ import { createLogger } from "./observability/logger.js";
|
|
|
12
12
|
import { errorKindOf } from "./observability/err-text.js";
|
|
13
13
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
14
14
|
import { ownerOfCheckpointScope } from "./security.js";
|
|
15
|
-
import { deriveAskId, deriveAskScopedBatchId, deriveBatchId, MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt } from "./approval-ask-machine.js";
|
|
16
|
-
import { currentParkArm, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildReplayFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readProbeReason, readReadRootCandidate, readStoredCardEnvelope, readRuleEvidence, readAllowRuleShadowed, readRuleOffersAbsence, readRuleOffersAbsenceSeat, readParkRowTrueSeat, readAskClassPair, readClosedWordSeat, buildApprovalCompleteFrame, readRuleOfferList, } from "./approval-card.js";
|
|
15
|
+
import { deriveAskId, deriveAskScopedBatchId, deriveBatchId, MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt, readBoundInputHash } from "./approval-ask-machine.js";
|
|
16
|
+
import { currentParkArm, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, adoptStoredLiveFacts, buildApprovalRequestFrame, buildReplayFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readProbeReason, readReadRootCandidate, readStoredCardEnvelope, readRuleEvidence, readAllowRuleShadowed, readRuleOffersAbsence, readRuleOffersAbsenceSeat, readParkRowTrueSeat, readAskClassPair, readAskReasons, readClosedWordSeat, buildApprovalCompleteFrame, readRuleOfferList, } from "./approval-card.js";
|
|
17
17
|
import { askOwnerAdmits, askRowCarriesOwner, POLICY_REFUSAL_DECISION, projectAskTerminalClaimTruth } from "./plugins/approval-ask-store-sql.js";
|
|
18
18
|
import { APPROVAL_ENDING_CAUSES, SETTLE_OUTCOME, askRowEndingCause, askRowParkTrigger } from "./approval-deny-reasons.js";
|
|
19
19
|
import { settleByPolicy } from "./approval-policy-settlement.js";
|
|
20
20
|
import { governanceAskMarksFor, runWithGovernanceAskScope } from "./governance-ask-marks.js";
|
|
21
21
|
import { governanceOriginOf } from "./runtime-governance.js";
|
|
22
|
-
import { grantBindingOf } from "./standing-answer-grant.js";
|
|
22
|
+
import { agreedGrantBinding, grantBindingOf } from "./standing-answer-grant.js";
|
|
23
23
|
import { operatorAsk } from "./operator-ask.js";
|
|
24
24
|
import { APPROVAL_EXEMPTED_EVENT } from "./plugins/approval-exemption-store.js";
|
|
25
25
|
import { refusalBody } from "./http/refusal-body.js";
|
|
@@ -47,7 +47,7 @@ export function approvalDecidePath(sessionId) {
|
|
|
47
47
|
return `/v1/approvals/${encodeURIComponent(sessionId)}/decide`;
|
|
48
48
|
}
|
|
49
49
|
function parkSessionOf(row) {
|
|
50
|
-
return row.
|
|
50
|
+
return row.sourceSessionId === row.sessionId && row.sessionId !== row.taskId ? row.sessionId : undefined;
|
|
51
51
|
}
|
|
52
52
|
function ruleMaterialCarriesCredentialShape(command) {
|
|
53
53
|
return redactSecretsWithArms(command, { observe: false }).arms.has("full");
|
|
@@ -223,10 +223,11 @@ function livePendingRowOf(e) {
|
|
|
223
223
|
...(e.sessionId !== undefined ? { sessionId: e.sessionId } : {}),
|
|
224
224
|
...(e.requiresRealApproval ? { requiresRealApproval: true } : {}),
|
|
225
225
|
...(e.governanceForced ? { governanceForced: true } : {}),
|
|
226
|
-
...(
|
|
226
|
+
...(listFrame.mandated === true ? { mandated: true } : {}),
|
|
227
227
|
...(standingAnswerHome(pendingEntryStandingAnswerFacts(e)) === "none" ? { rememberRefused: true } : {}),
|
|
228
|
-
...(
|
|
229
|
-
...(
|
|
228
|
+
...(listFrame.mandate !== undefined ? { mandate: listFrame.mandate } : {}),
|
|
229
|
+
...(listFrame.origin !== undefined ? { origin: listFrame.origin } : {}),
|
|
230
|
+
...(listFrame.type === "approval_request" && listFrame.liveFactsUnknown === true ? { liveFactsUnknown: true } : {}),
|
|
230
231
|
...(e.originTaskId !== undefined ? { fromSubagent: true, originTaskId: e.originTaskId } : {}),
|
|
231
232
|
...(approvalCard !== undefined ? { approvalCard } : {}),
|
|
232
233
|
frame: listFrame,
|
|
@@ -294,17 +295,17 @@ function parseToolApprovalFields(body, retired) {
|
|
|
294
295
|
}
|
|
295
296
|
if (retired !== undefined)
|
|
296
297
|
return { ok: false, error: retired.error };
|
|
297
|
-
const
|
|
298
|
-
let
|
|
299
|
-
switch (
|
|
298
|
+
const deciderReading = readDecider(body, false);
|
|
299
|
+
let decider;
|
|
300
|
+
switch (deciderReading.kind) {
|
|
300
301
|
case "outside_closed_set":
|
|
301
|
-
return { ok: false, error:
|
|
302
|
+
return { ok: false, error: deciderReading.message };
|
|
302
303
|
case "accepted":
|
|
303
|
-
|
|
304
|
+
decider = deciderReading.decider;
|
|
304
305
|
break;
|
|
305
306
|
default: {
|
|
306
|
-
const unreachable =
|
|
307
|
-
throw new Error(`unhandled
|
|
307
|
+
const unreachable = deciderReading;
|
|
308
|
+
throw new Error(`unhandled decider reading: ${JSON.stringify(unreachable)}`);
|
|
308
309
|
}
|
|
309
310
|
}
|
|
310
311
|
const rawGrant = body.readRootGrant;
|
|
@@ -319,7 +320,7 @@ function parseToolApprovalFields(body, retired) {
|
|
|
319
320
|
...(d !== "deny" && u !== undefined ? { updatedInput: u } : {}),
|
|
320
321
|
...(persistRule !== undefined ? { persistRule } : {}),
|
|
321
322
|
...(note !== undefined ? { note } : {}),
|
|
322
|
-
|
|
323
|
+
decider,
|
|
323
324
|
...(readRootGrant !== undefined ? { readRootGrant } : {}),
|
|
324
325
|
};
|
|
325
326
|
}
|
|
@@ -357,12 +358,6 @@ function boundArgs(args) {
|
|
|
357
358
|
}
|
|
358
359
|
return { args: redacted, omitted: false, hasBidi };
|
|
359
360
|
}
|
|
360
|
-
function readBoundInputHash(req) {
|
|
361
|
-
if (req === null || typeof req !== "object")
|
|
362
|
-
return null;
|
|
363
|
-
const v = Reflect.get(req, "boundInputHash");
|
|
364
|
-
return typeof v === "string" && v.length > 0 ? v : null;
|
|
365
|
-
}
|
|
366
361
|
export function resolveStreamApprovalGate(input) {
|
|
367
362
|
if (!input.toolApprovalEnabled)
|
|
368
363
|
return { active: false, reason: "no_tool_approval" };
|
|
@@ -492,7 +487,7 @@ function replayTerminalAskRow(row) {
|
|
|
492
487
|
}
|
|
493
488
|
export function outcomeOfDecidedRow(row) {
|
|
494
489
|
const allow = row.decision === "approve";
|
|
495
|
-
const source = row.settledBy !== null ? { settledBy: row.settledBy } : {};
|
|
490
|
+
const source = row.settledBy !== null ? { settledBy: row.settledBy, ...(row.decidedVia !== null ? { decidedVia: row.decidedVia } : {}) } : {};
|
|
496
491
|
const edit = allow && row.updatedInput !== undefined ? { updatedInput: row.updatedInput } : {};
|
|
497
492
|
return row.settledBy === null && !("updatedInput" in edit) ? allow : { allow, ...edit, ...source };
|
|
498
493
|
}
|
|
@@ -502,7 +497,7 @@ function settleArgsOfDecided(outcome) {
|
|
|
502
497
|
return {
|
|
503
498
|
allowed: outcome.allow,
|
|
504
499
|
...(outcome.updatedInput !== undefined ? { updatedInput: outcome.updatedInput } : {}),
|
|
505
|
-
...(outcome.settledBy !== undefined ? { settledBy: outcome.settledBy } : {}),
|
|
500
|
+
...(outcome.settledBy !== undefined ? { source: { settledBy: outcome.settledBy, ...(outcome.decidedVia !== undefined ? { decidedVia: outcome.decidedVia } : {}) } } : {}),
|
|
506
501
|
};
|
|
507
502
|
}
|
|
508
503
|
function verdictOfDecided(args) {
|
|
@@ -510,7 +505,7 @@ function verdictOfDecided(args) {
|
|
|
510
505
|
by: "human",
|
|
511
506
|
allowed: args.allowed,
|
|
512
507
|
...(args.updatedInput !== undefined ? { updatedInput: args.updatedInput } : {}),
|
|
513
|
-
...(args.
|
|
508
|
+
...(args.source !== undefined ? { hostSource: args.source } : {}),
|
|
514
509
|
};
|
|
515
510
|
}
|
|
516
511
|
function settleArgsOf(outcome) {
|
|
@@ -633,8 +628,8 @@ export class ToolApprovalCoordinator {
|
|
|
633
628
|
get unattendedRoutesToPark() {
|
|
634
629
|
return this.unattendedPolicy !== "deny";
|
|
635
630
|
}
|
|
636
|
-
batchIdFor(askId,
|
|
637
|
-
return this.unattendedRoutesToPark ? deriveBatchId(
|
|
631
|
+
batchIdFor(askId, sourceSessionId, runId, legKey) {
|
|
632
|
+
return this.unattendedRoutesToPark ? deriveBatchId(sourceSessionId, runId, legKey) : deriveAskScopedBatchId(askId);
|
|
638
633
|
}
|
|
639
634
|
unattendedAskOutcome(site) {
|
|
640
635
|
const facts = {
|
|
@@ -1024,7 +1019,7 @@ export class ToolApprovalCoordinator {
|
|
|
1024
1019
|
async sessionGrantUncontestedByRow(origin, req) {
|
|
1025
1020
|
if (!this.askStore)
|
|
1026
1021
|
return true;
|
|
1027
|
-
const call = { taskId: origin.taskId, legKey: origin.legKey, toolCallId: req.toolCallId,
|
|
1022
|
+
const call = { taskId: origin.taskId, legKey: origin.legKey, toolCallId: req.toolCallId, sourceSessionId: req.sourceSessionId ?? origin.taskId };
|
|
1028
1023
|
try {
|
|
1029
1024
|
const rows = await this.withStoreDeadline(this.askStore.listByCall(call), "listByCall(session-grant-provenance)", DURABLE_CONVERGE_READ_TIMEOUT_MS);
|
|
1030
1025
|
return rows.length === 0;
|
|
@@ -1330,6 +1325,7 @@ export class ToolApprovalCoordinator {
|
|
|
1330
1325
|
const cardWord = readApprovalCard(req.approvalCard);
|
|
1331
1326
|
const originWord = typeof req.origin === "string" && req.origin.length > 0 ? req.origin : undefined;
|
|
1332
1327
|
const askClassPair = readAskClassPair(req);
|
|
1328
|
+
const askReasonsOfReq = readAskReasons(req);
|
|
1333
1329
|
const requester = extensionRequesterOf(req.requestedBy, "tool_approval");
|
|
1334
1330
|
const frame = {
|
|
1335
1331
|
type: "tool_approval",
|
|
@@ -1338,7 +1334,7 @@ export class ToolApprovalCoordinator {
|
|
|
1338
1334
|
...(typeof req.toolCallId === "string" && req.toolCallId !== "" ? { toolCallId: req.toolCallId } : {}),
|
|
1339
1335
|
...(child
|
|
1340
1336
|
? {
|
|
1341
|
-
|
|
1337
|
+
sourceSessionId: req.sourceSessionId,
|
|
1342
1338
|
fromSubagent: true,
|
|
1343
1339
|
...(typeof req.sourceAgentName === "string" ? { sourceAgentName: redactSecrets(req.sourceAgentName) } : {}),
|
|
1344
1340
|
...(req.delegation
|
|
@@ -1352,7 +1348,9 @@ export class ToolApprovalCoordinator {
|
|
|
1352
1348
|
: {}),
|
|
1353
1349
|
}
|
|
1354
1350
|
: {}),
|
|
1351
|
+
...(typeof req.agentId === "string" && req.agentId !== "" ? { agentId: req.agentId } : {}),
|
|
1355
1352
|
message: typeof req.message === "string" ? redactDeep(req.message) : "",
|
|
1353
|
+
...(askReasonsOfReq !== undefined ? { askReasons: askReasonsOfReq } : {}),
|
|
1356
1354
|
...(governanceForced ? { governanceForced: true } : {}),
|
|
1357
1355
|
...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
1358
1356
|
...(req.mandated === true ? { mandated: true } : {}),
|
|
@@ -1384,6 +1382,7 @@ export class ToolApprovalCoordinator {
|
|
|
1384
1382
|
const card = this.askStore ? buildApprovalCard(frame, req, req.requiresRealApproval === true) : undefined;
|
|
1385
1383
|
let cardForFrame = card;
|
|
1386
1384
|
let persistedExpiresAtMs = expiresAtMs;
|
|
1385
|
+
let factsOfRecord;
|
|
1387
1386
|
let entryExecutionLane = origin.executionLane;
|
|
1388
1387
|
let lateEnsuredRow;
|
|
1389
1388
|
let lateTerminalRow;
|
|
@@ -1412,16 +1411,16 @@ export class ToolApprovalCoordinator {
|
|
|
1412
1411
|
: replayed;
|
|
1413
1412
|
};
|
|
1414
1413
|
if (this.askStore && card) {
|
|
1415
|
-
const
|
|
1414
|
+
const sourceSessionId = req.sourceSessionId ?? origin.taskId;
|
|
1416
1415
|
const runId = origin.taskId;
|
|
1417
1416
|
const legKey = origin.legKey;
|
|
1418
|
-
askId = deriveAskId(
|
|
1419
|
-
batchId = this.batchIdFor(askId,
|
|
1417
|
+
askId = deriveAskId(sourceSessionId, runId, legKey, req);
|
|
1418
|
+
batchId = this.batchIdFor(askId, sourceSessionId, runId, legKey);
|
|
1420
1419
|
try {
|
|
1421
1420
|
const existingOrCreated = await this.withStoreDeadline(this.askStore.ensureAsk({
|
|
1422
1421
|
askId,
|
|
1423
1422
|
taskId: origin.taskId,
|
|
1424
|
-
|
|
1423
|
+
sourceSessionId,
|
|
1425
1424
|
sessionId: origin.sessionId ?? origin.taskId,
|
|
1426
1425
|
owner: origin.owner,
|
|
1427
1426
|
executionLane: origin.executionLane,
|
|
@@ -1429,7 +1428,7 @@ export class ToolApprovalCoordinator {
|
|
|
1429
1428
|
toolCallId: req.toolCallId,
|
|
1430
1429
|
legKey,
|
|
1431
1430
|
parentToolCallId: req.delegation?.parentToolCallId ?? null,
|
|
1432
|
-
cardJson: buildApprovalCardEnvelope(askId, card),
|
|
1431
|
+
cardJson: buildApprovalCardEnvelope(askId, card, frame),
|
|
1433
1432
|
boundInputHash: readBoundInputHash(req),
|
|
1434
1433
|
...durableRuleMaterial(ruleLaneMaterial),
|
|
1435
1434
|
schemaVersion: 1,
|
|
@@ -1463,6 +1462,9 @@ export class ToolApprovalCoordinator {
|
|
|
1463
1462
|
persistedExpiresAtMs = existingOrCreated.row.expiresAtMs;
|
|
1464
1463
|
entryExecutionLane = existingOrCreated.row.executionLane;
|
|
1465
1464
|
cardForFrame = persistedEnvelope.card;
|
|
1465
|
+
factsOfRecord = existingOrCreated.inserted ? undefined : persistedEnvelope.liveFacts;
|
|
1466
|
+
if (factsOfRecord !== undefined)
|
|
1467
|
+
adoptStoredLiveFacts(frame, factsOfRecord);
|
|
1466
1468
|
if (cardForFrame.governanceForced === true)
|
|
1467
1469
|
frame.governanceForced = true;
|
|
1468
1470
|
else
|
|
@@ -1560,7 +1562,7 @@ export class ToolApprovalCoordinator {
|
|
|
1560
1562
|
if (hostSettled !== undefined || (denyReasonSettled !== undefined && denyReasonSettled !== "")) {
|
|
1561
1563
|
return {
|
|
1562
1564
|
allow: false,
|
|
1563
|
-
...
|
|
1565
|
+
...hostSettled,
|
|
1564
1566
|
...(denyReasonSettled !== undefined && denyReasonSettled !== "" ? { reason: denyReasonSettled } : {}),
|
|
1565
1567
|
};
|
|
1566
1568
|
}
|
|
@@ -1577,7 +1579,7 @@ export class ToolApprovalCoordinator {
|
|
|
1577
1579
|
return {
|
|
1578
1580
|
allow: true,
|
|
1579
1581
|
...(settled.updatedInput !== undefined ? { updatedInput: settled.updatedInput } : {}),
|
|
1580
|
-
...
|
|
1582
|
+
...hostSettled,
|
|
1581
1583
|
...(settled.readRootGrant !== undefined ? { readRootGrant: settled.readRootGrant } : {}),
|
|
1582
1584
|
};
|
|
1583
1585
|
}
|
|
@@ -1589,10 +1591,10 @@ export class ToolApprovalCoordinator {
|
|
|
1589
1591
|
done = true;
|
|
1590
1592
|
const allowed = verdict.by === "human" && verdict.allowed;
|
|
1591
1593
|
const outcome = verdict.by === "system" ? SETTLE_OUTCOME.EXPIRED : verdict.allowed ? SETTLE_OUTCOME.ALLOWED : SETTLE_OUTCOME.DENIED;
|
|
1592
|
-
const
|
|
1594
|
+
const hostSource = verdict.hostSource;
|
|
1593
1595
|
const updatedInput = verdict.by === "human" ? verdict.updatedInput : undefined;
|
|
1594
1596
|
const readRootGrant = verdict.by === "human" ? verdict.readRootGrant : undefined;
|
|
1595
|
-
hostSettled =
|
|
1597
|
+
hostSettled = hostSource;
|
|
1596
1598
|
denyReasonSettled = verdict.by === "human" && !verdict.allowed ? verdict.denyReason : undefined;
|
|
1597
1599
|
if (timer)
|
|
1598
1600
|
clearTimeout(timer);
|
|
@@ -1626,7 +1628,7 @@ export class ToolApprovalCoordinator {
|
|
|
1626
1628
|
const common = {
|
|
1627
1629
|
approvalId: wireApprovalId,
|
|
1628
1630
|
...(windowRouteUnavailable ? { parkRouted: true } : {}),
|
|
1629
|
-
...(
|
|
1631
|
+
...(hostSource !== undefined ? { settledBy: hostSource.settledBy } : {}),
|
|
1630
1632
|
settledAtMs: Date.now(),
|
|
1631
1633
|
};
|
|
1632
1634
|
return verdict.by === "system"
|
|
@@ -1638,7 +1640,7 @@ export class ToolApprovalCoordinator {
|
|
|
1638
1640
|
approvalId: wireApprovalId,
|
|
1639
1641
|
taskId: origin.taskId,
|
|
1640
1642
|
carrierLeg,
|
|
1641
|
-
executingSessionId: req.
|
|
1643
|
+
executingSessionId: req.sourceSessionId,
|
|
1642
1644
|
toolCallId: req.toolCallId,
|
|
1643
1645
|
settleRecord,
|
|
1644
1646
|
});
|
|
@@ -1792,7 +1794,7 @@ export class ToolApprovalCoordinator {
|
|
|
1792
1794
|
if (done)
|
|
1793
1795
|
return;
|
|
1794
1796
|
windowRouteUnavailable = true;
|
|
1795
|
-
settle({ by: "system", cause, ...(hostSettledBy !== undefined ? { hostSettledBy } : {}) });
|
|
1797
|
+
settle({ by: "system", cause, ...(hostSettledBy !== undefined ? { hostSource: { settledBy: hostSettledBy } } : {}) });
|
|
1796
1798
|
};
|
|
1797
1799
|
const windowExpired = (hostSelfReport, cause) => {
|
|
1798
1800
|
void (async () => {
|
|
@@ -1901,11 +1903,13 @@ export class ToolApprovalCoordinator {
|
|
|
1901
1903
|
}
|
|
1902
1904
|
const entryClasses = askClassPair?.classes;
|
|
1903
1905
|
const entryDeploymentListQuestion = carriesDeploymentListQuestion(deploymentListAsks, entryClasses);
|
|
1904
|
-
const
|
|
1906
|
+
const legGrantBinding = grantBindingOf(req);
|
|
1907
|
+
const entryGrantBinding = factsOfRecord === undefined ? legGrantBinding : agreedGrantBinding(legGrantBinding, grantBindingOf(factsOfRecord));
|
|
1908
|
+
const entryMandated = req.mandated === true || factsOfRecord?.mandated === true;
|
|
1905
1909
|
const rememberRefused = standingAnswerHome(pendingEntryStandingAnswerFacts({
|
|
1906
1910
|
...(effectiveGovernanceForced ? { governanceForced: true } : {}),
|
|
1907
1911
|
...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
1908
|
-
...(
|
|
1912
|
+
...(entryMandated ? { mandated: true } : {}),
|
|
1909
1913
|
grantBinding: entryGrantBinding,
|
|
1910
1914
|
classes: entryClasses,
|
|
1911
1915
|
...(entryDeploymentListQuestion ? { deploymentListQuestion: true } : {}),
|
|
@@ -1928,7 +1932,7 @@ export class ToolApprovalCoordinator {
|
|
|
1928
1932
|
owner: origin.owner,
|
|
1929
1933
|
...(primary ? { ctxTaskId: primary.taskId, originCtx: primary } : {}),
|
|
1930
1934
|
...(reachability === "unreached" ? { suspended: true } : {}),
|
|
1931
|
-
...(child ? { originTaskId: req.
|
|
1935
|
+
...(child ? { originTaskId: req.sourceSessionId } : primary ? { targetCtxs: new Set(aliveCtxs), onTargetGone } : {}),
|
|
1932
1936
|
...(origin.sessionId ? { sessionId: origin.sessionId } : {}),
|
|
1933
1937
|
frame,
|
|
1934
1938
|
...(cardFrame !== undefined ? { cardFrame } : {}),
|
|
@@ -1944,9 +1948,7 @@ export class ToolApprovalCoordinator {
|
|
|
1944
1948
|
...(ruleLaneMaterial !== undefined ? { ruleLane: ruleLaneMaterial } : {}),
|
|
1945
1949
|
...(effectiveGovernanceForced ? { governanceForced: true } : {}),
|
|
1946
1950
|
...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
1947
|
-
...(
|
|
1948
|
-
...(mandateWord !== undefined ? { mandate: mandateWord } : {}),
|
|
1949
|
-
...(originWord !== undefined ? { origin: originWord } : {}),
|
|
1951
|
+
...(entryMandated ? { mandated: true } : {}),
|
|
1950
1952
|
...(askId !== undefined && batchId !== undefined ? { askId, batchId } : {}),
|
|
1951
1953
|
};
|
|
1952
1954
|
selfEntry = pendingEntry;
|
|
@@ -1963,7 +1965,7 @@ export class ToolApprovalCoordinator {
|
|
|
1963
1965
|
this.askAudit?.recordAsk({
|
|
1964
1966
|
approvalId: wireApprovalId,
|
|
1965
1967
|
taskId: origin.taskId,
|
|
1966
|
-
...(req.
|
|
1968
|
+
...(req.sourceSessionId !== undefined ? { sourceSessionId: req.sourceSessionId } : {}),
|
|
1967
1969
|
...(origin.sessionId !== undefined ? { sessionId: origin.sessionId } : {}),
|
|
1968
1970
|
owner: origin.owner,
|
|
1969
1971
|
toolName: req.toolName,
|
|
@@ -2123,7 +2125,7 @@ export class ToolApprovalCoordinator {
|
|
|
2123
2125
|
const preRule = this.precheckEditedRuleBeforeDecision(entry, judgedOwner, parsed);
|
|
2124
2126
|
if (preRule !== undefined)
|
|
2125
2127
|
return preRule;
|
|
2126
|
-
if (parsed.value !== "deny" && policyCannotAnswer(heldAskOf(entry.requiresRealApproval === true), parsed.decidedBy)) {
|
|
2128
|
+
if (parsed.value !== "deny" && policyCannotAnswer(heldAskOf(entry.requiresRealApproval === true), parsed.decider.decidedBy)) {
|
|
2127
2129
|
return { status: 400, body: refusalBody({ errorCode: "request.body_shape", message: POLICY_CANNOT_ALLOW_PERSON_ASK }) };
|
|
2128
2130
|
}
|
|
2129
2131
|
const ruleEligibility = { eligible: true };
|
|
@@ -2486,7 +2488,7 @@ export class ToolApprovalCoordinator {
|
|
|
2486
2488
|
gateBoundInputHash: row.gateBoundInputHash,
|
|
2487
2489
|
decision,
|
|
2488
2490
|
...(parsed.note !== undefined ? { note: parsed.note } : {}),
|
|
2489
|
-
|
|
2491
|
+
decider: parsed.decider,
|
|
2490
2492
|
...(parsed.updatedInput !== undefined && parsed.value !== "deny" ? { updatedInput: parsed.updatedInput } : {}),
|
|
2491
2493
|
...(principal !== undefined ? { principal } : {}),
|
|
2492
2494
|
...(httpReq !== undefined ? { httpReq } : {}),
|
|
@@ -2729,7 +2731,7 @@ export class ToolApprovalCoordinator {
|
|
|
2729
2731
|
decision: parsed.value === "deny" ? "deny" : "approve",
|
|
2730
2732
|
...(parsed.note !== undefined ? { decisionNote: parsed.note } : {}),
|
|
2731
2733
|
...(parsed.value !== "deny" && parsed.updatedInput !== undefined ? { updatedInput: parsed.updatedInput } : {}),
|
|
2732
|
-
...(
|
|
2734
|
+
...liveHostSource(parsed.decider),
|
|
2733
2735
|
}), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
2734
2736
|
if (late.ok)
|
|
2735
2737
|
this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
|
|
@@ -2809,13 +2811,13 @@ export class ToolApprovalCoordinator {
|
|
|
2809
2811
|
this.allowAllSessions.add(sessionAllowKey(judgedOwner, entry.sessionId, sessionAllowCategory(entry.toolName), entry.grantBinding));
|
|
2810
2812
|
}
|
|
2811
2813
|
const allowed = parsed.value !== "deny";
|
|
2812
|
-
const settleArgs = opts?.settleOutcome !== undefined ? settleArgsOfDecided(opts.settleOutcome) : { allowed, updatedInput: parsed.updatedInput,
|
|
2814
|
+
const settleArgs = opts?.settleOutcome !== undefined ? settleArgsOfDecided(opts.settleOutcome) : { allowed, updatedInput: parsed.updatedInput, source: liveHostSource(parsed.decider) };
|
|
2813
2815
|
const readRootGrant = opts?.settleOutcome === undefined || opts.settleOutcomeIsThisRequest === true ? parsed.readRootGrant : undefined;
|
|
2814
2816
|
entry.settle({
|
|
2815
2817
|
by: "human",
|
|
2816
2818
|
allowed: settleArgs.allowed,
|
|
2817
2819
|
updatedInput: settleArgs.updatedInput,
|
|
2818
|
-
...(settleArgs.
|
|
2820
|
+
...(settleArgs.source !== undefined ? { hostSource: settleArgs.source } : {}),
|
|
2819
2821
|
...(!settleArgs.allowed && parsed.note !== undefined ? { denyReason: parsed.note } : {}),
|
|
2820
2822
|
...(readRootGrant !== undefined ? { readRootGrant } : {}),
|
|
2821
2823
|
});
|
|
@@ -2871,6 +2873,7 @@ export class ToolApprovalCoordinator {
|
|
|
2871
2873
|
const facts = {
|
|
2872
2874
|
...(card.governanceForced === true ? { governanceForced: true } : {}),
|
|
2873
2875
|
...(card.risk.requiresRealApproval ? { requiresRealApproval: true } : {}),
|
|
2876
|
+
...(replayFrame.mandated === true ? { mandated: true } : {}),
|
|
2874
2877
|
grantBinding: { kind: "unreadable" },
|
|
2875
2878
|
...(card.classes !== undefined ? { classes: card.classes } : {}),
|
|
2876
2879
|
};
|
|
@@ -2905,7 +2908,7 @@ export class ToolApprovalCoordinator {
|
|
|
2905
2908
|
owner: row.owner,
|
|
2906
2909
|
executionLane: row.executionLane,
|
|
2907
2910
|
...(row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {}),
|
|
2908
|
-
...(card.fromSubagent === true ? { originTaskId: row.
|
|
2911
|
+
...(card.fromSubagent === true ? { originTaskId: row.sourceSessionId } : {}),
|
|
2909
2912
|
toolName: card.toolName,
|
|
2910
2913
|
...facts,
|
|
2911
2914
|
approvalId: row.askId,
|
|
@@ -2962,10 +2965,16 @@ export class ToolApprovalCoordinator {
|
|
|
2962
2965
|
}
|
|
2963
2966
|
return rows;
|
|
2964
2967
|
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
+
hasLivePendingFromLeg(names) {
|
|
2969
|
+
if (names.length === 0)
|
|
2970
|
+
return false;
|
|
2971
|
+
for (const e of this.pending.values()) {
|
|
2972
|
+
if (e.adopted === true)
|
|
2973
|
+
continue;
|
|
2974
|
+
const { agentId, sourceSessionId } = e.frame;
|
|
2975
|
+
if ((agentId !== undefined && names.includes(agentId)) || (sourceSessionId !== undefined && names.includes(sourceSessionId)))
|
|
2968
2976
|
return true;
|
|
2977
|
+
}
|
|
2969
2978
|
return false;
|
|
2970
2979
|
}
|
|
2971
2980
|
async pollSuspendedDecisions() {
|