@sema-agent/server 7.148.0 → 7.150.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 +551 -9
- package/README.md +17 -2
- package/README.zh-CN.md +5 -1
- package/USAGE.md +126 -68
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +33 -33
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +66 -28
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +4 -4
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +35 -2
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +70 -60
- package/dist/capability-facts.js +45 -49
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +37 -33
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +49 -16
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +5 -5
- package/dist/http/approval-sweeps.js +5 -3
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +6 -6
- package/dist/http/claim-heartbeat.js +6 -6
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +7 -5
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +34 -15
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +246 -21
- package/dist/http/owner-access.js +186 -8
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +24 -3
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +262 -106
- package/dist/http/route-ctx.d.ts +29 -11
- package/dist/http/routes/a2a-serve.js +17 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +11 -11
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +33 -37
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +45 -37
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +136 -101
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +12 -9
- package/dist/http/server.js +35 -6
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +2 -2
- package/dist/http/submit-ctx.js +5 -5
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +13 -2
- package/dist/leg-facts.js +2 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +30 -5
- package/dist/owner-faces.js +2 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +51 -23
- package/dist/plugins/local-checkpoint-store.d.ts +8 -1
- package/dist/plugins/local-checkpoint-store.js +5 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +48 -22
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +110 -59
- package/dist/plugins/one-time-migrations.js +224 -136
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +14 -12
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +4 -8
- package/dist/plugins/remote-env-e2b.js +21 -15
- package/dist/plugins/remote-env-host.d.ts +51 -10
- package/dist/plugins/remote-env-host.js +97 -31
- package/dist/plugins/remote-env-k8s.js +7 -4
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +11 -25
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +27 -8
- package/dist/plugins/run-store-sql.js +46 -18
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
- package/dist/plugins/schema-consistency.d.ts +91 -5
- package/dist/plugins/schema-consistency.js +189 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
- package/dist/plugins/stop-then-start-sentence.js +51 -0
- package/dist/plugins/store-backend.d.ts +23 -9
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +45 -5
- package/dist/plugins/store-contracts.js +19 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +22 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +20 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +3 -3
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +4 -12
- package/dist/session-agent.js +0 -6
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
- package/dist/stores-sql/checkpoint-store-sql.js +109 -23
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +27 -10
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +14 -7
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +50 -41
- package/dist/tool-approval.js +96 -73
- package/dist/trace/engine-notice-wire.d.ts +38 -21
- package/dist/trace/engine-notice-wire.js +25 -4
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +8 -5
- package/dist/trace/project.js +11 -9
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +268 -56
- package/dist/trace/self-minted-wire.js +110 -40
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +4 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/wire-changes/server@7.150.0.json +335 -0
- package/dist/plain-string-record.js +0 -70
package/dist/tool-approval.js
CHANGED
|
@@ -37,7 +37,7 @@ const ADOPT_OPEN_ASKS_MAX = 1_000;
|
|
|
37
37
|
const EDITED_DECISION_MARK_CAP_MS = 10_000;
|
|
38
38
|
const DEFAULT_WINDOW_MARGIN_MS = 10_000;
|
|
39
39
|
const SHUTDOWN_DRAIN_POLL_MS = 50;
|
|
40
|
-
const MAX_ALLOW_SESSIONS = 4096;
|
|
40
|
+
export const MAX_ALLOW_SESSIONS = 4096;
|
|
41
41
|
const DEFAULT_ADMIT_MAX_PER_TASK = 32;
|
|
42
42
|
const DEFAULT_ADMIT_MAX_PER_OWNER = 256;
|
|
43
43
|
const DEFAULT_PARK_REDEMPTION_MAX = 2000;
|
|
@@ -115,8 +115,28 @@ const FS_WRITE_TOOLS = pathConfinableWriteToolNames();
|
|
|
115
115
|
function sessionAllowCategory(toolName) {
|
|
116
116
|
return FS_WRITE_TOOLS.has(toolName) ? "fs-write" : `tool:${toolName}`;
|
|
117
117
|
}
|
|
118
|
-
function sessionAllowKey(owner,
|
|
119
|
-
return JSON.stringify([owner, sessionId, category, binding.kind === "bound" ? binding.digest : null]);
|
|
118
|
+
function sessionAllowKey(owner, seat, category, binding) {
|
|
119
|
+
return JSON.stringify([owner, seat.sessionId, seat.incarnation, category, binding.kind === "bound" ? binding.digest : null]);
|
|
120
|
+
}
|
|
121
|
+
function sessionAllowSeatOf(leg) {
|
|
122
|
+
return leg.sessionId && leg.incarnation ? { sessionId: leg.sessionId, incarnation: leg.incarnation } : undefined;
|
|
123
|
+
}
|
|
124
|
+
function liveSessionAnswer(facts, leg) {
|
|
125
|
+
const home = standingAnswerHome(facts);
|
|
126
|
+
switch (home) {
|
|
127
|
+
case "none":
|
|
128
|
+
return { home: "none", occupantUnreadable: false };
|
|
129
|
+
case "seat": {
|
|
130
|
+
const seat = sessionAllowSeatOf(leg);
|
|
131
|
+
return seat !== undefined ? { home: "seat", seat } : { home: "none", occupantUnreadable: Boolean(leg.sessionId) };
|
|
132
|
+
}
|
|
133
|
+
case "server_store":
|
|
134
|
+
return leg.sessionId ? { home: "server_store", sessionId: leg.sessionId } : { home: "none", occupantUnreadable: false };
|
|
135
|
+
default: {
|
|
136
|
+
const unhandled = home;
|
|
137
|
+
throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
120
140
|
}
|
|
121
141
|
function askStandingAnswerFacts(req, governanceForced, deploymentListAsks) {
|
|
122
142
|
const classes = screenAskClassMembers(req.askClass, req.classes)?.classes;
|
|
@@ -194,8 +214,8 @@ function pendingEntryStandingAnswerFacts(entry) {
|
|
|
194
214
|
deploymentListQuestion: entry.deploymentListQuestion === true,
|
|
195
215
|
};
|
|
196
216
|
}
|
|
197
|
-
function projectDecisionFacts(facts, frame, card) {
|
|
198
|
-
const rememberRefused =
|
|
217
|
+
function projectDecisionFacts(facts, leg, frame, card) {
|
|
218
|
+
const rememberRefused = liveSessionAnswer(facts, leg).home === "none";
|
|
199
219
|
if (frame !== undefined) {
|
|
200
220
|
if (facts.requiresRealApproval)
|
|
201
221
|
frame.requiresRealApproval = true;
|
|
@@ -227,9 +247,6 @@ function mandatedFromSeat(seat) {
|
|
|
227
247
|
return false;
|
|
228
248
|
}
|
|
229
249
|
}
|
|
230
|
-
function rowOrUnknown(read) {
|
|
231
|
-
return read.kind === "row" ? read.row : null;
|
|
232
|
-
}
|
|
233
250
|
function askRowVisibleTo(row, principal) {
|
|
234
251
|
return row !== null && askOwnerAdmitsAnswer(row.owner, principal);
|
|
235
252
|
}
|
|
@@ -257,7 +274,7 @@ function livePendingRowOf(e) {
|
|
|
257
274
|
...(e.requiresRealApproval ? { requiresRealApproval: true } : {}),
|
|
258
275
|
...(e.governanceForced ? { governanceForced: true } : {}),
|
|
259
276
|
...(listFrame.mandated === true ? { mandated: true } : {}),
|
|
260
|
-
...(
|
|
277
|
+
...(liveSessionAnswer(pendingEntryStandingAnswerFacts(e), e).home === "none" ? { rememberRefused: true } : {}),
|
|
261
278
|
...(listFrame.mandate !== undefined ? { mandate: listFrame.mandate } : {}),
|
|
262
279
|
...(listFrame.origin !== undefined ? { origin: listFrame.origin } : {}),
|
|
263
280
|
...(listFrame.type === "approval_request" && listFrame.liveFactsUnknown === true ? { liveFactsUnknown: true } : {}),
|
|
@@ -960,7 +977,8 @@ export class ToolApprovalCoordinator {
|
|
|
960
977
|
const sessionId = origin.sessionId;
|
|
961
978
|
if (!sessionId)
|
|
962
979
|
return false;
|
|
963
|
-
const
|
|
980
|
+
const seat = sessionAllowSeatOf(origin);
|
|
981
|
+
const live = seat !== undefined && this.allowAllSessions.has(sessionAllowKey(origin.owner, seat, sessionAllowCategory(req.toolName), facts.grantBinding));
|
|
964
982
|
const durable = !live && facts.grantBinding.kind === "none" && (await this.durableGrantHas(sessionId, req.toolName));
|
|
965
983
|
if (!live && !durable)
|
|
966
984
|
return false;
|
|
@@ -984,7 +1002,14 @@ export class ToolApprovalCoordinator {
|
|
|
984
1002
|
}
|
|
985
1003
|
boundUnattendedAsk = (identity, why) => {
|
|
986
1004
|
return async (req) => {
|
|
987
|
-
const origin = {
|
|
1005
|
+
const origin = {
|
|
1006
|
+
owner: identity.owner,
|
|
1007
|
+
taskId: identity.taskId,
|
|
1008
|
+
...(identity.sessionId !== undefined ? { sessionId: identity.sessionId } : {}),
|
|
1009
|
+
legKey: "",
|
|
1010
|
+
executionLane: identity.executionLane,
|
|
1011
|
+
...(identity.incarnation !== undefined ? { incarnation: identity.incarnation } : {}),
|
|
1012
|
+
};
|
|
988
1013
|
if (await this.standingGrantSettles(origin, req, this.governanceForcedOf(origin, req)))
|
|
989
1014
|
return true;
|
|
990
1015
|
return this.unattendedAskOutcome({ ...why, taskId: identity.taskId, owner: identity.owner, toolName: req.toolName });
|
|
@@ -1230,6 +1255,7 @@ export class ToolApprovalCoordinator {
|
|
|
1230
1255
|
...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}),
|
|
1231
1256
|
legKey: ctx.legKey ?? "",
|
|
1232
1257
|
executionLane: ctx.executionLane,
|
|
1258
|
+
...(ctx.incarnation !== undefined ? { incarnation: ctx.incarnation } : {}),
|
|
1233
1259
|
...(ctx.legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic: ctx.legDeadlineMonotonic } : {}),
|
|
1234
1260
|
}, [ctx], req, signal);
|
|
1235
1261
|
};
|
|
@@ -1243,6 +1269,7 @@ export class ToolApprovalCoordinator {
|
|
|
1243
1269
|
...(identity.sessionId !== undefined ? { sessionId: identity.sessionId } : {}),
|
|
1244
1270
|
legKey: identity.legKey ?? "",
|
|
1245
1271
|
executionLane: identity.executionLane,
|
|
1272
|
+
...(identity.incarnation !== undefined ? { incarnation: identity.incarnation } : {}),
|
|
1246
1273
|
...(identity.legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic: identity.legDeadlineMonotonic } : {}),
|
|
1247
1274
|
}, live, req, signal);
|
|
1248
1275
|
};
|
|
@@ -1321,7 +1348,7 @@ export class ToolApprovalCoordinator {
|
|
|
1321
1348
|
...(askReasonsOfReq !== undefined ? { askReasons: askReasonsOfReq } : {}),
|
|
1322
1349
|
...(governanceForced ? { governanceForced: true } : {}),
|
|
1323
1350
|
...(req.mandated === true ? { mandated: true } : {}),
|
|
1324
|
-
...(
|
|
1351
|
+
...(liveSessionAnswer(askStandingAnswerFacts(req, governanceForced, deploymentListAsks), origin).home === "none" ? { rememberRefused: true } : {}),
|
|
1325
1352
|
...(typeof req.boundGrantDigest === "string" ? { boundGrantDigest: req.boundGrantDigest, ...(req.boundGrants !== undefined ? { boundGrants: req.boundGrants } : {}) } : {}),
|
|
1326
1353
|
...(noRulingCause !== undefined ? { classifierNoRuling: noRulingCause } : {}),
|
|
1327
1354
|
...(grantAbsence !== undefined ? { boundGrantAbsence: grantAbsence } : {}),
|
|
@@ -1888,7 +1915,7 @@ export class ToolApprovalCoordinator {
|
|
|
1888
1915
|
grantBinding: entryGrantBinding,
|
|
1889
1916
|
classes: entryClasses,
|
|
1890
1917
|
...(entryDeploymentListQuestion ? { deploymentListQuestion: true } : {}),
|
|
1891
|
-
}), frame, cardForFrame);
|
|
1918
|
+
}), origin, frame, cardForFrame);
|
|
1892
1919
|
const cardFrame = askId !== undefined && cardForFrame !== undefined
|
|
1893
1920
|
? buildApprovalRequestFrame({ askId, taskId: origin.taskId, approvalId: wireApprovalId, card: cardForFrame, expiresAtMs: persistedExpiresAtMs, nowMs: Date.now(), live: frame })
|
|
1894
1921
|
: undefined;
|
|
@@ -1902,6 +1929,7 @@ export class ToolApprovalCoordinator {
|
|
|
1902
1929
|
...(reachability === "unreached" ? { suspended: true } : {}),
|
|
1903
1930
|
...(child ? { originTaskId: req.sourceSessionId } : primary ? { targetCtxs: new Set(aliveCtxs), onTargetGone } : {}),
|
|
1904
1931
|
...(origin.sessionId ? { sessionId: origin.sessionId } : {}),
|
|
1932
|
+
...(origin.incarnation !== undefined ? { incarnation: origin.incarnation } : {}),
|
|
1905
1933
|
frame,
|
|
1906
1934
|
...(cardFrame !== undefined ? { cardFrame } : {}),
|
|
1907
1935
|
approvalId: wireApprovalId,
|
|
@@ -1934,7 +1962,7 @@ export class ToolApprovalCoordinator {
|
|
|
1934
1962
|
if (s.requiresRealApproval === true)
|
|
1935
1963
|
continue;
|
|
1936
1964
|
s.requiresRealApproval = true;
|
|
1937
|
-
const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s.frame, s.cardFrame?.card);
|
|
1965
|
+
const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s, s.frame, s.cardFrame?.card);
|
|
1938
1966
|
if (s.cardFrame !== undefined && card !== undefined && card !== s.cardFrame.card)
|
|
1939
1967
|
s.cardFrame = { ...s.cardFrame, card };
|
|
1940
1968
|
}
|
|
@@ -2058,10 +2086,7 @@ export class ToolApprovalCoordinator {
|
|
|
2058
2086
|
const store = this.askStore;
|
|
2059
2087
|
if (!store)
|
|
2060
2088
|
return this.askNotVisible();
|
|
2061
|
-
const
|
|
2062
|
-
const row = rowOrUnknown(await this.askRowFor(store, id, "getAsk(respond-by-row)"));
|
|
2063
|
-
if (row?.state === "STREAM_PENDING")
|
|
2064
|
-
this.followRowOwner(row.askId, row.owner, readSeq);
|
|
2089
|
+
const row = await this.askRowFollowingOwner(store, id, "getAsk(respond-by-row)");
|
|
2065
2090
|
if (!askRowVisibleTo(row, principal))
|
|
2066
2091
|
return this.askNotVisible();
|
|
2067
2092
|
if (row.state !== "STREAM_PENDING")
|
|
@@ -2090,11 +2115,10 @@ export class ToolApprovalCoordinator {
|
|
|
2090
2115
|
}
|
|
2091
2116
|
recordDeploymentListAnswer(decided, entry, judgedOwner, parsed, principal, eligibility) {
|
|
2092
2117
|
const store = this.sessionGrants;
|
|
2093
|
-
const
|
|
2094
|
-
if (parsed.value !== "allow_session" ||
|
|
2095
|
-
return decided;
|
|
2096
|
-
if (standingAnswerHome(pendingEntryStandingAnswerFacts(entry)) !== "server_store")
|
|
2118
|
+
const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
|
|
2119
|
+
if (parsed.value !== "allow_session" || answer.home !== "server_store" || store === undefined)
|
|
2097
2120
|
return decided;
|
|
2121
|
+
const sessionId = answer.sessionId;
|
|
2098
2122
|
return (async () => {
|
|
2099
2123
|
const result = await decided;
|
|
2100
2124
|
if (result.status !== 200)
|
|
@@ -2175,17 +2199,7 @@ export class ToolApprovalCoordinator {
|
|
|
2175
2199
|
const store = this.askStore;
|
|
2176
2200
|
if (!store)
|
|
2177
2201
|
return this.askNotVisible();
|
|
2178
|
-
const
|
|
2179
|
-
const read = await this.askRowFor(store, id, "getAsk(read-by-row)");
|
|
2180
|
-
if (read.kind === "unreadable") {
|
|
2181
|
-
if (entry.adopted === true || !askOwnerAdmitsAnswer(entry.owner, principal))
|
|
2182
|
-
return this.askNotVisible();
|
|
2183
|
-
const body = { state: "pending", ...livePendingRowOf(entry) };
|
|
2184
|
-
return { status: 200, body };
|
|
2185
|
-
}
|
|
2186
|
-
const row = rowOrUnknown(read);
|
|
2187
|
-
if (row?.state === "STREAM_PENDING")
|
|
2188
|
-
this.followRowOwner(row.askId, row.owner, readSeq);
|
|
2202
|
+
const row = await this.askRowFollowingOwner(store, id, "getAsk(read-by-row)");
|
|
2189
2203
|
if (askRowVisibleTo(row, principal) && row.state === "STREAM_PENDING") {
|
|
2190
2204
|
const body = { state: "pending", ...livePendingRowOf(entry) };
|
|
2191
2205
|
return { status: 200, body };
|
|
@@ -2193,7 +2207,7 @@ export class ToolApprovalCoordinator {
|
|
|
2193
2207
|
return this.readStateOfRow(row, principal);
|
|
2194
2208
|
}
|
|
2195
2209
|
async readAskRowState(store, id, principal) {
|
|
2196
|
-
return this.readStateOfRow(
|
|
2210
|
+
return this.readStateOfRow(await this.askRowFor(store, id, "getAsk(read)"), principal);
|
|
2197
2211
|
}
|
|
2198
2212
|
async readParkedGate(row) {
|
|
2199
2213
|
const gate = this.parkedGate;
|
|
@@ -2350,18 +2364,24 @@ export class ToolApprovalCoordinator {
|
|
|
2350
2364
|
return undefined;
|
|
2351
2365
|
}
|
|
2352
2366
|
async dispatchLateByRow(store, id, parsed, httpReq, principal) {
|
|
2353
|
-
return this.dispatchRowTruth(
|
|
2367
|
+
return this.dispatchRowTruth(await this.askRowFor(store, id, "getAsk(respond-late)"), id, parsed, httpReq, principal);
|
|
2354
2368
|
}
|
|
2355
2369
|
async askRowFor(store, id, label) {
|
|
2356
2370
|
try {
|
|
2357
|
-
|
|
2358
|
-
return row === null ? { kind: "absent" } : { kind: "row", row };
|
|
2371
|
+
return await this.withStoreDeadline(store.getAsk(id), label, DURABLE_CONVERGE_READ_TIMEOUT_MS);
|
|
2359
2372
|
}
|
|
2360
2373
|
catch (err) {
|
|
2361
2374
|
this.noteStoreError(err, label);
|
|
2362
|
-
return
|
|
2375
|
+
return null;
|
|
2363
2376
|
}
|
|
2364
2377
|
}
|
|
2378
|
+
async askRowFollowingOwner(store, id, label) {
|
|
2379
|
+
const readSeq = this.nextRowReadSeq();
|
|
2380
|
+
const row = await this.askRowFor(store, id, label);
|
|
2381
|
+
if (row?.state === "STREAM_PENDING")
|
|
2382
|
+
this.followRowOwner(row.askId, row.owner, readSeq);
|
|
2383
|
+
return row;
|
|
2384
|
+
}
|
|
2365
2385
|
async dispatchRowTruth(row, id, parsed, httpReq, principal) {
|
|
2366
2386
|
if (!askRowVisibleTo(row, principal))
|
|
2367
2387
|
return this.askNotVisible();
|
|
@@ -2778,30 +2798,21 @@ export class ToolApprovalCoordinator {
|
|
|
2778
2798
|
}
|
|
2779
2799
|
finishRespond(entry, judgedOwner, parsed, opts) {
|
|
2780
2800
|
let rememberApplied;
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
const unhandled = home;
|
|
2793
|
-
throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
|
|
2801
|
+
if (parsed.value === "allow_session") {
|
|
2802
|
+
const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
|
|
2803
|
+
rememberApplied = answer.home === "seat";
|
|
2804
|
+
if (answer.home === "seat") {
|
|
2805
|
+
const grantKey = sessionAllowKey(judgedOwner, answer.seat, sessionAllowCategory(entry.toolName), entry.grantBinding);
|
|
2806
|
+
if (this.allowAllSessions.size >= MAX_ALLOW_SESSIONS) {
|
|
2807
|
+
const oldest = this.allowAllSessions.values().next().value;
|
|
2808
|
+
if (oldest !== undefined)
|
|
2809
|
+
this.allowAllSessions.delete(oldest);
|
|
2810
|
+
}
|
|
2811
|
+
this.allowAllSessions.add(grantKey);
|
|
2794
2812
|
}
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
rememberApplied = Boolean(entry.sessionId) && grantable;
|
|
2798
|
-
if (parsed.value === "allow_session" && entry.sessionId && grantable) {
|
|
2799
|
-
if (this.allowAllSessions.size >= MAX_ALLOW_SESSIONS) {
|
|
2800
|
-
const oldest = this.allowAllSessions.values().next().value;
|
|
2801
|
-
if (oldest !== undefined)
|
|
2802
|
-
this.allowAllSessions.delete(oldest);
|
|
2813
|
+
else if (answer.home === "none" && answer.occupantUnreadable) {
|
|
2814
|
+
defaultLogger.warn("session_grant_refused_occupant_unreadable", { sessionId: entry.sessionId, toolName: entry.toolName });
|
|
2803
2815
|
}
|
|
2804
|
-
this.allowAllSessions.add(sessionAllowKey(judgedOwner, entry.sessionId, sessionAllowCategory(entry.toolName), entry.grantBinding));
|
|
2805
2816
|
}
|
|
2806
2817
|
const allowed = parsed.value !== "deny";
|
|
2807
2818
|
const settleArgs = opts?.settleOutcome !== undefined
|
|
@@ -2872,7 +2883,8 @@ export class ToolApprovalCoordinator {
|
|
|
2872
2883
|
grantBinding: { kind: "unreadable" },
|
|
2873
2884
|
...(card.classes !== undefined ? { classes: card.classes } : {}),
|
|
2874
2885
|
};
|
|
2875
|
-
const
|
|
2886
|
+
const leg = row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {};
|
|
2887
|
+
const rememberRefused = liveSessionAnswer(pendingEntryStandingAnswerFacts(facts), leg).home === "none";
|
|
2876
2888
|
const cardFrame = (card.rememberRefused === true) === rememberRefused
|
|
2877
2889
|
? replayFrame
|
|
2878
2890
|
: { ...replayFrame, card: rememberRefused ? { ...card, rememberRefused: true } : (({ rememberRefused: _stale, ...rest }) => rest)(card) };
|
|
@@ -2903,7 +2915,7 @@ export class ToolApprovalCoordinator {
|
|
|
2903
2915
|
owner: row.owner,
|
|
2904
2916
|
ownerReadSeq: this.rowReadSeq,
|
|
2905
2917
|
executionLane: row.executionLane,
|
|
2906
|
-
...
|
|
2918
|
+
...leg,
|
|
2907
2919
|
...(card.fromSubagent === true ? { originTaskId: row.sourceSessionId } : {}),
|
|
2908
2920
|
toolName: card.toolName,
|
|
2909
2921
|
...facts,
|
|
@@ -2979,18 +2991,29 @@ export class ToolApprovalCoordinator {
|
|
|
2979
2991
|
n += 1;
|
|
2980
2992
|
return n;
|
|
2981
2993
|
}
|
|
2982
|
-
listLivePending(scope) {
|
|
2983
|
-
const rows = [];
|
|
2994
|
+
async listLivePending(scope) {
|
|
2984
2995
|
const owner = scope === undefined ? undefined : ownerOfCheckpointScope(scope);
|
|
2985
|
-
const
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2996
|
+
const inScope = (rowOwner) => owner === undefined || rowOwner === owner;
|
|
2997
|
+
const candidates = new Map();
|
|
2998
|
+
for (const e of this.pending.values())
|
|
2999
|
+
if (!candidates.has(e.approvalId))
|
|
3000
|
+
candidates.set(e.approvalId, e);
|
|
3001
|
+
const store = this.askStore;
|
|
3002
|
+
const ids = [...candidates.keys()];
|
|
3003
|
+
const listed = await Promise.all([...candidates.values()].map(async (entry) => {
|
|
3004
|
+
if (store === undefined || !this.registrationHasRow(entry))
|
|
3005
|
+
return inScope(entry.owner);
|
|
3006
|
+
const ask = await this.askRowFollowingOwner(store, entry.askId, "getAsk(list-live)");
|
|
3007
|
+
return ask?.state === "STREAM_PENDING" && inScope(ask.owner);
|
|
3008
|
+
}));
|
|
3009
|
+
const rows = [];
|
|
3010
|
+
ids.forEach((id, i) => {
|
|
3011
|
+
if (!listed[i])
|
|
3012
|
+
return;
|
|
3013
|
+
const current = this.liveEntryFor(id);
|
|
3014
|
+
if (current !== undefined)
|
|
3015
|
+
rows.push(livePendingRowOf(current));
|
|
3016
|
+
});
|
|
2994
3017
|
return rows;
|
|
2995
3018
|
}
|
|
2996
3019
|
hasLivePendingFromLeg(names) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { projectMcpAuthorization } from "../mcp-authorization-face.js";
|
|
1
2
|
/**
|
|
2
3
|
* 上 wire 的通告码 —— **显式闭集常量表**(设计稿 ①,起步三码;今天的码数以本常量自身为准——
|
|
3
4
|
* 在散文里抄数字必陈腐,codex 5.65 增量批 R1-[low] 实逮:上一句曾写「今天九码」而表里是十条。
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
* 同文件 G1 e2e 的全码扇出夹具、以及契约文档附录 D.3 那张表(含**小节标题里的码数** —— 那道门本批
|
|
17
18
|
* 刚立,立完就在下一次加码时自己咬住了)。
|
|
18
19
|
*/
|
|
19
|
-
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.lineage_rerooted", "server.model_unreachable", "permission.entry_mode_clamped", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete", "route.finish_reason_unknown", "route.stream_end_ignored", "route.credential_origin_mismatch", "mods.registration_refused", "config.session_rules_earlier_grammar", "advisor.not_attached", "inherit_env.names_withheld", "model.capability_downgraded", "context.media_removed", "mcp.authorization_required", "classifier.seat_rate_limited", "context.tool_schema_removed", "memory.harvest_refused", "memory.harvest_conflict", "config.legacy_tool_name"];
|
|
20
|
+
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.lineage_rerooted", "server.model_unreachable", "permission.entry_mode_clamped", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete", "route.finish_reason_unknown", "route.stream_end_ignored", "route.credential_origin_mismatch", "mods.registration_refused", "config.session_rules_earlier_grammar", "advisor.not_attached", "inherit_env.names_withheld", "model.capability_downgraded", "context.media_removed", "mcp.authorization_required", "classifier.seat_rate_limited", "context.tool_schema_removed", "memory.harvest_refused", "memory.harvest_conflict", "config.legacy_tool_name", "config.read_deny_floor_unkept"];
|
|
20
21
|
export type EngineNoticeWireCode = (typeof ENGINE_NOTICE_WIRE_CODES)[number];
|
|
21
22
|
/** 白名单谓词(单点):路由与门都读这一个,不许第二处手抄码串。 */
|
|
22
23
|
export declare function isEngineNoticeWireCode(code: string): code is EngineNoticeWireCode;
|
|
@@ -108,6 +109,19 @@ export declare function redactNoticeMessage(message: unknown): string;
|
|
|
108
109
|
* 交中和形,空白 / 超长的条目两只码不同)。其余字段、其余码原样。
|
|
109
110
|
*/
|
|
110
111
|
export declare function redactNoticeRuleText(code: string, detail: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* 通告 `detail` 里**平铺着一条有处置表的记录**的码:码 → 那条记录的成员名与出门投影(一张表,不在 {@link engineNoticeEventData} 里写分支)。
|
|
114
|
+
* 记录成员只经那只投影出门(结构位:不过 {@link sanitizeWireText} 的脱敏与截断 —— 结构位的形与长由记录的属主判);detail 的其余成员照旧经
|
|
115
|
+
* {@link sanitizeNoticeDetail},合并按引擎 detail 的原键序。投影答 `undefined`(`reason` 出闭集 / 缺席)⇒ 记录成员整组缺席(在场而读不出由表的丢弃口计一次),
|
|
116
|
+
* 与状态面「整格缺席」同一失败方向。
|
|
117
|
+
* 运维日志腿(`boot/runner-deps.ts` 的转发席)不读这张登记:日志答「发生了什么」(给运维,整行过日志行的出口座),wire 答「用户拿到什么」—— 两个问题,两个读者。
|
|
118
|
+
*/
|
|
119
|
+
export declare const NOTICE_DETAIL_RECORDS: {
|
|
120
|
+
readonly "mcp.authorization_required": {
|
|
121
|
+
readonly members: readonly string[];
|
|
122
|
+
readonly project: typeof projectMcpAuthorization;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
111
125
|
export declare function engineNoticeEventData(notice: {
|
|
112
126
|
code: string;
|
|
113
127
|
message: string;
|
|
@@ -121,6 +135,17 @@ export declare function engineNoticeEventData(notice: {
|
|
|
121
135
|
export type EngineNoticeWireSink = (row: EngineNoticeWireRow) => unknown;
|
|
122
136
|
/** 口的槽位(闭集):`live` = 流上的人(SSE),`durable` = 这条 run 的事件账。{@link EngineNoticeRouter.routeConfirmed} 只数 `durable` 槽的落账确认。 */
|
|
123
137
|
export type EngineNoticeSlot = "live" | "durable";
|
|
138
|
+
/**
|
|
139
|
+
* 分流器收的通告形:引擎的四键(`code` / `message` / `detail` / 顶层 `sessionId`)加本服务的一只**投递键** `taskId` ——
|
|
140
|
+
* 在场 = 这条通告说的是哪一条 run(run 资源 id),只投给登记了同一条 run 的腿;缺席 = 按会话投(引擎的通告都不带它)。投递键不上 wire(行里没有它)。
|
|
141
|
+
*/
|
|
142
|
+
export interface RoutedNotice {
|
|
143
|
+
readonly code: string;
|
|
144
|
+
readonly message: string;
|
|
145
|
+
readonly detail?: Record<string, unknown>;
|
|
146
|
+
readonly sessionId?: unknown;
|
|
147
|
+
readonly taskId?: unknown;
|
|
148
|
+
}
|
|
124
149
|
/** 一条腿的两只具名口(各自可缺席:bg 腿没有 live SSE,ephemeral sync 腿没有账本)。 */
|
|
125
150
|
export interface EngineNoticeLegSlots {
|
|
126
151
|
readonly live?: EngineNoticeWireSink;
|
|
@@ -142,6 +167,11 @@ export interface EngineNoticeLegSlots {
|
|
|
142
167
|
* 药:每次 `registerLeg` 铸一个单调 legId,`route` **只投最新代**;旧代的口留在表里(它自己的注销仍
|
|
143
168
|
* 按身份精确删,不会误删新代),但一帧都收不到。方向 = fail-closed(宁可旧腿少一帧,不可新腿的事实
|
|
144
169
|
* 写进旧腿的账)。
|
|
170
|
+
*
|
|
171
|
+
* 🔴 **反方向同一条:点名了 run 的通告不进别的 run 的账**(投递键 `taskId`,{@link RoutedNotice})。本服务按腿作用域定归属的通告
|
|
172
|
+
* (`read-deny-floor-notice.ts`:腿派出去的 run 的那一帧)带上这条腿的 run;腿的作用域可以被续延留住(后台子代在腿收场之后才准备),
|
|
173
|
+
* 那一刻同会话的最新一代可能已是下一条 run ⇒ 最新一代登记的 run 不是点名的那一条 ⇒ 不投。腿登记时带它写的那条 run(`registerEngineNoticeLeg` 的 `taskId`);
|
|
174
|
+
* 引擎的通告不带投递键,照旧按会话投。
|
|
145
175
|
*/
|
|
146
176
|
export declare class EngineNoticeRouter {
|
|
147
177
|
private readonly legs;
|
|
@@ -150,7 +180,7 @@ export declare class EngineNoticeRouter {
|
|
|
150
180
|
*
|
|
151
181
|
* 每只口各自 try 隔离在 {@link route} 里,单口抛不牵连同腿另一口。
|
|
152
182
|
*/
|
|
153
|
-
registerLeg(sessionId: string, slots: EngineNoticeLegSlots): () => void;
|
|
183
|
+
registerLeg(sessionId: string, slots: EngineNoticeLegSlots, taskId?: string): () => void;
|
|
154
184
|
/** 单口腿的便捷形(测试用):登记为 **durable** 槽 —— 这样 `route()` 与 `routeConfirmed()` 两条路都能用一只口测到(live 槽对后者结构上恒不计)。 */
|
|
155
185
|
register(sessionId: string, sink: EngineNoticeWireSink): () => void;
|
|
156
186
|
/** 诊断/门用:某会话此刻**最新代**有几只口在听(旧代不计——它们收不到帧)。 */
|
|
@@ -158,28 +188,18 @@ export declare class EngineNoticeRouter {
|
|
|
158
188
|
/** 诊断/门用:某会话此刻有几代腿在表里(>1 = 正处在换代窗内)。 */
|
|
159
189
|
legCount(sessionId: string): number;
|
|
160
190
|
/**
|
|
161
|
-
* 分流器的 wire 半场。返回**真投出去的口数**(0 = 没投:非白名单码 / 缺 sessionId / 该会话无活跃腿)。
|
|
191
|
+
* 分流器的 wire 半场。返回**真投出去的口数**(0 = 没投:非白名单码 / 缺 sessionId / 该会话无活跃腿 / 点名的 run 不是最新一代登记的那一条)。
|
|
162
192
|
*
|
|
163
193
|
* 单只口抛错**不吃掉同腿的其它口**(fleet bus 订阅者隔离同理由),并按 F 类登记留痕。
|
|
164
194
|
*/
|
|
165
|
-
route(notice:
|
|
166
|
-
code: string;
|
|
167
|
-
message: string;
|
|
168
|
-
detail?: Record<string, unknown>;
|
|
169
|
-
sessionId?: unknown;
|
|
170
|
-
}, nowMs?: number): number;
|
|
195
|
+
route(notice: RoutedNotice, nowMs?: number): number;
|
|
171
196
|
/**
|
|
172
197
|
* [ref](codex r1-F2 / r2-F1;[ref] opus 腿 L2 改按槽判):同一只扇出,但**等**每只口交回的持久化结果 —— 返回**确认落账**的口数:
|
|
173
198
|
* 只数 **`durable` 槽**里交回 thenable 且兑现 `true` 的口;兑现 `false` / 拒绝不算;`live` 槽**结构上不计**(不管它返回什么 —— 流上的人收没收到说明不了落账;
|
|
174
199
|
* 修前按「交回 thenable」反推是不是 durable 口,哪天 live 口改成 async 返回 `true` 就会被计成落账)。给「投出之后要记一笔『告知过』」的铸点用:
|
|
175
200
|
* 记账必须跟在**落账**之后,不能跟在「调用了口」之后(后台腿唯一的口是事件账 append,写失败时 `route()` 的计数照样是 1)。判据(白名单 / 归属 / 最新代 / 隔离)与 `route()` 逐字同一条。
|
|
176
201
|
*/
|
|
177
|
-
routeConfirmed(notice:
|
|
178
|
-
code: string;
|
|
179
|
-
message: string;
|
|
180
|
-
detail?: Record<string, unknown>;
|
|
181
|
-
sessionId?: unknown;
|
|
182
|
-
}, nowMs?: number): Promise<number>;
|
|
202
|
+
routeConfirmed(notice: RoutedNotice, nowMs?: number): Promise<number>;
|
|
183
203
|
/** 两只入口共用的扇出:返回每只**没抛**的口的持久化结果(promise 形一律先接住拒绝 ⇒ 绝不留未处理拒绝)。 */
|
|
184
204
|
private fanOut;
|
|
185
205
|
}
|
|
@@ -197,6 +217,8 @@ export declare const defaultEngineNoticeRouter: EngineNoticeRouter;
|
|
|
197
217
|
*/
|
|
198
218
|
export declare function registerEngineNoticeLeg(opts: {
|
|
199
219
|
sessionId: string | undefined;
|
|
220
|
+
/** 这条腿写的那条 run(run 资源 id = 本腿 `spec.taskId`;没有 run 资源 ⇒ 缺席)—— 点名了 run 的通告只投给登记了同一条 run 的腿。 */
|
|
221
|
+
taskId?: string;
|
|
200
222
|
live?: EngineNoticeWireSink;
|
|
201
223
|
durable?: EngineNoticeWireSink;
|
|
202
224
|
router?: EngineNoticeRouter;
|
|
@@ -210,11 +232,6 @@ export declare function registerEngineNoticeLeg(opts: {
|
|
|
210
232
|
* `route()` 恒返 0 —— 一条结构上永远投不出去的用户面披露,就是本仓 `task.user_steer_undrained` 陈腐明拒
|
|
211
233
|
* 那一族的病。缺席/空数组 ⇒ 一个字节不投(既有腿逐字不变)。
|
|
212
234
|
*/
|
|
213
|
-
pending?: readonly
|
|
214
|
-
code: string;
|
|
215
|
-
message: string;
|
|
216
|
-
detail?: Record<string, unknown>;
|
|
217
|
-
sessionId?: unknown;
|
|
218
|
-
}[];
|
|
235
|
+
pending?: readonly RoutedNotice[];
|
|
219
236
|
}): () => void;
|
|
220
237
|
//# sourceMappingURL=engine-notice-wire.d.ts.map
|
|
@@ -2,6 +2,7 @@ import { uuidv7 } from "@sema-agent/core";
|
|
|
2
2
|
import { redactSecrets } from "./redact.js";
|
|
3
3
|
import { redactListEntry } from "../list-entry-display.js";
|
|
4
4
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
5
|
+
import { MCP_AUTHORIZATION_MEMBERS, projectMcpAuthorization } from "../mcp-authorization-face.js";
|
|
5
6
|
export const ENGINE_NOTICE_WIRE_CODES = [
|
|
6
7
|
"memory.session_polluted",
|
|
7
8
|
"memory.harvest_quarantined",
|
|
@@ -54,6 +55,7 @@ export const ENGINE_NOTICE_WIRE_CODES = [
|
|
|
54
55
|
"memory.harvest_refused",
|
|
55
56
|
"memory.harvest_conflict",
|
|
56
57
|
"config.legacy_tool_name",
|
|
58
|
+
"config.read_deny_floor_unkept",
|
|
57
59
|
];
|
|
58
60
|
const WIRE_CODES = new Set(ENGINE_NOTICE_WIRE_CODES);
|
|
59
61
|
export function isEngineNoticeWireCode(code) {
|
|
@@ -135,11 +137,27 @@ export function redactNoticeRuleText(code, detail) {
|
|
|
135
137
|
});
|
|
136
138
|
return { ...detail, [at.array]: redacted };
|
|
137
139
|
}
|
|
140
|
+
export const NOTICE_DETAIL_RECORDS = {
|
|
141
|
+
"mcp.authorization_required": { members: MCP_AUTHORIZATION_MEMBERS, project: projectMcpAuthorization },
|
|
142
|
+
};
|
|
143
|
+
function noticeDetailOf(code, detail) {
|
|
144
|
+
const records = NOTICE_DETAIL_RECORDS;
|
|
145
|
+
const record = Object.hasOwn(records, code) ? records[code] : undefined;
|
|
146
|
+
if (record === undefined || detail === undefined)
|
|
147
|
+
return sanitizeNoticeDetail(redactNoticeRuleText(code, detail));
|
|
148
|
+
const own = (key) => record.members.includes(key);
|
|
149
|
+
const face = { ...record.project(Object.fromEntries(Object.entries(detail).filter(([k]) => own(k)))) };
|
|
150
|
+
const rest = sanitizeNoticeDetail(redactNoticeRuleText(code, Object.fromEntries(Object.entries(detail).filter(([k]) => !own(k)))));
|
|
151
|
+
return Object.fromEntries(Object.keys(detail).flatMap((k) => {
|
|
152
|
+
const from = own(k) ? face : rest;
|
|
153
|
+
return Object.hasOwn(from, k) ? [[k, from[k]]] : [];
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
138
156
|
export function engineNoticeEventData(notice, sessionId, nowMs, eventId) {
|
|
139
157
|
return {
|
|
140
158
|
code: notice.code,
|
|
141
159
|
message: redactNoticeMessage(notice.message).slice(0, NOTICE_TEXT_MAX),
|
|
142
|
-
detail:
|
|
160
|
+
detail: noticeDetailOf(notice.code, notice.detail),
|
|
143
161
|
sessionId,
|
|
144
162
|
ts: nowMs,
|
|
145
163
|
eventId,
|
|
@@ -149,9 +167,9 @@ const isThenableResult = (v) => typeof v === "object" && v !== null && typeof v.
|
|
|
149
167
|
let nextLegId = 1;
|
|
150
168
|
export class EngineNoticeRouter {
|
|
151
169
|
legs = new Map();
|
|
152
|
-
registerLeg(sessionId, slots) {
|
|
170
|
+
registerLeg(sessionId, slots, taskId) {
|
|
153
171
|
const sinks = [...(slots.live ? [{ slot: "live", sink: slots.live }] : []), ...(slots.durable ? [{ slot: "durable", sink: slots.durable }] : [])];
|
|
154
|
-
const leg = { legId: nextLegId++, sinks };
|
|
172
|
+
const leg = { legId: nextLegId++, sinks, ...(taskId !== undefined && taskId.length > 0 ? { taskId } : {}) };
|
|
155
173
|
const list = this.legs.get(sessionId) ?? [];
|
|
156
174
|
list.push(leg);
|
|
157
175
|
this.legs.set(sessionId, list);
|
|
@@ -197,6 +215,9 @@ export class EngineNoticeRouter {
|
|
|
197
215
|
const leg = list && list.length > 0 ? list[list.length - 1] : undefined;
|
|
198
216
|
if (!leg || leg.sinks.length === 0)
|
|
199
217
|
return [];
|
|
218
|
+
const named = notice.taskId;
|
|
219
|
+
if (typeof named === "string" && named.length > 0 && leg.taskId !== named)
|
|
220
|
+
return [];
|
|
200
221
|
const row = engineNoticeEventData(notice, sessionId, nowMs, uuidv7());
|
|
201
222
|
const outcomes = [];
|
|
202
223
|
for (const { slot, sink } of leg.sinks) {
|
|
@@ -219,7 +240,7 @@ export function registerEngineNoticeLeg(opts) {
|
|
|
219
240
|
if (live === undefined && durable === undefined)
|
|
220
241
|
return () => undefined;
|
|
221
242
|
const router = opts.router ?? defaultEngineNoticeRouter;
|
|
222
|
-
const unregister = router.registerLeg(sessionId, { ...(live ? { live } : {}), ...(durable ? { durable } : {}) });
|
|
243
|
+
const unregister = router.registerLeg(sessionId, { ...(live ? { live } : {}), ...(durable ? { durable } : {}) }, opts.taskId);
|
|
223
244
|
for (const notice of opts.pending ?? [])
|
|
224
245
|
router.route(notice);
|
|
225
246
|
return unregister;
|
|
@@ -69,7 +69,9 @@ export interface LedgerSink {
|
|
|
69
69
|
* The redaction owner is NOT this writer: it is `redactLedgerEventData` — the one confluence every ledger row
|
|
70
70
|
* crosses at the three store twins' `appendEvent` AND again on the read face (idempotent). Redacting here too
|
|
71
71
|
* would put two writers on one semantic surface; the other park writers (`http/server.ts`'s two resume legs)
|
|
72
|
-
* would still need it, and a per-writer arm is exactly the shape that drifts.
|
|
72
|
+
* would still need it, and a per-writer arm is exactly the shape that drifts.
|
|
73
|
+
* Never rejects: the park is already committed by the engine (its card is in the checkpoint store) and only the run row's park write
|
|
74
|
+
* decides the run (`park-row-commit.ts`); an unwritable park / usage row is a loud log gap (`appendParkRow`), not a verdict. */
|
|
73
75
|
appendParked(kind: ParkLedgerEventType, result: unknown): Promise<void>;
|
|
74
76
|
/** Terminal `done` event. `result` must already be checkpoint-token-stripped (and, on the bg leg,
|
|
75
77
|
* model-usage-attached) by the caller. */
|
package/dist/trace/project.d.ts
CHANGED
|
@@ -217,7 +217,7 @@ export declare function toolStartEventData(ev: {
|
|
|
217
217
|
* `done` 永远到不了、重连恒复现同一处),而 `gate-outcome-defective` 那一格还不涨。
|
|
218
218
|
*
|
|
219
219
|
* ⇒ 兑现方式从「枚举」换成**结构**:任何逃出投影的异常同走既有的那一口 report + withhold。规则因此变少
|
|
220
|
-
* (不是「守住已知的 N 种坏形」而是「坏字节一律 withhold」)。core 7.51.0 起筛本身对任意 JSON 形不抛(
|
|
220
|
+
* (不是「守住已知的 N 种坏形」而是「坏字节一律 withhold」)。core 7.51.0 起筛本身对任意 JSON 形不抛([ref]:只覆盖 JSON ——
|
|
221
221
|
* 访问器 / Proxy 这类非 JSON 值仍可能抛),本仓此前叠在筛前的具名形门与成员门(第二读法)随之退役,诊断串就是筛给的缺陷句。
|
|
222
222
|
* ⛔ **刻意不动**「先脱敏后截断」的次序:截断在前会把跨界的密钥切成半截明文留在输出里,而且它只治
|
|
223
223
|
* `note` 一条叶(`approver` 同病)—— 那是给一个类打两个特判,正是本仓要消掉的形。
|
|
@@ -294,7 +294,8 @@ export declare function reasoningEndEventData(ev: Record<string, unknown>): Segm
|
|
|
294
294
|
* can never appear here) — SAME UNTRUSTED RAW contract as `output` (a card carries `originalFile`/stdout bodies),
|
|
295
295
|
* so it gets the same deep redaction before it is persisted or echoed — except a media card's `file.base64` (image / document
|
|
296
296
|
* cards: the second encoding of the same bytes the `output` block carries), which, like the block's `data`, is an encoding of
|
|
297
|
-
* bytes and not text
|
|
297
|
+
* bytes and not text; a card that carries a record with a disposition table (an MCP authorization failure card's `authorization`) has that member
|
|
298
|
+
* projected by the record's table ({@link projectToolCard}, the one reader of a tool card — session history reads `toolResult.details` with it too; the durable face drops the media bytes in the ledger confluence). `label`(core 展示名,同 tool_start 的
|
|
298
299
|
* label 待遇 verbatim)白名单排查(2026-07-24)补齐进函数本体——此前外包给调用点各自手动拼接,7 处只有
|
|
299
300
|
* 3 处记得拼,resume leg + ledger-sink 落盘两处漏了,持久化记录本身缺 label 一写盘就永久追不回来。 */
|
|
300
301
|
export declare function toolEndEventData(ev: {
|
|
@@ -333,7 +334,7 @@ export declare function toolEndEventData(ev: {
|
|
|
333
334
|
* · `toolCallId` / `toolName` —— 调用 id(🔴 [ref] 订正:出身是**服务商**在 tool_use / tool_calls 里给的,引擎缺席时自铸兜底、越界时折叠 ——
|
|
334
335
|
* 此前写「引擎铸」不实)与名册里的工具名(与 `tool_start` 逐字同源)⇒ verbatim。调用 id 这一族的形状在**全部面的共同入口**一次施加 ——
|
|
335
336
|
* core 7.36.0([ref])brain 建调用那一行的准入(在形原样 / 越界单射折叠,原字节只在转录 `ToolCall.wireId`),一方 brain 新铸的调用在逐帧面上
|
|
336
|
-
* 恒是在形的引擎 id(残余两条 [ref]:≤7.106.0 写下的存量行 resume 出来的帧是服务商原串逐字;宿主 Brain 不准入
|
|
337
|
+
* 恒是在形的引擎 id(残余两条 [ref]:≤7.106.0 写下的存量行 resume 出来的帧是服务商原串逐字;宿主 Brain 不准入 [ref] —— 详见
|
|
337
338
|
* run-terminal `admitProviderEcho` 顶注);
|
|
338
339
|
* 本仓不设第二道闸(见 run-terminal `admitProviderEcho` 顶注;[ref] 关)。
|
|
339
340
|
* · `elapsedTimeSeconds` —— 引擎铸的整秒,单调、一 call 一个原点 ⇒ 有限数才铸键。
|
|
@@ -440,8 +441,10 @@ export interface ModelUsageSeat {
|
|
|
440
441
|
* 终局由 {@link attachModelUsage} 先结清最后一拍再落 `done`,停驻由本函数先 drain 再落停驻行。顺序属于写口、不属于调用点:
|
|
441
442
|
* 只回结果的 verify 腿没有逐 turn 落账的流(无 `turn_end` 帧),挂起前的用量只有停驻这一拍才落账;若各调用点各自记得「先结清」,
|
|
442
443
|
* 这条腿的账本尾帧就会是 `model_usage`,与不带 `verify` 的停驻(用量在 `turn_end` 就结清了)两形不同序(`GET /v1/runs/:id/events` 的尾帧)。
|
|
443
|
-
*
|
|
444
|
-
*
|
|
444
|
+
*
|
|
445
|
+
* **不抛**:这两行是一次**已提交**停驻的投影(卡在引擎交回之前已落 checkpoint 店;停驻成立与否只由 run 行的停驻写回答,`park-row-commit.ts`)。
|
|
446
|
+
* 写不下 ⇒ 响亮留痕(`server.runs.terminal-ledger-write-failed`,`arm=park-usage` / `arm=park-row`,与终局帧写不下同一只 tag:run 行是 durable truth,
|
|
447
|
+
* 读面与收割器容忍账本尾巴缺席),调用方照常往下提交行 —— 账本写不下从不改这条 run 的判词。用量行落不下 ⇒ 停驻行照落(两笔各自留痕)。
|
|
445
448
|
*/
|
|
446
449
|
export declare function appendParkRow(append: AppendFn, usage: ModelUsageSeat | undefined, word: ParkLedgerEventType, result: unknown, reopened?: string | null): Promise<void>;
|
|
447
450
|
/**
|