@sema-agent/server 7.131.0 → 7.133.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 +575 -0
- package/README.md +12 -9
- package/README.zh-CN.md +9 -6
- package/USAGE.md +326 -98
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +82 -20
- package/dist/approval-card.js +46 -16
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +33 -19
- package/dist/audit.js +12 -16
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +27 -12
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +74 -123
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +15 -2
- package/dist/boot/session-faces.d.ts +2 -7
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +4 -2
- package/dist/boot/stage-06-runners.js +11 -7
- package/dist/boot/stage-07-capability-layer.d.ts +4 -2
- package/dist/boot/stage-07-capability-layer.js +27 -6
- package/dist/boot/stage-08-reapers.d.ts +4 -2
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +6 -9
- package/dist/boot/stage-10-http-server.d.ts +6 -9
- package/dist/boot/stage-10-http-server.js +7 -9
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +7 -8
- package/dist/boot/web-admin.d.ts +4 -3
- package/dist/boot/web-admin.js +186 -98
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +25 -25
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +23 -0
- package/dist/caller-text-echo.js +21 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +30 -6
- package/dist/capabilities/hands-lane.js +11 -1
- package/dist/capabilities/mcp-probe.d.ts +48 -3
- package/dist/capabilities/mcp-probe.js +47 -135
- package/dist/capabilities/scenarios.d.ts +95 -45
- package/dist/capabilities/scenarios.js +53 -38
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +47 -32
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +9 -2
- package/dist/config-provider.js +18 -6
- package/dist/config-types.d.ts +75 -20
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +137 -62
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -22
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +56 -10
- package/dist/execution-lane-caps.js +50 -0
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +91 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +79 -36
- package/dist/hooks/hook-runner.d.ts +349 -95
- package/dist/hooks/hook-runner.js +855 -568
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +188 -101
- package/dist/http/approval-sweeps.js +99 -21
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +41 -24
- package/dist/http/checkpoint-ctx.js +23 -16
- package/dist/http/claimed-run.d.ts +14 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +7 -11
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +15 -13
- package/dist/http/durable-run-leg.d.ts +6 -33
- package/dist/http/durable-run-leg.js +36 -10
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +70 -28
- package/dist/http/principal-gate.js +61 -15
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +43 -23
- package/dist/http/request-guards.js +53 -17
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +28 -4
- package/dist/http/resume-legs.js +169 -91
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +21 -5
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +6 -2
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +34 -107
- package/dist/http/routes/session-sync.js +15 -26
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +8 -7
- package/dist/http/routes/tasks.js +67 -21
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +33 -10
- package/dist/http/send.js +21 -4
- package/dist/http/server.d.ts +27 -18
- package/dist/http/server.js +34 -6
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +40 -0
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +11 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/lane-home-probe.d.ts +112 -0
- package/dist/lane-home-probe.js +101 -0
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +59 -0
- package/dist/limit-refusal.js +15 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +32 -19
- package/dist/mcp-assertion-header.js +10 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +6 -4
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +24 -17
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +44 -12
- package/dist/model-provider.js +21 -2
- package/dist/model-route-endpoint.d.ts +9 -12
- package/dist/model-route-endpoint.js +8 -11
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +76 -14
- package/dist/observability/fail-open.js +76 -14
- package/dist/observability/metrics.js +4 -1
- package/dist/observability/prompt-manifest.d.ts +33 -82
- package/dist/observability/prompt-manifest.js +122 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +58 -49
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +83 -15
- package/dist/plugins/blob-backend.js +68 -15
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +28 -4
- package/dist/plugins/checkpoint-store-sql.js +59 -28
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +11 -3
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +245 -93
- package/dist/plugins/one-time-migrations.js +668 -207
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +20 -8
- package/dist/plugins/pg-session-storage.js +34 -21
- package/dist/plugins/remote-env-adb.d.ts +12 -12
- package/dist/plugins/remote-env-adb.js +21 -6
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +103 -38
- package/dist/plugins/remote-env-k8s.js +288 -95
- package/dist/plugins/remote-env-local-docker.d.ts +27 -13
- package/dist/plugins/remote-env-local-docker.js +82 -11
- package/dist/plugins/remote-env-ssh.d.ts +21 -12
- package/dist/plugins/remote-env-ssh.js +117 -5
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +39 -0
- package/dist/plugins/session-epoch-anchor.js +22 -0
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +205 -1
- package/dist/plugins/sql-driver.js +325 -13
- package/dist/plugins/sql-errors.d.ts +64 -0
- package/dist/plugins/sql-errors.js +57 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +42 -15
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +8 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +29 -5
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +9 -2
- package/dist/request-key-closure.js +11 -5
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +38 -11
- package/dist/rule-entry-list.js +106 -30
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +54 -24
- package/dist/runs.d.ts +15 -8
- package/dist/runs.js +35 -1
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +27 -6
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +66 -54
- package/dist/sql-engine-posture.d.ts +31 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +82 -107
- package/dist/task-settings.d.ts +95 -108
- package/dist/task-settings.js +77 -98
- package/dist/text-bidi.d.ts +1 -48
- package/dist/text-bidi.js +3 -5
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +304 -88
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +122 -20
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +98 -17
- package/dist/trace/project.js +98 -50
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +377 -3
- package/dist/trace/wire-projection-faces.js +164 -1
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +11 -9
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 跨主体投递门 —— core `OrgDeliveryGate` 契约的 server 实现([ref] §10.2;core 7.53.0 的 core 半场)。
|
|
3
|
+
*
|
|
4
|
+
* ## 规则(一条)
|
|
5
|
+
* **一封跨主体的信只因这只门把它追加进收件人的 `principal.inbox` 而存在。** 门是唯一的跨 scope 追加持有者:成员判 →
|
|
6
|
+
* 铸信 → 收件箱上界 → 配额 → 追加,全在 {@link createOrgDeliveryGate} 交出的 `deliverCrossPrincipal` 里一体完成;
|
|
7
|
+
* 它只有两种答案 —— 一张回执,或 core 闭集 `ORG_DELIVERY_REFUSAL_CODES` 里的一个词。本仓不铸第二只拒绝词。
|
|
8
|
+
*
|
|
9
|
+
* 规则因此少了几条(而不是多了几条):
|
|
10
|
+
* · **成员判不另立名册**:「谁属于 org:acme」在一个进程里只有一个答案 —— 记忆准入 seam、memory-policy 面、共享记忆读面
|
|
11
|
+
* 读的那**同一个**目录实例(`boot/org-memory.ts` 装配的 `OrgMemoryDirectory`)。两位主体同属一个 org ⟺ 两人
|
|
12
|
+
* `lookup` 的 `org:` 键集合有交集。目录答不上来(`unavailable`)= 「部署说不出他们同 org」⇒ `not_member`
|
|
13
|
+
* (core 对这只词的定义逐字含这一臂)。
|
|
14
|
+
* · **记录只有一个铸点**:core 的纯函数 `mintCrossPrincipalRecord`(只写 `peerMeta.kind / fromScope / gateReceiptId`
|
|
15
|
+
* + 可选 `urgent` 与显示名;不写 `fromSession / fromMode / hopChain`)。本仓不另铸任何记录形。
|
|
16
|
+
* · **限流是配额店的两个原子动作,各管一件事**:`admitAttempt` 记发件人的每一次尝试(碰目录之前;界住刷目录的速率),
|
|
17
|
+
* `take` 在同一把锁下判并记 (from→to) 对偶界与收件人聚合界(投递额度)。SQL 两方言各是一个事务,见
|
|
18
|
+
* `plugins/org-delivery-quota-store.ts` 头注;File / Memory = 单进程。
|
|
19
|
+
* · **收件人的 scope 就是收件人主体串本身**:本服务的引擎 scope = `spec.principal`(`resolve-spec.ts` 落
|
|
20
|
+
* `auth.principal`;同一事实的推导见 `peer-directory.ts` 的「scope 轴」段)。门不另造编解码。
|
|
21
|
+
*
|
|
22
|
+
* ## 次序与理由
|
|
23
|
+
* 0. **发件人的尝试界**(配额店 `admitAttempt`,成没成都记一笔):满 ⇒ `rate_limited`。它必须在成员判之前 —— 成员判把调用方给的
|
|
24
|
+
* 收件人串交给组织目录去查,而目录的每主体状态按属主裁定不淘汰、它的量级只在「查的都是验过的主体」时有界(`org-memory-admission.ts`
|
|
25
|
+
* 的 `PrincipalState` 注);这一界让「一个成员拿任意串去刷目录」的速率与总量随时间线性有界(设计稿收件人查询面第四条:查询限流)。
|
|
26
|
+
* 与收件人无关 ⇒ 它的 `rate_limited` 不泄露收件人存不存在。
|
|
27
|
+
* 1. **成员判**(纯读):不同 org / 查无此人 / 目录不可用 / 收件人串过不了主体形判 / 收件人当不了收件箱的身份键(良构 Unicode ∧ 无控制字符 ∧
|
|
28
|
+
* UTF-8 字节不超过键列宽 —— 两方言收件箱写面与读面同读的唯一判官 `mailbox-store-sql.ts` 的 `mailboxKeyProblem`)⇒ 同一句 `not_member`,逐字节同 ——
|
|
29
|
+
* 门永远不是一只存在性探针(core 契约原句),也不说「是长度」。收件人那一判必须在配额之前:第 5 步的追加按同一只判官拒,拒在扣了投递额度之后就是「吃了额度没投到」。
|
|
30
|
+
* 2. **铸信**(纯函数):放在任何有副作用的步骤之前。发件人的 scope 拼不进信封的发件人位(引擎按百分号编码后 1..190 字节判,抛闭集码
|
|
31
|
+
* `cross_session.invalid_from_scope`,`CrossSessionCodecError` 由引擎包根导出)⇒ 同一句 `not_member`、一个配额名额都没吃 —— 发件人这一侧的判官只有引擎这一只,
|
|
32
|
+
* 本仓不另抄宽度公式。部署没声明收件箱消费方(`no_consumer`)或别的铸信失败 ⇒ 门抛(core:「the gate maps that to its own failure」),HTTP 面答 500,同样没吃额度。
|
|
33
|
+
* 3. **收件箱上界**(`peekCount` 读):满 ⇒ `inbox_full`,在吃配额之前判,满箱不烧发件人的额度。与引擎同主体车道的
|
|
34
|
+
* `maxQueuedPeerMessages` 同一形(入口处读一次占用);两封并发信最多越界并发数那么多,上界由配额再界一次。
|
|
35
|
+
* 4. **配额**(原子判并记):任一界满 ⇒ `rate_limited`,与第 0 步同一句(不让发件人从拒句里分辨出「收件人这一小时收了多少」)。
|
|
36
|
+
* 5. **追加**:`append(收件人 scope, PRINCIPAL_INBOX_HANDLE, 记录)`。店的预删除态拒码(`mailbox.recipient_tombstoned`)
|
|
37
|
+
* 原样转成 `recipient_tombstoned`(core 对这只词的定义:「the store's own pre-delete code, relayed」);其余错误抛。
|
|
38
|
+
* 被拒的投递在任何地方都不追加任何东西(core 契约原句);投递额度(第 4 步)在之后只有追加失败这一种「吃了额度没投到」—— 方向是收紧;
|
|
39
|
+
* 尝试界(第 0 步)按定义每次都记。
|
|
40
|
+
*
|
|
41
|
+
* ## 不是本门的威胁面(如实,[ref] §10.2-1 原句)
|
|
42
|
+
* 库内直接持有 `MailboxStore` 的宿主恒能写任何 scope —— 那是同一信任域内的事。本门保证的是**本服务的 wire 面**上没有第二条
|
|
43
|
+
* 跨 scope 写径:受理口(`POST /v1/principal-inbox/messages`)只调门,本仓源码里拼得出 `principal.inbox` 这只箱址的只有本文件
|
|
44
|
+
* (`test/org-delivery-gate-single-path.test.ts` 按源码钉)。
|
|
45
|
+
*/
|
|
46
|
+
import { type MailboxStore, type OrgDeliveryGate, type OrgDeliveryRefusalCode, type PrincipalInboxConsumer } from "@sema-agent/core";
|
|
47
|
+
import type { OrgMemoryDirectory } from "./org-memory-admission.js";
|
|
48
|
+
import type { OrgDeliveryQuotaPolicy, OrgDeliveryQuotaStore } from "./plugins/org-delivery-quota-store.js";
|
|
49
|
+
/**
|
|
50
|
+
* 跨主体配额(**唯一**的数字源;店只按它数)。默认显著紧于同主体车道(引擎 `PEER_LANE_DEFAULTS`:每发件人突发 30、
|
|
51
|
+
* 每秒回填 0.5):同一对主体每小时 10 封,一位收件人每小时合计 30 封 —— org 里一个吵闹的主体淹不了别人的箱;
|
|
52
|
+
* 一个发件人每小时 60 次尝试(成没成都算)—— 拿收件人串去问组织目录的速率有界(头注「次序」第 0 步)。
|
|
53
|
+
*/
|
|
54
|
+
export declare const ORG_DELIVERY_QUOTA: OrgDeliveryQuotaPolicy;
|
|
55
|
+
/** 收件箱上界(在箱、未被消费方确认的信封数)。与引擎同主体车道的箱上界缺省(`maxQueuedPeerMessages`)同值。 */
|
|
56
|
+
export declare const PRINCIPAL_INBOX_BOUND = 50;
|
|
57
|
+
/**
|
|
58
|
+
* 四只拒绝词各自的那**一句**(wire 上的 `error` 就是它,`routes/principal-inbox.ts` 原样中继、不手抄)。
|
|
59
|
+
* 键集 = core 闭集:core 加词 ⇒ 这张表编译红。
|
|
60
|
+
* `not_member` 一句同时服务「不同 org / 查无此人 / 目录答不上来 / 收件人串不成形 / 收件人当不了收件箱的键 / 发件人主体拼不进信封的发件人位」—— 改它要保持各臂同字节。
|
|
61
|
+
*/
|
|
62
|
+
export declare const ORG_DELIVERY_REFUSAL_MESSAGES: Readonly<Record<OrgDeliveryRefusalCode, string>>;
|
|
63
|
+
export interface OrgDeliveryGateDeps {
|
|
64
|
+
/** org 成员目录 —— **必须**与记忆准入 seam / memory-policy / 共享记忆读面同一个实例(头注)。 */
|
|
65
|
+
readonly directory: OrgMemoryDirectory;
|
|
66
|
+
/** 收件人箱所在的店(与引擎 `RunnerDeps.mailboxStore` 同一只)。 */
|
|
67
|
+
readonly mailbox: Pick<MailboxStore, "append" | "peekCount">;
|
|
68
|
+
/** 配额店(`StoreBackend.orgDeliveryQuota()`)。 */
|
|
69
|
+
readonly quota: OrgDeliveryQuotaStore;
|
|
70
|
+
/** 部署声明的收件箱消费方 —— `principalInboxConsumerOf` 读**同一份** `RunnerDeps` 的结果(core 契约:铸信要它)。 */
|
|
71
|
+
readonly consumer: PrincipalInboxConsumer;
|
|
72
|
+
/** 信的 `sentAt` 钟(缺省本进程墙钟)。配额窗不读它 —— 窗由配额店自己的钟定。 */
|
|
73
|
+
readonly nowMs?: () => number;
|
|
74
|
+
/** 回执 id 铸点(缺省 uuidv7)。 */
|
|
75
|
+
readonly mintReceiptId?: () => string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 活对象(闭包持有目录 / 两只店 / 消费方)⇒ `create*`(CLAUDE.md 工厂命名律)。
|
|
79
|
+
*/
|
|
80
|
+
export declare function createOrgDeliveryGate(deps: OrgDeliveryGateDeps): OrgDeliveryGate;
|
|
81
|
+
//# sourceMappingURL=org-delivery-gate.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CrossSessionCodecError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, PRINCIPAL_INBOX_HANDLE, mintCrossPrincipalRecord, uuidv7, } from "@sema-agent/core";
|
|
2
|
+
import { principalShapeProblem } from "./security.js";
|
|
3
|
+
import { mailboxKeyProblem } from "./plugins/mailbox-store-sql.js";
|
|
4
|
+
export const ORG_DELIVERY_QUOTA = Object.freeze({ windowMs: 3_600_000, attemptsPerSender: 60, perPair: 10, perRecipient: 30 });
|
|
5
|
+
export const PRINCIPAL_INBOX_BOUND = 50;
|
|
6
|
+
export const ORG_DELIVERY_REFUSAL_MESSAGES = Object.freeze({
|
|
7
|
+
"org_delivery.not_member": "the recipient cannot be reached through the organization delivery gate",
|
|
8
|
+
"org_delivery.rate_limited": "the cross-principal delivery quota is spent for now — try again later",
|
|
9
|
+
"org_delivery.inbox_full": "the recipient's principal inbox is full — try again after the recipient has read some of it",
|
|
10
|
+
"org_delivery.recipient_tombstoned": "the recipient is being deleted — nothing was delivered",
|
|
11
|
+
});
|
|
12
|
+
const refuse = (code) => ({ ok: false, code, message: ORG_DELIVERY_REFUSAL_MESSAGES[code] });
|
|
13
|
+
async function shareAnOrg(directory, a, b) {
|
|
14
|
+
const [la, lb] = await Promise.all([directory.lookup(a), directory.lookup(b)]);
|
|
15
|
+
if (la.kind !== "granted" || lb.kind !== "granted")
|
|
16
|
+
return false;
|
|
17
|
+
return Object.keys(la.scopes).some((org) => Object.hasOwn(lb.scopes, org));
|
|
18
|
+
}
|
|
19
|
+
const principalShaped = (s) => s !== "" && principalShapeProblem(s) === undefined;
|
|
20
|
+
const fitsInboxKey = (recipient) => mailboxKeyProblem("scope", recipient) === undefined;
|
|
21
|
+
export function createOrgDeliveryGate(deps) {
|
|
22
|
+
const nowMs = deps.nowMs ?? Date.now;
|
|
23
|
+
const mintReceiptId = deps.mintReceiptId ?? uuidv7;
|
|
24
|
+
return {
|
|
25
|
+
async deliverCrossPrincipal(authedFrom, toPrincipal, body) {
|
|
26
|
+
if (!(await deps.quota.admitAttempt(authedFrom.scope, ORG_DELIVERY_QUOTA)))
|
|
27
|
+
return refuse("org_delivery.rate_limited");
|
|
28
|
+
if (!principalShaped(toPrincipal) || !fitsInboxKey(toPrincipal) || !(await shareAnOrg(deps.directory, authedFrom.scope, toPrincipal))) {
|
|
29
|
+
return refuse("org_delivery.not_member");
|
|
30
|
+
}
|
|
31
|
+
const toScope = toPrincipal;
|
|
32
|
+
const receiptId = mintReceiptId();
|
|
33
|
+
let record;
|
|
34
|
+
try {
|
|
35
|
+
record = mintCrossPrincipalRecord({ from: authedFrom, body, receiptId, sentAt: nowMs(), consumer: deps.consumer });
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err instanceof CrossSessionCodecError && err.code === "cross_session.invalid_from_scope")
|
|
39
|
+
return refuse("org_delivery.not_member");
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
if ((await deps.mailbox.peekCount(toScope, PRINCIPAL_INBOX_HANDLE)) >= PRINCIPAL_INBOX_BOUND)
|
|
43
|
+
return refuse("org_delivery.inbox_full");
|
|
44
|
+
if (!(await deps.quota.take(authedFrom.scope, toScope, ORG_DELIVERY_QUOTA)))
|
|
45
|
+
return refuse("org_delivery.rate_limited");
|
|
46
|
+
let seq;
|
|
47
|
+
try {
|
|
48
|
+
seq = await deps.mailbox.append(toScope, PRINCIPAL_INBOX_HANDLE, record);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err?.code === MAILBOX_TOMBSTONED_RECIPIENT_CODE)
|
|
52
|
+
return refuse("org_delivery.recipient_tombstoned");
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
return { ok: true, receipt: { receiptId, seq } };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=org-delivery-gate.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读面上「一台服务器 / 一个对端挂了哪些工具」的**名单截表律** —— 全仓唯一属主。
|
|
3
|
+
*
|
|
4
|
+
* 为什么必须是一处:名单的条数是远端可控且无界的(A2A 卡里的技能条数、MCP 服务器列出的工具条数,core 只限单个名字的
|
|
5
|
+
* 长度,不限条数),而这些读面都是**只读 GET / 可被反复触发的探测**,多身份可放大。所以读面发的是
|
|
6
|
+
* **有界表 + 真计数 + 显式旗**,而不是静默截断:一个会撒谎的读面比一个大的读面更贵。
|
|
7
|
+
* 同一个事实(「名单被截了」)在每一张读面上必须是同一个数、同一个旗键、同一个说法 —— 两处各写一遍,
|
|
8
|
+
* 下一个人只会改到其中一处。
|
|
9
|
+
*
|
|
10
|
+
* ## 契约(所有用到它的读面逐字成立)
|
|
11
|
+
* · 名单最多 {@link PANEL_MAX_TOOL_NAMES} 条,**读数序**取前缀;
|
|
12
|
+
* · 超出时另发 `toolNamesTruncated: true`;**恰好**在上限上不算截断,旗键缺席(不编 `false`);
|
|
13
|
+
* · **真数不在这里**:`toolCount` 是各读面自己的铸点(A2A 面板 = 名单长度;MCP 状态面 = §G.7 的那一只投影),本函数一个字都不碰它 ——
|
|
14
|
+
* 消费端读数用 `toolCount`,别用 `toolNames.length`。
|
|
15
|
+
*/
|
|
16
|
+
/** 每一台服务器 / 每一个对端最多回多少条工具名。 */
|
|
17
|
+
export declare const PANEL_MAX_TOOL_NAMES = 200;
|
|
18
|
+
/** 一份工具名单的有界出口形(纯数据,`build*`)。入参不被改写。 */
|
|
19
|
+
export declare function buildBoundedToolNames(names: readonly string[]): {
|
|
20
|
+
toolNames: string[];
|
|
21
|
+
toolNamesTruncated?: true;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=panel-tool-names.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const PANEL_MAX_TOOL_NAMES = 200;
|
|
2
|
+
export function buildBoundedToolNames(names) {
|
|
3
|
+
return {
|
|
4
|
+
toolNames: names.slice(0, PANEL_MAX_TOOL_NAMES),
|
|
5
|
+
...(names.length > PANEL_MAX_TOOL_NAMES ? { toolNamesTruncated: true } : {}),
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=panel-tool-names.js.map
|
package/dist/parked-decide.d.ts
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* 行永 parked、生命周期分叉)。
|
|
10
10
|
*/
|
|
11
11
|
import type { HostDecision } from "./host-decision.js";
|
|
12
|
-
import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, QuestionAnswer,
|
|
12
|
+
import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, CheckpointToken, QuestionAnswer, RunInternals, TaskRegistry, ToolExecuteContext, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
|
|
13
13
|
import type { ParkedReviveSurfaceFactory } from "./parked-revive-surface.js";
|
|
14
14
|
import type { RebuiltInheritedGate } from "./boot/parked-revive-gate.js";
|
|
15
15
|
import { type WorkflowRunParkKey, type WorkflowAgentSessionIndex } from "./orchestration/workflow-agent-session-index.js";
|
|
16
|
+
import type { WorkflowParkDecisionStore, WorkflowParkOutcome } from "./orchestration/workflow-park-decision.js";
|
|
16
17
|
import { type SessionFaceReader } from "./session-incarnation.js";
|
|
17
18
|
export interface ParkedAgentMatch {
|
|
18
19
|
handle: string;
|
|
@@ -90,6 +91,36 @@ export declare function findParkOrigin(sources: ParkOriginSources, cp: {
|
|
|
90
91
|
scope: string;
|
|
91
92
|
sessionId: string;
|
|
92
93
|
}): Promise<ParkOrigin | undefined>;
|
|
94
|
+
/** 起跑读者的源(就是 `ServiceDeps` 上那几只;任一缺席 ⇒ 这台部署没有这条车道,读者只交回调用方自己带的那一份)。 */
|
|
95
|
+
export interface HeldWorkflowParkDecisionSources {
|
|
96
|
+
readonly workflowParkDecisions?: WorkflowParkDecisionStore;
|
|
97
|
+
readonly checkpointStore?: {
|
|
98
|
+
get(token: CheckpointToken): Promise<{
|
|
99
|
+
readonly status: string;
|
|
100
|
+
readonly scope: string;
|
|
101
|
+
readonly sessionId: string;
|
|
102
|
+
} | null>;
|
|
103
|
+
};
|
|
104
|
+
readonly workflowAgentSessionIndex?: WorkflowAgentSessionIndex;
|
|
105
|
+
readonly workflowRunStore?: Pick<WorkflowRunStore, "get">;
|
|
106
|
+
}
|
|
107
|
+
/** `RunInternals.workflowParkedResume` 的一条(形直接取 core 的那一位)。 */
|
|
108
|
+
type ParkedResumeEntry = NonNullable<RunInternals["workflowParkedResume"]>[number];
|
|
109
|
+
/**
|
|
110
|
+
* 🔴 **决定进引擎的唯一读者** —— 每一只起跑器(durable run 腿、续跑腿流形与 verify 形、同步流腿、同步 JSON 腿)开跑之前调一次,
|
|
111
|
+
* 产物原样摊进那一跑的 `RunInternals`(部署方铸的 TRUSTED internals:不是 `TaskSpec` 字段、不是工具参数 —— 模型永远不能自己决定一次审批)。
|
|
112
|
+
*
|
|
113
|
+
* 产物 = 调用方自己带的那一份(`carried`:`/decide` 的投递跑带着它刚受理、行还没落的那条决定)∪ 这个会话的决定行(律与寿命的属主 =
|
|
114
|
+
* `orchestration/workflow-park-decision.ts` 文件头),同一张卡以 `carried` 为准(它是要取代行上旧决定的那一个)。行这一侧逐条:
|
|
115
|
+
* · 子代卡此刻**仍 pending** 才供:读回 `null` / 状态不是 `pending` ⇒ 不供(引擎对「记着停驻、卡却已不 pending」的序数,有条目 ⇒ 当确认
|
|
116
|
+
* 结算、没条目 ⇒ 拒续跑 —— 供一条过期条目会把后者改成前者);读卡抛 ⇒ 不供并计 `server.workflow-park-decision.card-unreadable`
|
|
117
|
+
* (这一读失败不代表引擎随后的那一读也失败;不供的方向是这一跑不带它、行留着给下一跑 —— 绝不把它变成一次确认);
|
|
118
|
+
* · 投递目标 = 这张卡**当下**的持有者 run(`findParkOrigin`,与 `/decide` 路由同一只判官):持有者判不出唯一一条(分叉 / 证不了 / 卡
|
|
119
|
+
* 已在新 token 下再停)⇒ 不供(引擎只把条目交给 `resumeFromRunId` 恰是持有者的续跑;没有唯一持有者就没有可交付的那一跑)。
|
|
120
|
+
* 决定店读抛(local 账本闸合上 / SQL 一行坏体)⇒ 与读卡失败同律:这一店当「没有可供的行」,只交回 `carried`,计 `server.workflow-park-decision.store-unreadable`
|
|
121
|
+
* (不跳过坏行照供其余:读不出的那一行可能正是取代了旧决定的那一笔;不拒起跑:不供是安全方向,卡仍 pending、可再决)。决定的写口照旧由店闸住。
|
|
122
|
+
*/
|
|
123
|
+
export declare function heldWorkflowParkDecisions(sources: HeldWorkflowParkDecisionSources, hostSessionId: string, carried?: readonly ParkedResumeEntry[]): Promise<Pick<RunInternals, "workflowParkedResume">>;
|
|
93
124
|
/**
|
|
94
125
|
* pending checkpoint → parked bg 行匹配。
|
|
95
126
|
*
|
|
@@ -217,7 +248,7 @@ export interface ParkedDecideResult {
|
|
|
217
248
|
* 自铸的结算词是 pre-CAS 响亮拒)。
|
|
218
249
|
* · `answer` 原样透传([ref]:header 逐字匹配等语义校验全在 core,server 不预判)。
|
|
219
250
|
*/
|
|
220
|
-
export declare function buildParkedResumeOutcome(req: ParkedDecideRequest):
|
|
251
|
+
export declare function buildParkedResumeOutcome(req: ParkedDecideRequest): WorkflowParkOutcome;
|
|
221
252
|
/**
|
|
222
253
|
* S-185 车CM —— **第三条车道的计划**(纯函数;驱动本身归 resume 家族的那条腿,见下方「为什么不自建驱动」)。
|
|
223
254
|
*
|
|
@@ -234,12 +265,13 @@ export declare function buildParkedResumeOutcome(req: ParkedDecideRequest): Resu
|
|
|
234
265
|
* decided, the deployment resumes this run (resumeFromRunId: …)」。
|
|
235
266
|
* ⇒ 第三条车道 = **把决定挂在宿主会话的下一跑上**,而那一跑必须走 resume 家族**既有**的那条腿
|
|
236
267
|
* (`notify-wake.ts` 的成文纪律:wake 会烧模型,所以复用 `ctx.legs.resumeWake`,「而不是在本域自建第二条
|
|
237
|
-
* 驱动路径」)。本函数因此只出**计划**:宿主会话 + 要注入的消息 +
|
|
268
|
+
* 驱动路径」)。本函数因此只出**计划**:宿主会话 + 要注入的消息 + 要落成决定行的那一条决定(调用方受理时落行,宿主会话的每一跑
|
|
269
|
+
* 开跑前经那一只读者把它放进 internals)。
|
|
238
270
|
*
|
|
239
271
|
* ## 诚实边界(登记,不假装没有)
|
|
240
272
|
* · **模型中介**:决定送达宿主之后,真正的赎回发生在宿主再调一次 `Workflow({resumeFromRunId})` 时。
|
|
241
|
-
* core 的 park 回执逐字告诉模型这件事,但它不是一条确定性的机器腿。宿主没照做 ⇒ 卡仍 pending
|
|
242
|
-
*
|
|
273
|
+
* core 的 park 回执逐字告诉模型这件事,但它不是一条确定性的机器腿。宿主没照做 ⇒ 卡仍 pending、决定行还在:
|
|
274
|
+
* 宿主会话的下一跑(谁起的都算)照带它,同一个决定重投再触发一次投递(**不会**静默吃掉批准)。
|
|
243
275
|
* · **`inheritedGate` 不供**:那是「跨进程重供 checkpoint 的父约束」的席位,而 wa* 行不带父约束链;
|
|
244
276
|
* 同进程时 core 的内存 registry 自动重供,跨进程且该 cp 带 `requiresParentConstraint` 时 core 响亮拒
|
|
245
277
|
* (`resume.parent_constraint_missing`)⇒ 该 ordinal 再 park 一次,不会 fail-open。
|
|
@@ -257,7 +289,7 @@ export type WorkflowParkedDecidePlan = {
|
|
|
257
289
|
hostSessionId: string;
|
|
258
290
|
runId: string;
|
|
259
291
|
message: string;
|
|
260
|
-
outcome:
|
|
292
|
+
outcome: WorkflowParkOutcome;
|
|
261
293
|
} | {
|
|
262
294
|
ok: false;
|
|
263
295
|
deny: ParkedDecideResult;
|
|
@@ -311,4 +343,5 @@ export declare function planWorkflowParkedDecide(origin: Extract<ParkOrigin, {
|
|
|
311
343
|
* re-park 诚实可见,操作员可再决。
|
|
312
344
|
*/
|
|
313
345
|
export declare function decideParkedAgent(deps: ParkedDecideDeps, req: ParkedDecideRequest, match: ParkedAgentMatch): Promise<ParkedDecideResult>;
|
|
346
|
+
export {};
|
|
314
347
|
//# sourceMappingURL=parked-decide.d.ts.map
|
package/dist/parked-decide.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { readClosedWordSeat } from "./approval-card.js";
|
|
2
2
|
import { routeWorkflowPark } from "./orchestration/workflow-agent-session-index.js";
|
|
3
|
+
import { recordFailOpen } from "./observability/fail-open.js";
|
|
3
4
|
import { defaultSubagentTailBus } from "./fleet/subagent-tail-bus.js";
|
|
4
|
-
import { backgroundScopesForCheckpointScope, decodeCheckpointScope } from "./security.js";
|
|
5
|
+
import { backgroundScopesForCheckpointScope, decodeCheckpointScope, ownerOfCheckpointScope } from "./security.js";
|
|
5
6
|
import { ASK_USER_QUESTION_TOOL_NAME } from "./approval-content-kind.js";
|
|
6
7
|
import { sameSessionOccupant } from "./session-incarnation.js";
|
|
8
|
+
import { refusalBody } from "./http/refusal-body.js";
|
|
7
9
|
export async function findParkOrigin(sources, cp) {
|
|
8
10
|
if (sources.agentStore !== undefined) {
|
|
9
11
|
let match;
|
|
@@ -51,6 +53,33 @@ export async function findParkOrigin(sources, cp) {
|
|
|
51
53
|
return undefined;
|
|
52
54
|
}
|
|
53
55
|
}
|
|
56
|
+
export async function heldWorkflowParkDecisions(sources, hostSessionId, carried) {
|
|
57
|
+
const entries = [...(carried ?? [])];
|
|
58
|
+
const { workflowParkDecisions: decisions, checkpointStore: cs, workflowAgentSessionIndex: workflowIndex, workflowRunStore } = sources;
|
|
59
|
+
if (decisions !== undefined && cs !== undefined && workflowIndex !== undefined && workflowRunStore !== undefined) {
|
|
60
|
+
const own = new Set(entries.map((e) => String(e.token)));
|
|
61
|
+
const held = await decisions.listByHostSession(hostSessionId).then((rows) => ({ rows }), (err) => ({ err }));
|
|
62
|
+
if ("err" in held) {
|
|
63
|
+
recordFailOpen("server.workflow-park-decision.store-unreadable", `hostSessionId=${hostSessionId} err=${held.err instanceof Error ? held.err.message : String(held.err)}`);
|
|
64
|
+
return entries.length > 0 ? { workflowParkedResume: entries } : {};
|
|
65
|
+
}
|
|
66
|
+
for (const row of held.rows) {
|
|
67
|
+
if (own.has(String(row.token)))
|
|
68
|
+
continue;
|
|
69
|
+
const card = await cs.get(row.token).then((cp) => ({ cp }), (err) => ({ err }));
|
|
70
|
+
if ("err" in card) {
|
|
71
|
+
recordFailOpen("server.workflow-park-decision.card-unreadable", `runId=${row.runId} err=${card.err instanceof Error ? card.err.message : String(card.err)}`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (card.cp === null || card.cp.status !== "pending")
|
|
75
|
+
continue;
|
|
76
|
+
const origin = await findParkOrigin({ workflowIndex, workflowRunStore }, { token: row.token, scope: card.cp.scope, sessionId: card.cp.sessionId });
|
|
77
|
+
if (origin?.kind === "workflow")
|
|
78
|
+
entries.push({ runId: origin.runId, token: row.token, outcome: row.outcome });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return entries.length > 0 ? { workflowParkedResume: entries } : {};
|
|
82
|
+
}
|
|
54
83
|
function quiet(warn, event, fields) {
|
|
55
84
|
try {
|
|
56
85
|
warn?.(event, fields);
|
|
@@ -106,21 +135,25 @@ export function denyWorkflowParksUnreadable(origin) {
|
|
|
106
135
|
case "older_engine":
|
|
107
136
|
return {
|
|
108
137
|
status: 409,
|
|
109
|
-
body: {
|
|
110
|
-
error: "this decision cannot be matched to the pending step it belongs to: the run's record was written by an earlier engine version, which did not record which run is waiting on each pending step — and that record is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resume the run itself instead — `Workflow({resumeFromRunId})` with the runId below — and once the resumed run is waiting on this step again it records itself as the one waiting, after which deciding here works normally. Only if the engine also refuses that resume is the run truly unrecoverable",
|
|
138
|
+
body: refusalBody({
|
|
111
139
|
errorCode: "decide.workflow_parks_unreadable",
|
|
112
|
-
|
|
113
|
-
|
|
140
|
+
message: "this decision cannot be matched to the pending step it belongs to: the run's record was written by an earlier engine version, which did not record which run is waiting on each pending step — and that record is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resume the run itself instead — `Workflow({resumeFromRunId})` with the runId below — and once the resumed run is waiting on this step again it records itself as the one waiting, after which deciding here works normally. Only if the engine also refuses that resume is the run truly unrecoverable",
|
|
141
|
+
facts: {
|
|
142
|
+
runId: origin.runId,
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
114
145
|
};
|
|
115
146
|
case "unreadable":
|
|
116
147
|
return {
|
|
117
148
|
status: 409,
|
|
118
|
-
body: {
|
|
119
|
-
error: "this decision cannot be matched to the pending step it belongs to: this run's record cannot be read (the list of pending steps the run owns is damaged: one of its entries is malformed, or it is not a list at all) — and that list is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resuming does not clear this: the damaged record keeps naming this step whatever runs after it, so the decision stays undeliverable until whoever operates this deployment repairs that record (the runId below); after that, deciding here works normally. When the response also carries readableHolderRunId, that run's record is readable and is the latest one waiting on this step — it is where the work can be carried on, but the damaged record above still keeps this decision from being delivered until that record is fixed",
|
|
149
|
+
body: refusalBody({
|
|
120
150
|
errorCode: "decide.workflow_parks_unreadable",
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
151
|
+
message: "this decision cannot be matched to the pending step it belongs to: this run's record cannot be read (the list of pending steps the run owns is damaged: one of its entries is malformed, or it is not a list at all) — and that list is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resuming does not clear this: the damaged record keeps naming this step whatever runs after it, so the decision stays undeliverable until whoever operates this deployment repairs that record (the runId below); after that, deciding here works normally. When the response also carries readableHolderRunId, that run's record is readable and is the latest one waiting on this step — it is where the work can be carried on, but the damaged record above still keeps this decision from being delivered until that record is fixed",
|
|
152
|
+
facts: {
|
|
153
|
+
runId: origin.runId,
|
|
154
|
+
...(origin.readableHolderRunId !== undefined ? { readableHolderRunId: origin.readableHolderRunId } : {}),
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
124
157
|
};
|
|
125
158
|
default: {
|
|
126
159
|
const unhandled = origin.cause;
|
|
@@ -131,11 +164,13 @@ export function denyWorkflowParksUnreadable(origin) {
|
|
|
131
164
|
export function denyWorkflowParkForked(origin) {
|
|
132
165
|
return {
|
|
133
166
|
status: 409,
|
|
134
|
-
body: {
|
|
135
|
-
error: "this decision cannot be delivered: the same run was resumed more than once and every resumed copy listed in runIds is waiting on this same step, so there is no single run to hand the decision to. Nothing was delivered and the approval card stays pending. Resume one of the runs listed in runIds; once that run is waiting on this step again, deciding here works normally",
|
|
167
|
+
body: refusalBody({
|
|
136
168
|
errorCode: "decide.workflow_park_forked",
|
|
137
|
-
|
|
138
|
-
|
|
169
|
+
message: "this decision cannot be delivered: the same run was resumed more than once and every resumed copy listed in runIds is waiting on this same step, so there is no single run to hand the decision to. Nothing was delivered and the approval card stays pending. Resume one of the runs listed in runIds; once that run is waiting on this step again, deciding here works normally",
|
|
170
|
+
facts: {
|
|
171
|
+
runIds: [...origin.runIds],
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
139
174
|
};
|
|
140
175
|
}
|
|
141
176
|
export function planWorkflowParkedDecide(origin, req) {
|
|
@@ -144,11 +179,13 @@ export function planWorkflowParkedDecide(origin, req) {
|
|
|
144
179
|
ok: false,
|
|
145
180
|
deny: {
|
|
146
181
|
status: 400,
|
|
147
|
-
body: {
|
|
148
|
-
error: "remember:\"session\" is not supported for this approval: accepting it here only means the decision was handed on for delivery, not that the engine has applied it — an exemption granted now could outlive a decision the engine later rejects. Re-issue the decide without `remember`; the decision itself is accepted normally that way.",
|
|
182
|
+
body: refusalBody({
|
|
149
183
|
errorCode: "decide.workflow_remember_unsupported",
|
|
150
|
-
|
|
151
|
-
|
|
184
|
+
message: "remember:\"session\" is not supported for this approval: accepting it here only means the decision was handed on for delivery, not that the engine has applied it — an exemption granted now could outlive a decision the engine later rejects. Re-issue the decide without `remember`; the decision itself is accepted normally that way.",
|
|
185
|
+
facts: {
|
|
186
|
+
runId: origin.runId,
|
|
187
|
+
},
|
|
188
|
+
}),
|
|
152
189
|
},
|
|
153
190
|
};
|
|
154
191
|
}
|
|
@@ -158,11 +195,13 @@ export function planWorkflowParkedDecide(origin, req) {
|
|
|
158
195
|
ok: false,
|
|
159
196
|
deny: {
|
|
160
197
|
status: 409,
|
|
161
|
-
body: {
|
|
162
|
-
error: "this run was started on its own rather than from a session, so this deployment has nowhere to deliver the decision. Nothing was decided and the approval is still pending — resume the run yourself with the runId below and decide it there",
|
|
198
|
+
body: refusalBody({
|
|
163
199
|
errorCode: "decide.workflow_host_unknown",
|
|
164
|
-
|
|
165
|
-
|
|
200
|
+
message: "this run was started on its own rather than from a session, so this deployment has nowhere to deliver the decision. Nothing was decided and the approval is still pending — resume the run yourself with the runId below and decide it there",
|
|
201
|
+
facts: {
|
|
202
|
+
runId: origin.runId,
|
|
203
|
+
},
|
|
204
|
+
}),
|
|
166
205
|
},
|
|
167
206
|
};
|
|
168
207
|
}
|
|
@@ -181,29 +220,31 @@ export function planWorkflowParkedDecide(origin, req) {
|
|
|
181
220
|
function sessionGone(taskId) {
|
|
182
221
|
return {
|
|
183
222
|
status: 409,
|
|
184
|
-
body: {
|
|
185
|
-
error: "the session this agent belongs to was deleted (or deleted and started again under the same id) while its approval waited, so the approval no longer applies — nothing was resumed",
|
|
223
|
+
body: refusalBody({
|
|
186
224
|
errorCode: "decide.not_parked",
|
|
187
|
-
|
|
188
|
-
|
|
225
|
+
message: "the session this agent belongs to was deleted (or deleted and started again under the same id) while its approval waited, so the approval no longer applies — nothing was resumed",
|
|
226
|
+
facts: {
|
|
227
|
+
taskId,
|
|
228
|
+
},
|
|
229
|
+
}),
|
|
189
230
|
};
|
|
190
231
|
}
|
|
191
232
|
export async function decideParkedAgent(deps, req, match) {
|
|
192
233
|
const row = match.row;
|
|
193
234
|
const rememberRoot = req.grantRemember !== undefined ? grantRootOf(row) : undefined;
|
|
194
235
|
if (req.grantRemember !== undefined && rememberRoot === undefined) {
|
|
195
|
-
return { status: 400, body: {
|
|
236
|
+
return { status: 400, body: refusalBody({ errorCode: "decide.parked_remember_unsupported", message: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", facts: { taskId: match.handle } }) };
|
|
196
237
|
}
|
|
197
238
|
const pendingTool = req.pendingAction?.toolName;
|
|
198
239
|
if (pendingTool === ASK_USER_QUESTION_TOOL_NAME && req.decision === "approve" && req.answer === undefined) {
|
|
199
|
-
return { status: 400, body: {
|
|
240
|
+
return { status: 400, body: refusalBody({ errorCode: "decide.parked_answer_required", message: "pending action is AskUserQuestion — approve requires body.answer (the operator's answers[]); deny needs none", facts: { taskId: match.handle } }) };
|
|
200
241
|
}
|
|
201
242
|
if (row.name === undefined) {
|
|
202
|
-
return { status: 409, body: {
|
|
243
|
+
return { status: 409, body: refusalBody({ errorCode: "decide.row_unrevivable", message: "parked row carries no agent name — the revive path requires a named agent (row damaged?)", facts: { taskId: match.handle } }) };
|
|
203
244
|
}
|
|
204
245
|
const root = row.rootSessionId;
|
|
205
246
|
if (root === undefined) {
|
|
206
|
-
return { status: 409, body: {
|
|
247
|
+
return { status: 409, body: refusalBody({ errorCode: "decide.row_unrevivable", message: "this agent's row carries no root session anchor — the revive path cannot tell which session this approval belongs to (row damaged?)", facts: { taskId: match.handle } }) };
|
|
207
248
|
}
|
|
208
249
|
const faceBefore = await deps.sessionFaceOf(root);
|
|
209
250
|
if (faceBefore === undefined)
|
|
@@ -214,14 +255,14 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
214
255
|
if (!claim.ok) {
|
|
215
256
|
switch (claim.reason) {
|
|
216
257
|
case "store_unreachable":
|
|
217
|
-
return { status: 503, body: {
|
|
258
|
+
return { status: 503, body: refusalBody({ errorCode: "decide.store_unreachable", message: "the durable agent store is unreachable — retry", facts: { taskId: match.handle } }) };
|
|
218
259
|
case "claim_lost":
|
|
219
|
-
return { status: 409, body: {
|
|
260
|
+
return { status: 409, body: refusalBody({ errorCode: "decide.claim_lost", message: "the parked agent is already claimed — either a concurrent decide won (re-check the pending list), or a stale claim is pending automatic cleanup (retry after the stale-claim window)", facts: { taskId: match.handle } }) };
|
|
220
261
|
case "binding_broken":
|
|
221
262
|
case "checkpoint_not_pending":
|
|
222
|
-
return { status: 409, body: {
|
|
263
|
+
return { status: 409, body: refusalBody({ errorCode: "decide.gate_moved", message: "the approval gate moved under this decide (re-parked or already settled) — re-check the pending list", facts: { taskId: match.handle } }) };
|
|
223
264
|
default:
|
|
224
|
-
return { status: 409, body: {
|
|
265
|
+
return { status: 409, body: refusalBody({ errorCode: "decide.not_parked", message: "the parked agent moved under this decide (stopped or already decided)", facts: { taskId: match.handle } }) };
|
|
225
266
|
}
|
|
226
267
|
}
|
|
227
268
|
const ticket = claim.ticket;
|
|
@@ -281,7 +322,7 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
281
322
|
toolCallId: `drv-${ticket.claimId}`,
|
|
282
323
|
...(surface.mountsCallerTool !== undefined ? { mountsCallerTool: surface.mountsCallerTool } : {}),
|
|
283
324
|
...(deps.approverSeatFor !== undefined && seatRoot !== undefined
|
|
284
|
-
? { onAsk: deps.approverSeatFor({ owner:
|
|
325
|
+
? { onAsk: deps.approverSeatFor({ owner: ownerOfCheckpointScope(req.scope), taskId: match.handle, sessionId: seatRoot }) }
|
|
285
326
|
: {}),
|
|
286
327
|
reviveClaim: {
|
|
287
328
|
row: { ...ticket.row, parkClaimId: ticket.claimId },
|
|
@@ -302,12 +343,14 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
302
343
|
const disp = await rollback("execute_threw");
|
|
303
344
|
return {
|
|
304
345
|
status: 500,
|
|
305
|
-
body: {
|
|
306
|
-
error: `revive failed before the resume was driven: ${e instanceof Error ? e.message : String(e)}`,
|
|
346
|
+
body: refusalBody({
|
|
307
347
|
errorCode: "decide.revive_failed",
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
348
|
+
message: `revive failed before the resume was driven: ${e instanceof Error ? e.message : String(e)}`,
|
|
349
|
+
facts: {
|
|
350
|
+
taskId: match.handle,
|
|
351
|
+
rollback: disp,
|
|
352
|
+
},
|
|
353
|
+
}),
|
|
311
354
|
};
|
|
312
355
|
}
|
|
313
356
|
const isErr = typeof receipt === "object" && receipt !== null && receipt.isError === true;
|
|
@@ -319,23 +362,27 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
319
362
|
const cause = readClosedWordSeat(receiptDetails, "cause");
|
|
320
363
|
return {
|
|
321
364
|
status: 422,
|
|
322
|
-
body: {
|
|
323
|
-
error: typeof content === "string" ? content : "the parked resume failed during startup",
|
|
365
|
+
body: refusalBody({
|
|
324
366
|
errorCode: "parked_resume.startup_failed",
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
367
|
+
message: typeof content === "string" ? content : "the parked resume failed during startup",
|
|
368
|
+
facts: {
|
|
369
|
+
taskId: match.handle,
|
|
370
|
+
rollback: disp,
|
|
371
|
+
...(cause !== undefined ? { cause } : {}),
|
|
372
|
+
},
|
|
373
|
+
}),
|
|
329
374
|
};
|
|
330
375
|
}
|
|
331
376
|
return {
|
|
332
377
|
status: 409,
|
|
333
|
-
body: {
|
|
334
|
-
error: typeof content === "string" ? content : "revive was rejected by the delegation tool",
|
|
378
|
+
body: refusalBody({
|
|
335
379
|
errorCode: "decide.revive_rejected",
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
380
|
+
message: typeof content === "string" ? content : "revive was rejected by the delegation tool",
|
|
381
|
+
facts: {
|
|
382
|
+
taskId: match.handle,
|
|
383
|
+
rollback: disp,
|
|
384
|
+
},
|
|
385
|
+
}),
|
|
339
386
|
};
|
|
340
387
|
}
|
|
341
388
|
return { status: 200, body: { taskId: match.handle, status: "resuming", decision: req.decision } };
|
|
@@ -19,15 +19,22 @@
|
|
|
19
19
|
* 这里的第 ② 条是同一条事实在交座这一处的判据(规则只写在这里,腿只负责读两次)。根删除时把子孙的 parked 卡一并作废 = S-790 件 B
|
|
20
20
|
* (`boot/session-faces.ts` 的删除协调器)。
|
|
21
21
|
* · 只对**一层**行填座(`rootSessionId` 在场且 = `parentSessionId`:派它的 run 就是根会话的 run,列表正是那个 run 的挂载)。更深的行
|
|
22
|
-
* (孙代:派它的是一个子代,它的挂载是继承裁剪后的子集,行上读不出来)不填 ——
|
|
22
|
+
* (孙代:派它的是一个子代,它的挂载是继承裁剪后的子集,行上读不出来)不填 —— 无座 = core 的 fail-closed 臂;
|
|
23
23
|
* 行上带继承组成是 core #1112(7.32.x)的半场,到货再改读行。
|
|
24
24
|
* 近似如实记:重解的列表是**部署缺省**那一份,读不回那一 run 的逐请求差异(`settings.webSearch` 后端、center overlay 场景)——
|
|
25
25
|
* 座只判 bundle 实例的成员性,继承面是 `[...web, ...scaffolds]`,那两项差异不改变谁在面内。
|
|
26
|
+
*
|
|
27
|
+
* **属主来源(S-1770 / S-1808)与交座是两个独立判据**:赎回工具的停驻挂点(复活的子代再要审批时停驻,`plugins/session-store.ts`)按委派继承律定宿主行属主,
|
|
28
|
+
* 律要的是**委派树根的见证**:根 id(行上本来就带 `rootSessionId`)+ 判断那一刻读到的根行住客(赎回腿 claim 前后两读的那一位 —— 两读不是同一位时赎回腿整条拒,
|
|
29
|
+
* 走不到这里;读数缺席 ⇒ 见证不带住客,挂点那一刻根行在 ⇒ 停驻否决)。所以**每一行**都交出它({@link ScenarioContext} 的 `delegationRoot`):交座的一层行以
|
|
30
|
+
* `{ sessionId: root, delegationRoot }` 重解,不交座的行(更深的行、根住客已变的一层行、读数缺席)以 `{ delegationRoot }` 重解 —— 只喂停驻挂点,不挂任何会话级设施、
|
|
31
|
+
* 不带 principal,交座判据(上面三条)一个字不动。行上没有根 ⇒ boot 期那只裸 Agent(没有根可交 ⇒ 律给哨兵)。挂点那一刻根行已不在 ⇒ 律给哨兵;在而不是见证的那一位
|
|
32
|
+
* (批准之后删了、同 id 被重新登记)⇒ 停驻否决 —— 两件都在挂点那一侧判,与这里无关。
|
|
26
33
|
*/
|
|
27
34
|
import { type BackgroundAgentRecord, type ToolSpec } from "@sema-agent/core";
|
|
28
35
|
import type { Scenario } from "./capabilities/scenarios.js";
|
|
29
36
|
import { type SessionFace } from "./session-incarnation.js";
|
|
30
|
-
/** 一次赎回用的面:驱动的 Agent 工具
|
|
37
|
+
/** 一次赎回用的面:驱动的 Agent 工具(它的停驻挂点绑着行上的根)+ (交座时)与它同出一张列表的继承座。 */
|
|
31
38
|
export interface ParkedReviveSurface {
|
|
32
39
|
readonly reviveTool: ToolSpec;
|
|
33
40
|
/** 缺席 = 不交座(core fail-closed:复活的子代不继承任何场景层工具)。 */
|
|
@@ -7,18 +7,21 @@ export function createParkedReviveSurface(defaultScenario) {
|
|
|
7
7
|
return undefined;
|
|
8
8
|
return (row, identity) => {
|
|
9
9
|
const root = row.rootSessionId;
|
|
10
|
-
if (root === undefined
|
|
10
|
+
if (root === undefined)
|
|
11
11
|
return { reviveTool: bootTool };
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if ((face.before.owner ?? undefined) !== identity.principal || (face.after.owner ?? undefined) !== identity.principal)
|
|
16
|
-
return { reviveTool: bootTool };
|
|
17
|
-
const tools = defaultScenario({}, identity.principal, { sessionId: root }).tools;
|
|
12
|
+
const seated = holdsSeat(row.parentSessionId === root, identity);
|
|
13
|
+
const delegationRoot = { sessionId: root, incarnation: identity.root?.after.incarnation ?? null };
|
|
14
|
+
const tools = (seated ? defaultScenario({}, identity.principal, { sessionId: root, delegationRoot }) : defaultScenario({}, undefined, { delegationRoot })).tools;
|
|
18
15
|
const reviveTool = agentOf(tools);
|
|
19
16
|
if (reviveTool === undefined)
|
|
20
17
|
return { reviveTool: bootTool };
|
|
21
|
-
return { reviveTool, mountsCallerTool: (t) => tools.includes(t) };
|
|
18
|
+
return seated ? { reviveTool, mountsCallerTool: (t) => tools.includes(t) } : { reviveTool };
|
|
22
19
|
};
|
|
23
20
|
}
|
|
21
|
+
function holdsSeat(oneLevel, identity) {
|
|
22
|
+
const face = identity.root;
|
|
23
|
+
if (!oneLevel || face === undefined || !sameSessionOccupant(face.before, face.after))
|
|
24
|
+
return false;
|
|
25
|
+
return (face.before.owner ?? undefined) === identity.principal && (face.after.owner ?? undefined) === identity.principal;
|
|
26
|
+
}
|
|
24
27
|
//# sourceMappingURL=parked-revive-surface.js.map
|
package/dist/per-task-image.d.ts
CHANGED
|
@@ -4,13 +4,19 @@ import type { ImageViewer, ImageIndexEntry } from "./plugins/store-contracts.js"
|
|
|
4
4
|
export interface SandboxImageResolver {
|
|
5
5
|
latestPublished(profile: string, viewer: ImageViewer): Promise<Pick<ImageIndexEntry, "repo" | "digest" | "capabilities"> | null>;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* 解析失败的机读码(闭集):`not_found.image` = 按调用方的约束(档案 · 本主体可见 · 已发布 · 所需能力)找不到镜像 —— 与 `POST /v1/images/select`
|
|
9
|
+
* 「没有可见的已发布镜像」同一个码(同一个事实);`request.field_invalid` = `capabilitiesNeeded` 里有不认识的能力词。状态随码,一码一状态。
|
|
10
|
+
*/
|
|
11
|
+
export type SandboxImageRefusalCode = "not_found.image" | "request.field_invalid";
|
|
7
12
|
export type SandboxImageResolution = {
|
|
8
13
|
ok: true;
|
|
9
14
|
ref: string;
|
|
10
15
|
capabilities?: import("./plugins/store-contracts.js").ImageCapabilities;
|
|
11
16
|
} | {
|
|
12
17
|
ok: false;
|
|
13
|
-
status:
|
|
18
|
+
status: 404 | 400;
|
|
19
|
+
errorCode: SandboxImageRefusalCode;
|
|
14
20
|
message: string;
|
|
15
21
|
};
|
|
16
22
|
/**
|