@sema-agent/server 7.149.0 → 7.151.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 +307 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +92 -40
- package/deploy/sema-up/README.md +7 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +3 -3
- package/dist/approval-gate-currency.d.ts +2 -2
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +2 -2
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +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/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +7 -8
- package/dist/boot/resolve-spec.js +80 -35
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +28 -24
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +16 -8
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +44 -6
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/boot/web-admin.js +3 -1
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capability-facts.d.ts +84 -66
- package/dist/capability-facts.js +58 -41
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +15 -12
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +22 -15
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +66 -29
- package/dist/device-ws-protocol.d.ts +79 -12
- package/dist/device-ws-protocol.js +64 -26
- package/dist/engine-identity.d.ts +23 -5
- package/dist/engine-identity.js +13 -0
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +3 -3
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- 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/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +19 -4
- package/dist/http/approval-sweeps.js +7 -6
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +20 -63
- package/dist/http/checkpoint-ctx.js +2 -24
- package/dist/http/claim-heartbeat.d.ts +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +36 -29
- package/dist/http/durable-run-leg.js +17 -17
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +264 -20
- package/dist/http/owner-access.js +215 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +38 -1
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +273 -89
- package/dist/http/route-ctx.d.ts +41 -19
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +12 -12
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/fleet.js +10 -8
- 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/projects.d.ts +4 -2
- package/dist/http/routes/projects.js +7 -6
- 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 +125 -66
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +174 -83
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +26 -48
- package/dist/http/routes/tasks.js +38 -23
- 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 +28 -30
- package/dist/http/server.js +7 -3
- 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 +1 -2
- package/dist/http/submit-ctx.js +8 -6
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +19 -6
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/endpoint.js +9 -8
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +19 -5
- package/dist/leg-facts.js +3 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +12 -8
- package/dist/observability/fail-open.js +12 -8
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/owner-faces.d.ts +28 -4
- package/dist/owner-faces.js +2 -0
- package/dist/parked-decide.d.ts +104 -53
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +80 -61
- package/dist/plugins/one-time-migrations.js +241 -104
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +28 -1
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +8 -3
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +44 -17
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +114 -14
- package/dist/plugins/remote-env-e2b.d.ts +18 -7
- package/dist/plugins/remote-env-e2b.js +53 -40
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +18 -1
- package/dist/plugins/remote-env-host.js +48 -47
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +56 -32
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +37 -43
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +64 -62
- package/dist/plugins/remote-shell.d.ts +101 -2
- package/dist/plugins/remote-shell.js +221 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +22 -3
- package/dist/plugins/run-store-sql.js +33 -9
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
- package/dist/plugins/schema-consistency.d.ts +9 -5
- package/dist/plugins/schema-consistency.js +48 -18
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +68 -0
- package/dist/plugins/serving-requirement.js +60 -0
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
- package/dist/plugins/stop-then-start-sentence.js +48 -0
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +29 -2
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.js +9 -0
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +6 -1
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +64 -0
- package/dist/project-context.js +66 -0
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +31 -33
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +28 -4
- package/dist/session-incarnation.js +14 -2
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +4 -74
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +2 -10
- package/dist/stores-sql/retention-store-sql.js +2 -10
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +6 -5
- package/dist/task-settings.d.ts +19 -5
- package/dist/task-settings.js +13 -7
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +147 -12
- package/dist/tool-approval.js +206 -109
- package/dist/trace/engine-notice-wire.d.ts +14 -0
- package/dist/trace/engine-notice-wire.js +18 -1
- package/dist/trace/project.d.ts +4 -3
- package/dist/trace/project.js +3 -2
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/self-minted-wire.d.ts +422 -26
- package/dist/trace/self-minted-wire.js +149 -23
- 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/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
- package/package.json +3 -3
- package/wire-changes/server@7.150.0.json +335 -0
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
package/dist/tool-approval.js
CHANGED
|
@@ -27,6 +27,7 @@ import { APPROVAL_EXEMPTED_EVENT } from "./plugins/approval-exemption-store.js";
|
|
|
27
27
|
import { refusalBody } from "./http/refusal-body.js";
|
|
28
28
|
import { withoutSettlementEvidence } from "./gate-settlement.js";
|
|
29
29
|
import { extensionRequesterOf } from "./trace/extension-call-face.js";
|
|
30
|
+
import { boundedRotation } from "./bounded-rotation.js";
|
|
30
31
|
const defaultLogger = createLogger();
|
|
31
32
|
const MAX_APPROVAL_ARGS_BYTES = 16384;
|
|
32
33
|
const DEFAULT_APPROVAL_TTL_MS = 5 * 60_000;
|
|
@@ -69,7 +70,7 @@ function durableRuleMaterial(material) {
|
|
|
69
70
|
}
|
|
70
71
|
export const NOT_PENDING_UNKNOWN_CAUSE = "unknown_or_other_replica";
|
|
71
72
|
export const TOOL_APPROVAL_READ_STATES = ["pending", "decided", "parked", "void"];
|
|
72
|
-
function decidedRowFacts(row) {
|
|
73
|
+
export function decidedRowFacts(row) {
|
|
73
74
|
if (row.state !== "DECIDED" || (row.decision !== "approve" && row.decision !== "deny") || row.provisional || row.decidedAtMs === null)
|
|
74
75
|
return undefined;
|
|
75
76
|
return { decision: row.decision === "approve" ? "allow" : "deny", decidedAtMs: row.decidedAtMs, ...(row.decisionNote !== null ? { decisionNote: row.decisionNote } : {}) };
|
|
@@ -85,6 +86,22 @@ function buildAskRowReadProjection(row, nowMs) {
|
|
|
85
86
|
};
|
|
86
87
|
}
|
|
87
88
|
export const ASK_DECISION_CONSUMER_ABSENT = "absent";
|
|
89
|
+
function standingParkedDecision(gate, row, idempotencyKey) {
|
|
90
|
+
if (gate?.kind !== "decided")
|
|
91
|
+
return undefined;
|
|
92
|
+
const decision = gate.decision === "allow" ? "approve" : "deny";
|
|
93
|
+
if (row.decision === decision && row.decidedAtMs !== null && row.decidedAtMs >= gate.decidedAtMs) {
|
|
94
|
+
return {
|
|
95
|
+
kind: "standing",
|
|
96
|
+
decision,
|
|
97
|
+
decidedAtMs: row.decidedAtMs,
|
|
98
|
+
...(row.decisionNote !== null ? { decisionNote: row.decisionNote } : {}),
|
|
99
|
+
...(row.decisionActor !== null ? { actor: row.decisionActor } : {}),
|
|
100
|
+
byThisRequest: idempotencyKey !== undefined && row.idempotencyKey === idempotencyKey,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return { kind: "standing", decision, decidedAtMs: gate.decidedAtMs, ...(gate.decisionNote !== undefined ? { decisionNote: gate.decisionNote } : {}), byThisRequest: false };
|
|
104
|
+
}
|
|
88
105
|
const MAX_INFLIGHT_TERMINAL_CLAIMS = 2;
|
|
89
106
|
const DURABLE_CONVERGE_BACKOFF_MS = [50, 100, 200, 400, 800, 1600];
|
|
90
107
|
export const DURABLE_CONVERGE_READ_TIMEOUT_MS = 2_000;
|
|
@@ -115,10 +132,28 @@ const FS_WRITE_TOOLS = pathConfinableWriteToolNames();
|
|
|
115
132
|
function sessionAllowCategory(toolName) {
|
|
116
133
|
return FS_WRITE_TOOLS.has(toolName) ? "fs-write" : `tool:${toolName}`;
|
|
117
134
|
}
|
|
118
|
-
function sessionAllowKey(owner,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
function sessionAllowKey(owner, seat, category, binding) {
|
|
136
|
+
return JSON.stringify([owner, seat.sessionId, seat.incarnation, category, binding.kind === "bound" ? binding.digest : null]);
|
|
137
|
+
}
|
|
138
|
+
function sessionAllowSeatOf(leg) {
|
|
139
|
+
return leg.sessionId && leg.incarnation ? { sessionId: leg.sessionId, incarnation: leg.incarnation } : undefined;
|
|
140
|
+
}
|
|
141
|
+
function liveSessionAnswer(facts, leg) {
|
|
142
|
+
const home = standingAnswerHome(facts);
|
|
143
|
+
switch (home) {
|
|
144
|
+
case "none":
|
|
145
|
+
return { home: "none", occupantUnreadable: false };
|
|
146
|
+
case "seat": {
|
|
147
|
+
const seat = sessionAllowSeatOf(leg);
|
|
148
|
+
return seat !== undefined ? { home: "seat", seat } : { home: "none", occupantUnreadable: Boolean(leg.sessionId) };
|
|
149
|
+
}
|
|
150
|
+
case "server_store":
|
|
151
|
+
return leg.sessionId ? { home: "server_store", sessionId: leg.sessionId } : { home: "none", occupantUnreadable: false };
|
|
152
|
+
default: {
|
|
153
|
+
const unhandled = home;
|
|
154
|
+
throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
122
157
|
}
|
|
123
158
|
function askStandingAnswerFacts(req, governanceForced, deploymentListAsks) {
|
|
124
159
|
const classes = screenAskClassMembers(req.askClass, req.classes)?.classes;
|
|
@@ -196,8 +231,8 @@ function pendingEntryStandingAnswerFacts(entry) {
|
|
|
196
231
|
deploymentListQuestion: entry.deploymentListQuestion === true,
|
|
197
232
|
};
|
|
198
233
|
}
|
|
199
|
-
function projectDecisionFacts(facts, frame, card) {
|
|
200
|
-
const rememberRefused =
|
|
234
|
+
function projectDecisionFacts(facts, leg, frame, card) {
|
|
235
|
+
const rememberRefused = liveSessionAnswer(facts, leg).home === "none";
|
|
201
236
|
if (frame !== undefined) {
|
|
202
237
|
if (facts.requiresRealApproval)
|
|
203
238
|
frame.requiresRealApproval = true;
|
|
@@ -256,7 +291,7 @@ function livePendingRowOf(e) {
|
|
|
256
291
|
...(e.requiresRealApproval ? { requiresRealApproval: true } : {}),
|
|
257
292
|
...(e.governanceForced ? { governanceForced: true } : {}),
|
|
258
293
|
...(listFrame.mandated === true ? { mandated: true } : {}),
|
|
259
|
-
...(
|
|
294
|
+
...(liveSessionAnswer(pendingEntryStandingAnswerFacts(e), e).home === "none" ? { rememberRefused: true } : {}),
|
|
260
295
|
...(listFrame.mandate !== undefined ? { mandate: listFrame.mandate } : {}),
|
|
261
296
|
...(listFrame.origin !== undefined ? { origin: listFrame.origin } : {}),
|
|
262
297
|
...(listFrame.type === "approval_request" && listFrame.liveFactsUnknown === true ? { liveFactsUnknown: true } : {}),
|
|
@@ -360,6 +395,18 @@ function parseToolApprovalFields(body, retired) {
|
|
|
360
395
|
}
|
|
361
396
|
return { ok: false, error: 'decision must be one of "allow" | "allow_session" | "deny"' };
|
|
362
397
|
}
|
|
398
|
+
export function askDecisionRecordOf(write) {
|
|
399
|
+
return {
|
|
400
|
+
decision: write.decision,
|
|
401
|
+
...(write.actor !== undefined ? { decisionActor: write.actor } : {}),
|
|
402
|
+
decisionNote: write.note ?? null,
|
|
403
|
+
idempotencyKey: write.idempotencyKey ?? null,
|
|
404
|
+
...liveHostSource(write.decider),
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function liveDecideInputOf(write) {
|
|
408
|
+
return { ...askDecisionRecordOf(write), ...(write.decision === "approve" && write.updatedInput !== undefined ? { updatedInput: write.updatedInput } : {}) };
|
|
409
|
+
}
|
|
363
410
|
export function buildUnattendedPolicyRefusal(reason) {
|
|
364
411
|
return { allow: false, settledBy: POLICY_REFUSAL_DECISION.settledBy, reason };
|
|
365
412
|
}
|
|
@@ -544,8 +591,8 @@ export class ToolApprovalCoordinator {
|
|
|
544
591
|
admitMaxPerOwner;
|
|
545
592
|
admitByTask = new Map();
|
|
546
593
|
admitByOwner = new Map();
|
|
547
|
-
|
|
548
|
-
|
|
594
|
+
suspendedPollCursor = { offset: 0 };
|
|
595
|
+
adoptedPollCursor = { offset: 0 };
|
|
549
596
|
editedDecisionsInFlight = new Map();
|
|
550
597
|
storeErrorWarned = false;
|
|
551
598
|
storeErrorTally = 0;
|
|
@@ -959,8 +1006,8 @@ export class ToolApprovalCoordinator {
|
|
|
959
1006
|
const sessionId = origin.sessionId;
|
|
960
1007
|
if (!sessionId)
|
|
961
1008
|
return false;
|
|
962
|
-
const
|
|
963
|
-
const live =
|
|
1009
|
+
const seat = sessionAllowSeatOf(origin);
|
|
1010
|
+
const live = seat !== undefined && this.allowAllSessions.has(sessionAllowKey(origin.owner, seat, sessionAllowCategory(req.toolName), facts.grantBinding));
|
|
964
1011
|
const durable = !live && facts.grantBinding.kind === "none" && (await this.durableGrantHas(sessionId, req.toolName));
|
|
965
1012
|
if (!live && !durable)
|
|
966
1013
|
return false;
|
|
@@ -1330,7 +1377,7 @@ export class ToolApprovalCoordinator {
|
|
|
1330
1377
|
...(askReasonsOfReq !== undefined ? { askReasons: askReasonsOfReq } : {}),
|
|
1331
1378
|
...(governanceForced ? { governanceForced: true } : {}),
|
|
1332
1379
|
...(req.mandated === true ? { mandated: true } : {}),
|
|
1333
|
-
...(
|
|
1380
|
+
...(liveSessionAnswer(askStandingAnswerFacts(req, governanceForced, deploymentListAsks), origin).home === "none" ? { rememberRefused: true } : {}),
|
|
1334
1381
|
...(typeof req.boundGrantDigest === "string" ? { boundGrantDigest: req.boundGrantDigest, ...(req.boundGrants !== undefined ? { boundGrants: req.boundGrants } : {}) } : {}),
|
|
1335
1382
|
...(noRulingCause !== undefined ? { classifierNoRuling: noRulingCause } : {}),
|
|
1336
1383
|
...(grantAbsence !== undefined ? { boundGrantAbsence: grantAbsence } : {}),
|
|
@@ -1897,7 +1944,7 @@ export class ToolApprovalCoordinator {
|
|
|
1897
1944
|
grantBinding: entryGrantBinding,
|
|
1898
1945
|
classes: entryClasses,
|
|
1899
1946
|
...(entryDeploymentListQuestion ? { deploymentListQuestion: true } : {}),
|
|
1900
|
-
}), frame, cardForFrame);
|
|
1947
|
+
}), origin, frame, cardForFrame);
|
|
1901
1948
|
const cardFrame = askId !== undefined && cardForFrame !== undefined
|
|
1902
1949
|
? buildApprovalRequestFrame({ askId, taskId: origin.taskId, approvalId: wireApprovalId, card: cardForFrame, expiresAtMs: persistedExpiresAtMs, nowMs: Date.now(), live: frame })
|
|
1903
1950
|
: undefined;
|
|
@@ -1944,7 +1991,7 @@ export class ToolApprovalCoordinator {
|
|
|
1944
1991
|
if (s.requiresRealApproval === true)
|
|
1945
1992
|
continue;
|
|
1946
1993
|
s.requiresRealApproval = true;
|
|
1947
|
-
const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s.frame, s.cardFrame?.card);
|
|
1994
|
+
const card = projectDecisionFacts(pendingEntryStandingAnswerFacts(s), s, s.frame, s.cardFrame?.card);
|
|
1948
1995
|
if (s.cardFrame !== undefined && card !== undefined && card !== s.cardFrame.card)
|
|
1949
1996
|
s.cardFrame = { ...s.cardFrame, card };
|
|
1950
1997
|
}
|
|
@@ -2097,11 +2144,10 @@ export class ToolApprovalCoordinator {
|
|
|
2097
2144
|
}
|
|
2098
2145
|
recordDeploymentListAnswer(decided, entry, judgedOwner, parsed, principal, eligibility) {
|
|
2099
2146
|
const store = this.sessionGrants;
|
|
2100
|
-
const
|
|
2101
|
-
if (parsed.value !== "allow_session" ||
|
|
2102
|
-
return decided;
|
|
2103
|
-
if (standingAnswerHome(pendingEntryStandingAnswerFacts(entry)) !== "server_store")
|
|
2147
|
+
const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
|
|
2148
|
+
if (parsed.value !== "allow_session" || answer.home !== "server_store" || store === undefined)
|
|
2104
2149
|
return decided;
|
|
2150
|
+
const sessionId = answer.sessionId;
|
|
2105
2151
|
return (async () => {
|
|
2106
2152
|
const result = await decided;
|
|
2107
2153
|
if (result.status !== 200)
|
|
@@ -2443,21 +2489,50 @@ export class ToolApprovalCoordinator {
|
|
|
2443
2489
|
const openGenerationNow = this.lookupParkRedemption(row.askId) !== undefined ? await this.openGateGeneration(row) : undefined;
|
|
2444
2490
|
const prior = this.lookupParkRedemption(row.askId);
|
|
2445
2491
|
if (prior?.redeemed !== undefined && receiptAnswersNow(prior.redeemed.gateGeneration, openGenerationNow))
|
|
2446
|
-
return this.replayRedeemReceipt(id, prior, row, prior.redeemed, parsed);
|
|
2492
|
+
return this.replayRedeemReceipt(id, prior, row, prior.redeemed, parsed, row);
|
|
2447
2493
|
if (prior?.inflight !== undefined) {
|
|
2448
2494
|
const shared = await prior.inflight;
|
|
2449
2495
|
if (shared.status < 200 || shared.status >= 300)
|
|
2450
2496
|
return shared;
|
|
2451
2497
|
if (!receiptAnswersNow(shared.gateGeneration, openGenerationNow))
|
|
2452
2498
|
return this.redeemParkedAsk(id, row, parsed, httpReq, principal);
|
|
2453
|
-
return this.replayRedeemReceipt(id, prior, row, { decision: shared.decision, body: shared.body, gateGeneration: shared.gateGeneration, ...(shared.rule?.terminal === true ? { rule: shared.rule.body } : {}) }, parsed);
|
|
2499
|
+
return this.replayRedeemReceipt(id, prior, row, { decision: shared.decision, body: shared.body, gateGeneration: shared.gateGeneration, ...(shared.rule?.terminal === true ? { rule: shared.rule.body } : {}) }, parsed, shared.recorded ?? { decisionNote: null });
|
|
2454
2500
|
}
|
|
2501
|
+
const store = this.askStore;
|
|
2502
|
+
if (store === undefined)
|
|
2503
|
+
return this.notPending();
|
|
2504
|
+
const request = {
|
|
2505
|
+
write: { decision: parsed.value === "deny" ? "deny" : "approve", decider: parsed.decider, ...(parsed.note !== undefined ? { note: parsed.note } : {}) },
|
|
2506
|
+
...(parsed.value === "allow_session" ? { remember: "session" } : {}),
|
|
2507
|
+
...(parsed.persistRule !== undefined ? { persistRule: parsed.persistRule } : {}),
|
|
2508
|
+
...(parsed.updatedInput !== undefined && parsed.value !== "deny" ? { updatedInput: parsed.updatedInput } : {}),
|
|
2509
|
+
...(principal !== undefined ? { principal } : {}),
|
|
2510
|
+
operator: false,
|
|
2511
|
+
...(httpReq !== undefined ? { httpReq } : {}),
|
|
2512
|
+
};
|
|
2513
|
+
const out = await this.runParkedFlight(redeem, store, row, row.gateToken, request);
|
|
2514
|
+
if (out.status < 200 || out.status >= 300)
|
|
2515
|
+
return { status: out.status, body: out.body };
|
|
2516
|
+
const rule = out.rule;
|
|
2517
|
+
return {
|
|
2518
|
+
status: out.status,
|
|
2519
|
+
body: {
|
|
2520
|
+
...out.body,
|
|
2521
|
+
approvalId: id,
|
|
2522
|
+
askId: row.askId,
|
|
2523
|
+
accepted: "parked_redeemed",
|
|
2524
|
+
...(parsed.value === "allow_session" ? { rememberApplied: out.rememberApplied === true } : {}),
|
|
2525
|
+
...noteRecordedReceipt(parsed.note, noteLandedOnRow(parsed.note, out.recorded?.decisionNote ?? null)),
|
|
2526
|
+
...(rule?.body ?? {}),
|
|
2527
|
+
},
|
|
2528
|
+
};
|
|
2529
|
+
}
|
|
2530
|
+
async runParkedFlight(redeem, store, row, gateToken, request) {
|
|
2531
|
+
const decision = request.write.decision;
|
|
2455
2532
|
const admission = this.parkRedemptionAdmission(row.owner);
|
|
2456
2533
|
if (admission !== undefined)
|
|
2457
|
-
return admission;
|
|
2534
|
+
return { ...admission, body: admission.body, decision };
|
|
2458
2535
|
const memo = this.openParkRedemption(row.askId, row.owner);
|
|
2459
|
-
const decision = parsed.value === "deny" ? "deny" : "approve";
|
|
2460
|
-
const gateToken = row.gateToken;
|
|
2461
2536
|
const flight = (async () => {
|
|
2462
2537
|
let res;
|
|
2463
2538
|
try {
|
|
@@ -2467,12 +2542,13 @@ export class ToolApprovalCoordinator {
|
|
|
2467
2542
|
gateBoundCallId: row.gateBoundCallId,
|
|
2468
2543
|
gateBoundInputHash: row.gateBoundInputHash,
|
|
2469
2544
|
decision,
|
|
2470
|
-
...(
|
|
2471
|
-
decider:
|
|
2472
|
-
...(
|
|
2473
|
-
...(
|
|
2474
|
-
...(principal !== undefined ? { principal } : {}),
|
|
2475
|
-
|
|
2545
|
+
...(request.write.note !== undefined ? { note: request.write.note } : {}),
|
|
2546
|
+
decider: request.write.decider,
|
|
2547
|
+
...(request.updatedInput !== undefined && decision === "approve" ? { updatedInput: request.updatedInput } : {}),
|
|
2548
|
+
...(request.remember !== undefined ? { remember: request.remember } : {}),
|
|
2549
|
+
...(request.principal !== undefined ? { principal: request.principal } : {}),
|
|
2550
|
+
operator: request.operator,
|
|
2551
|
+
...(request.httpReq !== undefined ? { httpReq: request.httpReq } : {}),
|
|
2476
2552
|
});
|
|
2477
2553
|
}
|
|
2478
2554
|
catch (err) {
|
|
@@ -2481,8 +2557,9 @@ export class ToolApprovalCoordinator {
|
|
|
2481
2557
|
}
|
|
2482
2558
|
if (res.status < 200 || res.status >= 300)
|
|
2483
2559
|
return { ...res, decision };
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2560
|
+
const recorded = await this.recordParkedOutcome(store, row, request.write);
|
|
2561
|
+
const rule = await this.persistRuleFromRow(row, request.persistRule, request.updatedInput !== undefined);
|
|
2562
|
+
return { ...res, decision, ...(recorded !== undefined ? { recorded } : {}), ...(rule !== undefined ? { rule } : {}) };
|
|
2486
2563
|
})();
|
|
2487
2564
|
memo.inflight = flight;
|
|
2488
2565
|
let out;
|
|
@@ -2495,25 +2572,57 @@ export class ToolApprovalCoordinator {
|
|
|
2495
2572
|
if (out.status < 200 || out.status >= 300) {
|
|
2496
2573
|
if (this.parkRedemptions.get(row.askId) === memo)
|
|
2497
2574
|
this.parkRedemptions.delete(row.askId);
|
|
2498
|
-
return
|
|
2575
|
+
return out;
|
|
2499
2576
|
}
|
|
2500
|
-
const rule = out.rule;
|
|
2501
2577
|
if (this.retainParkRedemption(row.askId, memo))
|
|
2502
|
-
memo.redeemed = { decision, body: out.body, gateGeneration: out.gateGeneration, ...(rule?.terminal === true ? { rule: rule.body } : {}) };
|
|
2503
|
-
return
|
|
2504
|
-
status: out.status,
|
|
2505
|
-
body: {
|
|
2506
|
-
...out.body,
|
|
2507
|
-
approvalId: id,
|
|
2508
|
-
askId: row.askId,
|
|
2509
|
-
accepted: "parked_redeemed",
|
|
2510
|
-
...(parsed.value === "allow_session" ? { rememberApplied: out.rememberApplied === true } : {}),
|
|
2511
|
-
...(rule?.body ?? {}),
|
|
2512
|
-
},
|
|
2513
|
-
};
|
|
2578
|
+
memo.redeemed = { decision, body: out.body, gateGeneration: out.gateGeneration, ...(out.rule?.terminal === true ? { rule: out.rule.body } : {}) };
|
|
2579
|
+
return out;
|
|
2514
2580
|
}
|
|
2515
|
-
async
|
|
2516
|
-
|
|
2581
|
+
async recordParkedOutcome(store, row, write) {
|
|
2582
|
+
try {
|
|
2583
|
+
const out = await this.writeAskDecision(store, row.askId, { kind: "parked" }, row.owner, write);
|
|
2584
|
+
if (out.ok)
|
|
2585
|
+
return out.row;
|
|
2586
|
+
recordFailOpen("server.approval.parked-decision-not-recorded", `askId=${row.askId} reason=${out.reason}`);
|
|
2587
|
+
return undefined;
|
|
2588
|
+
}
|
|
2589
|
+
catch (err) {
|
|
2590
|
+
this.noteStoreError(err, "recordParkedDecision");
|
|
2591
|
+
recordFailOpen("server.approval.parked-decision-not-recorded", `askId=${row.askId} reason=store_error`);
|
|
2592
|
+
return undefined;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
async decideParkedAsk(store, row, request, idempotencyKey) {
|
|
2596
|
+
for (;;) {
|
|
2597
|
+
const gate = await this.readParkedGate(row);
|
|
2598
|
+
const current = await this.askRowFor(store, row.askId, "getAsk(parked-decision)");
|
|
2599
|
+
if (current === null || current.state !== "PARKED" || !askRowCarriesOwner(current, row.owner))
|
|
2600
|
+
return { kind: "gone" };
|
|
2601
|
+
const inflight = this.lookupParkRedemption(row.askId)?.inflight;
|
|
2602
|
+
if (inflight !== undefined) {
|
|
2603
|
+
await inflight;
|
|
2604
|
+
continue;
|
|
2605
|
+
}
|
|
2606
|
+
const standing = standingParkedDecision(gate, current, idempotencyKey);
|
|
2607
|
+
if (standing !== undefined)
|
|
2608
|
+
return standing;
|
|
2609
|
+
if (request.write.decision === "approve" && request.policyMayNotApprove === true)
|
|
2610
|
+
return { kind: "policy_refused" };
|
|
2611
|
+
const redeem = this.parkedRedeem?.();
|
|
2612
|
+
if (redeem === undefined || row.gateToken === null) {
|
|
2613
|
+
if (row.gateToken === null)
|
|
2614
|
+
defaultLogger.error("tool approval parked row carries no gate token — nothing to redeem", { askId: row.askId });
|
|
2615
|
+
return { kind: "gate_only" };
|
|
2616
|
+
}
|
|
2617
|
+
const out = await this.runParkedFlight(redeem, store, current, row.gateToken, request);
|
|
2618
|
+
if (out.status === 200)
|
|
2619
|
+
return { kind: "accepted", body: out.body, ...(out.recorded !== undefined ? { recorded: out.recorded } : {}) };
|
|
2620
|
+
if ((await this.readParkedGate(row))?.kind === "decided")
|
|
2621
|
+
continue;
|
|
2622
|
+
return { kind: "refused", status: out.status, body: out.body };
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
async persistRuleFromRow(row, persistRule, inputWasEdited) {
|
|
2517
2626
|
if (persistRule === undefined)
|
|
2518
2627
|
return undefined;
|
|
2519
2628
|
const flag = (rulePersisted, ruleRefusal, echo) => ({
|
|
@@ -2533,7 +2642,7 @@ export class ToolApprovalCoordinator {
|
|
|
2533
2642
|
const command = row.ruleCommand;
|
|
2534
2643
|
if (command === null)
|
|
2535
2644
|
return flag(false, "rule_material_absent");
|
|
2536
|
-
if (
|
|
2645
|
+
if (inputWasEdited)
|
|
2537
2646
|
return flag(false, "rule_input_edited");
|
|
2538
2647
|
const offers = card.ruleOffers ?? [];
|
|
2539
2648
|
const scope = row.ruleScopeRoot !== null ? { kind: "project", root: row.ruleScopeRoot } : undefined;
|
|
@@ -2590,10 +2699,10 @@ export class ToolApprovalCoordinator {
|
|
|
2590
2699
|
return { ...flag(false, "rule_store_error"), terminal: false };
|
|
2591
2700
|
}
|
|
2592
2701
|
}
|
|
2593
|
-
async replayRedeemReceipt(id, memo, row, receipt, parsed) {
|
|
2702
|
+
async replayRedeemReceipt(id, memo, row, receipt, parsed, recordedNote) {
|
|
2594
2703
|
let rule = receipt.decision === "approve" ? receipt.rule : this.lateRuleRefusal(parsed);
|
|
2595
2704
|
if (receipt.decision === "approve" && rule === undefined && parsed.persistRule !== undefined) {
|
|
2596
|
-
const flight = memo.ruleInflight ?? this.persistRuleFromRow(row, parsed);
|
|
2705
|
+
const flight = memo.ruleInflight ?? this.persistRuleFromRow(row, parsed.persistRule, parsed.updatedInput !== undefined);
|
|
2597
2706
|
const isOwner = memo.ruleInflight === undefined;
|
|
2598
2707
|
if (isOwner)
|
|
2599
2708
|
memo.ruleInflight = flight;
|
|
@@ -2619,6 +2728,7 @@ export class ToolApprovalCoordinator {
|
|
|
2619
2728
|
accepted: "parked_redeemed",
|
|
2620
2729
|
idempotent: true,
|
|
2621
2730
|
decision: receipt.decision === "approve" ? "allow" : "deny",
|
|
2731
|
+
...noteRecordedReceipt(parsed.note, noteLandedOnRow(parsed.note, recordedNote.decisionNote)),
|
|
2622
2732
|
...(rule ?? {}),
|
|
2623
2733
|
},
|
|
2624
2734
|
};
|
|
@@ -2702,19 +2812,36 @@ export class ToolApprovalCoordinator {
|
|
|
2702
2812
|
return withFlag(false, "rule_store_error");
|
|
2703
2813
|
}
|
|
2704
2814
|
}
|
|
2815
|
+
writeAskDecision(store, askId, form, owner, write) {
|
|
2816
|
+
switch (form.kind) {
|
|
2817
|
+
case "live":
|
|
2818
|
+
return this.withStoreDeadline(store.decideAsk(askId, form.batchId, owner, liveDecideInputOf(write)), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
2819
|
+
if (!late.ok)
|
|
2820
|
+
return;
|
|
2821
|
+
if (decidedRowFacts(late.row) === undefined) {
|
|
2822
|
+
defaultLogger.error("ask decision landed after its deadline on a row that is not an authoritative human decision — not settled", { askId, state: late.row.state, provisional: late.row.provisional });
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2825
|
+
this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
|
|
2826
|
+
});
|
|
2827
|
+
case "parked":
|
|
2828
|
+
return this.withStoreDeadline(store.recordParkedDecision(askId, owner, askDecisionRecordOf(write)), "recordParkedDecision", DURABLE_CALL_TIMEOUT_MS);
|
|
2829
|
+
default: {
|
|
2830
|
+
const unhandled = form;
|
|
2831
|
+
throw new Error(`writeAskDecision: unhandled form ${JSON.stringify(unhandled)}`);
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2705
2835
|
async respondWithCas(askStore, askId, batchId, owner, entry, parsed, ruleEligibility) {
|
|
2706
2836
|
let winnerRow;
|
|
2707
2837
|
let ambiguousConfirmedRow;
|
|
2708
2838
|
let noteLanded = false;
|
|
2709
2839
|
try {
|
|
2710
|
-
const decided = await this.
|
|
2840
|
+
const decided = await this.writeAskDecision(askStore, askId, { kind: "live", batchId }, owner, {
|
|
2711
2841
|
decision: parsed.value === "deny" ? "deny" : "approve",
|
|
2712
|
-
|
|
2713
|
-
...(parsed.
|
|
2714
|
-
...
|
|
2715
|
-
}), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
|
|
2716
|
-
if (late.ok)
|
|
2717
|
-
this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
|
|
2842
|
+
decider: parsed.decider,
|
|
2843
|
+
...(parsed.note !== undefined ? { note: parsed.note } : {}),
|
|
2844
|
+
...(parsed.updatedInput !== undefined ? { updatedInput: parsed.updatedInput } : {}),
|
|
2718
2845
|
});
|
|
2719
2846
|
if (decided.ok) {
|
|
2720
2847
|
winnerRow = decided.row;
|
|
@@ -2781,25 +2908,11 @@ export class ToolApprovalCoordinator {
|
|
|
2781
2908
|
}
|
|
2782
2909
|
finishRespond(entry, judgedOwner, parsed, opts) {
|
|
2783
2910
|
let rememberApplied;
|
|
2784
|
-
const home = standingAnswerHome(pendingEntryStandingAnswerFacts(entry));
|
|
2785
|
-
let grantable;
|
|
2786
|
-
switch (home) {
|
|
2787
|
-
case "seat":
|
|
2788
|
-
grantable = true;
|
|
2789
|
-
break;
|
|
2790
|
-
case "none":
|
|
2791
|
-
case "server_store":
|
|
2792
|
-
grantable = false;
|
|
2793
|
-
break;
|
|
2794
|
-
default: {
|
|
2795
|
-
const unhandled = home;
|
|
2796
|
-
throw new Error(`unhandled standing-answer home: ${String(unhandled)}`);
|
|
2797
|
-
}
|
|
2798
|
-
}
|
|
2799
2911
|
if (parsed.value === "allow_session") {
|
|
2800
|
-
const
|
|
2801
|
-
rememberApplied =
|
|
2802
|
-
if (
|
|
2912
|
+
const answer = liveSessionAnswer(pendingEntryStandingAnswerFacts(entry), entry);
|
|
2913
|
+
rememberApplied = answer.home === "seat";
|
|
2914
|
+
if (answer.home === "seat") {
|
|
2915
|
+
const grantKey = sessionAllowKey(judgedOwner, answer.seat, sessionAllowCategory(entry.toolName), entry.grantBinding);
|
|
2803
2916
|
if (this.allowAllSessions.size >= MAX_ALLOW_SESSIONS) {
|
|
2804
2917
|
const oldest = this.allowAllSessions.values().next().value;
|
|
2805
2918
|
if (oldest !== undefined)
|
|
@@ -2807,7 +2920,7 @@ export class ToolApprovalCoordinator {
|
|
|
2807
2920
|
}
|
|
2808
2921
|
this.allowAllSessions.add(grantKey);
|
|
2809
2922
|
}
|
|
2810
|
-
else if (
|
|
2923
|
+
else if (answer.home === "none" && answer.occupantUnreadable) {
|
|
2811
2924
|
defaultLogger.warn("session_grant_refused_occupant_unreadable", { sessionId: entry.sessionId, toolName: entry.toolName });
|
|
2812
2925
|
}
|
|
2813
2926
|
}
|
|
@@ -2880,7 +2993,8 @@ export class ToolApprovalCoordinator {
|
|
|
2880
2993
|
grantBinding: { kind: "unreadable" },
|
|
2881
2994
|
...(card.classes !== undefined ? { classes: card.classes } : {}),
|
|
2882
2995
|
};
|
|
2883
|
-
const
|
|
2996
|
+
const leg = row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {};
|
|
2997
|
+
const rememberRefused = liveSessionAnswer(pendingEntryStandingAnswerFacts(facts), leg).home === "none";
|
|
2884
2998
|
const cardFrame = (card.rememberRefused === true) === rememberRefused
|
|
2885
2999
|
? replayFrame
|
|
2886
3000
|
: { ...replayFrame, card: rememberRefused ? { ...card, rememberRefused: true } : (({ rememberRefused: _stale, ...rest }) => rest)(card) };
|
|
@@ -2911,7 +3025,7 @@ export class ToolApprovalCoordinator {
|
|
|
2911
3025
|
owner: row.owner,
|
|
2912
3026
|
ownerReadSeq: this.rowReadSeq,
|
|
2913
3027
|
executionLane: row.executionLane,
|
|
2914
|
-
...
|
|
3028
|
+
...leg,
|
|
2915
3029
|
...(card.fromSubagent === true ? { originTaskId: row.sourceSessionId } : {}),
|
|
2916
3030
|
toolName: card.toolName,
|
|
2917
3031
|
...facts,
|
|
@@ -3042,28 +3156,11 @@ export class ToolApprovalCoordinator {
|
|
|
3042
3156
|
continue;
|
|
3043
3157
|
seen.add(entry.askId);
|
|
3044
3158
|
}
|
|
3045
|
-
const waitingStart = waiting.length > 0 ? this.suspendedPollOffset % waiting.length : 0;
|
|
3046
|
-
const adoptedStart = adopted.length > 0 ? this.adoptedPollOffset % adopted.length : 0;
|
|
3047
|
-
const ordered = [
|
|
3048
|
-
...[...waiting.slice(waitingStart), ...waiting.slice(0, waitingStart)].map((askId) => ({ askId, tier: "waiting" })),
|
|
3049
|
-
...[...adopted.slice(adoptedStart), ...adopted.slice(0, adoptedStart)].map((askId) => ({ askId, tier: "adopted" })),
|
|
3050
|
-
];
|
|
3051
|
-
const deadlineMs = Date.now() + SUSPENDED_POLL_BUDGET_MS;
|
|
3052
3159
|
let settled = 0;
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
for (const { askId, tier } of ordered) {
|
|
3058
|
-
if (polled >= SUSPENDED_POLL_MAX_PER_TICK || Date.now() >= deadlineMs) {
|
|
3059
|
-
truncated = true;
|
|
3060
|
-
break;
|
|
3061
|
-
}
|
|
3062
|
-
polled++;
|
|
3063
|
-
if (tier === "waiting")
|
|
3064
|
-
this.suspendedPollOffset = waitingStart + ++polledWaiting;
|
|
3065
|
-
else
|
|
3066
|
-
this.adoptedPollOffset = adoptedStart + ++polledAdopted;
|
|
3160
|
+
const { visited: polled, truncated } = await boundedRotation([
|
|
3161
|
+
{ items: waiting, cursor: this.suspendedPollCursor },
|
|
3162
|
+
{ items: adopted, cursor: this.adoptedPollCursor },
|
|
3163
|
+
], { maxPerTick: SUSPENDED_POLL_MAX_PER_TICK, budgetMs: SUSPENDED_POLL_BUDGET_MS }, async (askId) => {
|
|
3067
3164
|
let row;
|
|
3068
3165
|
const readSeq = this.nextRowReadSeq();
|
|
3069
3166
|
try {
|
|
@@ -3071,24 +3168,24 @@ export class ToolApprovalCoordinator {
|
|
|
3071
3168
|
}
|
|
3072
3169
|
catch (err) {
|
|
3073
3170
|
this.noteStoreError(err, "getAsk(poll-suspended)");
|
|
3074
|
-
|
|
3171
|
+
return;
|
|
3075
3172
|
}
|
|
3076
3173
|
if (row === null) {
|
|
3077
3174
|
this.forgetAdoptedAsk(askId);
|
|
3078
|
-
|
|
3175
|
+
return;
|
|
3079
3176
|
}
|
|
3080
3177
|
if (row.state === "STREAM_PENDING") {
|
|
3081
3178
|
this.followRowOwner(askId, row.owner, readSeq);
|
|
3082
|
-
|
|
3179
|
+
return;
|
|
3083
3180
|
}
|
|
3084
3181
|
if (this.editedDecisionInFlight(askId))
|
|
3085
|
-
|
|
3182
|
+
return;
|
|
3086
3183
|
const endingCause = askRowEndingCause(row);
|
|
3087
3184
|
if (endingCause !== undefined) {
|
|
3088
3185
|
const before = this.waitingRegistrationCount(askId);
|
|
3089
3186
|
this.settleVoidedSiblings([askId], endingCause);
|
|
3090
3187
|
settled += before;
|
|
3091
|
-
|
|
3188
|
+
return;
|
|
3092
3189
|
}
|
|
3093
3190
|
const outcome = replayTerminalAskRow(row);
|
|
3094
3191
|
if (outcome === "unavailable") {
|
|
@@ -3096,11 +3193,11 @@ export class ToolApprovalCoordinator {
|
|
|
3096
3193
|
const parkCause = askRowParkTrigger(row) ?? (Date.now() >= row.expiresAtMs ? APPROVAL_ENDING_CAUSES.TTL_EXPIRED : APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK);
|
|
3097
3194
|
this.settleSameAskIdParkRoute(askId, parkCause);
|
|
3098
3195
|
settled += before;
|
|
3099
|
-
|
|
3196
|
+
return;
|
|
3100
3197
|
}
|
|
3101
3198
|
const delivered = this.notifyExternalDecision(askId, outcome).settled;
|
|
3102
3199
|
settled += delivered;
|
|
3103
|
-
}
|
|
3200
|
+
});
|
|
3104
3201
|
const backlog = Math.max(0, waiting.length + adopted.length - polled);
|
|
3105
3202
|
if (truncated) {
|
|
3106
3203
|
defaultLogger.warn("approval_suspended_poll_truncated", {
|
|
@@ -3109,8 +3206,8 @@ export class ToolApprovalCoordinator {
|
|
|
3109
3206
|
backlog,
|
|
3110
3207
|
maxPerTick: SUSPENDED_POLL_MAX_PER_TICK,
|
|
3111
3208
|
budgetMs: SUSPENDED_POLL_BUDGET_MS,
|
|
3112
|
-
resumeFromOffset: this.
|
|
3113
|
-
resumeAdoptedFromOffset: this.
|
|
3209
|
+
resumeFromOffset: this.suspendedPollCursor.offset,
|
|
3210
|
+
resumeAdoptedFromOffset: this.adoptedPollCursor.offset,
|
|
3114
3211
|
});
|
|
3115
3212
|
}
|
|
3116
3213
|
return { polled, settled, backlog, truncated };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { projectMcpAuthorization } from "../mcp-authorization-face.js";
|
|
1
2
|
/**
|
|
2
3
|
* 上 wire 的通告码 —— **显式闭集常量表**(设计稿 ①,起步三码;今天的码数以本常量自身为准——
|
|
3
4
|
* 在散文里抄数字必陈腐,codex 5.65 增量批 R1-[low] 实逮:上一句曾写「今天九码」而表里是十条。
|
|
@@ -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;
|
|
@@ -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",
|
|
@@ -136,11 +137,27 @@ export function redactNoticeRuleText(code, detail) {
|
|
|
136
137
|
});
|
|
137
138
|
return { ...detail, [at.array]: redacted };
|
|
138
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
|
+
}
|
|
139
156
|
export function engineNoticeEventData(notice, sessionId, nowMs, eventId) {
|
|
140
157
|
return {
|
|
141
158
|
code: notice.code,
|
|
142
159
|
message: redactNoticeMessage(notice.message).slice(0, NOTICE_TEXT_MAX),
|
|
143
|
-
detail:
|
|
160
|
+
detail: noticeDetailOf(notice.code, notice.detail),
|
|
144
161
|
sessionId,
|
|
145
162
|
ts: nowMs,
|
|
146
163
|
eventId,
|
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 一个原点 ⇒ 有限数才铸键。
|