@sema-agent/server 7.150.0 → 7.152.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 +451 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +144 -87
- package/deploy/sema-up/README.md +11 -4
- 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 +7 -6
- package/deploy/sema-up/kube-up.sh +6 -6
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +12 -14
- package/dist/approval-gate-currency.d.ts +9 -9
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.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 +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +3 -6
- package/dist/bind-host.js +4 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +9 -14
- package/dist/boot/execution-env.js +85 -22
- 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/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +6 -1
- package/dist/boot/reapers.js +13 -2
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +43 -48
- package/dist/boot/runner-deps.d.ts +46 -35
- package/dist/boot/runner-deps.js +94 -91
- 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 +9 -5
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +3 -2
- package/dist/boot/stage-06-runners.d.ts +9 -4
- package/dist/boot/stage-06-runners.js +24 -9
- package/dist/boot/stage-07-capability-layer.d.ts +8 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +8 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +12 -5
- package/dist/boot/stage-09-leader.js +14 -5
- package/dist/boot/stage-10-http-server.d.ts +19 -5
- package/dist/boot/stage-10-http-server.js +14 -21
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +5 -8
- 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/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +43 -32
- package/dist/capability-facts.js +45 -51
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- 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 +26 -22
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +20 -8
- package/dist/config-invariants.js +55 -12
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +38 -42
- package/dist/config.d.ts +58 -7
- package/dist/config.js +90 -40
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- 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 +7 -0
- package/dist/device-ws-hub.js +10 -3
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/elicitation.js +2 -2
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +29 -0
- package/dist/execution-env-refusal.js +8 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- 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 +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +18 -3
- package/dist/host-decision.d.ts +11 -11
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +10 -7
- package/dist/http/checkpoint-ctx.d.ts +4 -0
- package/dist/http/checkpoint-ctx.js +2 -0
- package/dist/http/dispatch.d.ts +8 -3
- package/dist/http/dispatch.js +59 -32
- package/dist/http/durable-run-leg.js +16 -17
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +3 -1
- package/dist/http/owner-access.d.ts +33 -14
- package/dist/http/owner-access.js +40 -10
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +42 -3
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +367 -117
- package/dist/http/route-ctx.d.ts +91 -15
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +5 -1
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +99 -51
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +38 -10
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +171 -65
- package/dist/http/routes/session-sync.d.ts +22 -9
- package/dist/http/routes/session-sync.js +204 -107
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +30 -15
- package/dist/http/routes/tasks.js +46 -41
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +30 -30
- package/dist/http/server.js +16 -4
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +7 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +2 -2
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +116 -11
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +23 -11
- package/dist/memory-scope.js +18 -6
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +25 -17
- package/dist/observability/fail-open.js +25 -17
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- 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/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +2 -2
- package/dist/parked-decide.d.ts +106 -55
- 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/permission-mode-admission.d.ts +74 -5
- package/dist/permission-mode-admission.js +56 -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 +14 -2
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
- package/dist/plugins/approval-ask-store-memory.js +35 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
- package/dist/plugins/approval-ask-store-sql.js +45 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- 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/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- 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/execution-placement-sql.js +6 -6
- 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 +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- 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-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +104 -80
- package/dist/plugins/one-time-migrations.js +226 -132
- 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 +35 -10
- 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 +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- 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 +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +46 -10
- package/dist/plugins/remote-env-host.js +124 -52
- package/dist/plugins/remote-env-k8s.d.ts +109 -41
- package/dist/plugins/remote-env-k8s.js +160 -54
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- 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.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 +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +5 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- 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/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -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/sql-json-column.d.ts +1 -1
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- 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 +84 -15
- package/dist/plugins/store-backend.js +236 -72
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -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.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +14 -1
- 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 +21 -25
- 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-custody.d.ts +4 -3
- 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/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- 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/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +9 -9
- package/dist/runs.d.ts +54 -16
- package/dist/runs.js +67 -13
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- 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 +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +25 -103
- package/dist/session-sync.js +14 -76
- 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/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
- package/dist/stores-sql/file-history-store-sql.js +205 -95
- 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 +1 -9
- package/dist/stores-sql/retention-store-sql.js +5 -19
- 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 +2 -2
- package/dist/task-settings.d.ts +7 -5
- package/dist/task-settings.js +3 -3
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +465 -507
- package/dist/tool-approval.js +606 -1222
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +571 -178
- package/dist/trace/self-minted-wire.js +189 -56
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
- package/package.json +7 -3
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.151.0.json +762 -0
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
package/dist/http/resume-legs.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { uuidv7, resumeWithVerification, resumeCascade, CheckpointError, judgeCheckpointRow, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
|
|
4
|
-
import { decideParkedAgent,
|
|
4
|
+
import { answerOfHolderFence, answerOfHolderRedeem, decideParkedAgent, deliverableEntryOf, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, holderFenceFaultAnswer, planWorkflowParkedDecide, redeemHere, runChannelEnded, workflowParkGuidance } from "../parked-decide.js";
|
|
5
5
|
import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
|
|
6
|
-
import {
|
|
6
|
+
import { heldParksOf, readRunParks } from "../orchestration/workflow-agent-session-index.js";
|
|
7
|
+
import { isAdoptionQuiescing, trackMaintenanceLeg } from "../adoption/quiesce.js";
|
|
8
|
+
import { runFactsOf, sealRouteDeps, sessionFactsReadOf, sessionOccupantReadOf } from "./owner-access.js";
|
|
7
9
|
import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
|
|
8
10
|
const DELIVERY_NOT_RECORDED = "workflow park decide: this delivery no longer holds the host session (its claim was released) — the decision was not recorded and this delivery was not started";
|
|
9
|
-
import { HttpError, checkpointPartsOf, decodeCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
11
|
+
import { HttpError, checkpointPartsOf, decodeCheckpointScope, ownerOfCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
10
12
|
import { keyAdmits } from "../owner-faces.js";
|
|
11
13
|
import { personOf } from "../owner-brands.js";
|
|
12
14
|
import { recoveredSubject } from "../owner-faces.js";
|
|
13
|
-
import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
|
|
15
|
+
import { beatRunHeartbeat, createRunAnchorWriter, graftParkToolCallId, heldParkOf, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
|
|
14
16
|
import { commitParkRow } from "../park-row-commit.js";
|
|
15
17
|
import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane, outwardThrownMessage } from "../terminal.js";
|
|
16
18
|
import { voidVerifierPauseCard } from "../verifier-pause-card.js";
|
|
@@ -22,7 +24,7 @@ import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotific
|
|
|
22
24
|
import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals } from "../fleet/fleet-bus.js";
|
|
23
25
|
import { defaultSubagentTailBus } from "../fleet/subagent-tail-bus.js";
|
|
24
26
|
import { currentApprovalGateToken, currentGateFacesOf, sightsCurrentGate } from "../approval-gate-currency.js";
|
|
25
|
-
import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
|
|
27
|
+
import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, readCardRuleRecordOfAskRow, readCardRuleRecordOfParkRow, redeemCardRule, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
|
|
26
28
|
import { createHitlTransport } from "../hitl-delivery.js";
|
|
27
29
|
import { buildCheckpointAnchorHash } from "../approval-ask-audit-store.js";
|
|
28
30
|
import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
|
|
@@ -60,7 +62,7 @@ import { buildActiveRunConflict, resumeEntryForGate } from "./active-run-conflic
|
|
|
60
62
|
import { refusalAfterLostClaim } from "./claim-heartbeat.js";
|
|
61
63
|
import { CONTINUATION_CLAIM_FACE, ClaimFaultAnswer, commitExecutionContext, faultedAnswerOf, isRootSessionGoneError, resolveBeforeClaim, rootSessionAbsentAnswer, stampSpecRoot, withdrawClaim } from "./execution-context.js";
|
|
62
64
|
import { timeClaim } from "./claim-latency.js";
|
|
63
|
-
import {
|
|
65
|
+
import { commitLegBindings } from "../session-bindings.js";
|
|
64
66
|
import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
|
|
65
67
|
import { deploymentListAsks } from "../approval.js";
|
|
66
68
|
import { isParkLedgerEventType } from "../trace/ledger-events.js";
|
|
@@ -70,11 +72,18 @@ import { buildCheckpointVersionKeys, resumeAssemblyRefusalAnswer, resumeRefusalW
|
|
|
70
72
|
import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
|
|
71
73
|
import { storedBodyReplayRefusal } from "./stored-body-replay.js";
|
|
72
74
|
import { restateResumeCtx } from "./resume-restatement.js";
|
|
75
|
+
import { stampReplayEntryMode, withStoredPermissionMode } from "../permission-mode-admission.js";
|
|
73
76
|
import { httpErrorRefusal } from "./send.js";
|
|
74
77
|
import { createRunAcceptance } from "../run-acceptance.js";
|
|
75
78
|
import { createSubmissionSeat } from "../submission-exit.js";
|
|
76
79
|
import { fieldConflictFacts } from "../field-conflict.js";
|
|
77
80
|
import { createSessionNotifyDoor } from "../session-notify-door.js";
|
|
81
|
+
const HANDOFF_RETRY_CODES = new Set(["conflict.session_active_run", "not_found.parked_checkpoint", "conflict.claim_lost"]);
|
|
82
|
+
function handoffResultOf(refusal, refusedWhy) {
|
|
83
|
+
const errorCode = "errorCode" in refusal.body ? refusal.body.errorCode : undefined;
|
|
84
|
+
const code = typeof errorCode === "string" ? errorCode : `status_${refusal.status}`;
|
|
85
|
+
return refusal.status >= 500 || HANDOFF_RETRY_CODES.has(code) ? { kind: "retry", why: code } : { kind: "refused", why: refusedWhy ?? code };
|
|
86
|
+
}
|
|
78
87
|
function compositionUnlinkedAnswer() {
|
|
79
88
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context does not match this card — the run is a cascade but the card records no ladder rung, so the ladder cannot be continued" }) };
|
|
80
89
|
}
|
|
@@ -210,6 +219,35 @@ function decisionRefusalCauseOf(e, gate) {
|
|
|
210
219
|
function notResumableAnswer() {
|
|
211
220
|
return { status: 409, body: refusalBody({ errorCode: "conflict.not_resumable", message: "run is not in a resumable (suspended) state (already resumed, decided, or expired)" }) };
|
|
212
221
|
}
|
|
222
|
+
function planeOfEndedRow(row) {
|
|
223
|
+
return { status: row?.status ?? "failed", errorCode: row?.errorCode ?? undefined, errorMessage: row?.error ?? undefined };
|
|
224
|
+
}
|
|
225
|
+
async function landedTerminalRow(runStore, taskId, arm) {
|
|
226
|
+
let row;
|
|
227
|
+
try {
|
|
228
|
+
row = await runStore.getRun(taskId);
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
recordFailOpen("server.resume.cancel-answer-row-unreadable", `task=${taskId} arm=${arm} err=${errorText(e)}`);
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
return row !== undefined && isTerminalRunStatus(row.status) ? row : undefined;
|
|
235
|
+
}
|
|
236
|
+
function settledLegAnswer(o) {
|
|
237
|
+
return {
|
|
238
|
+
status: 200,
|
|
239
|
+
body: {
|
|
240
|
+
...(o.taskId !== undefined ? { taskId: o.taskId } : {}),
|
|
241
|
+
sessionId: o.sessionId,
|
|
242
|
+
status: o.plane.status,
|
|
243
|
+
bindingEnforced: true,
|
|
244
|
+
...(o.plane.errorCode ? { errorCode: o.plane.errorCode } : {}),
|
|
245
|
+
...(o.plane.errorMessage ? { errorMessage: redactErrorMessage(o.plane.errorMessage) ?? "" } : {}),
|
|
246
|
+
...(o.reparked ? { retriable: true } : {}),
|
|
247
|
+
...o.evidence,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
213
251
|
function resumeClaimFaultAnswerOf(e) {
|
|
214
252
|
return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
|
|
215
253
|
}
|
|
@@ -270,7 +308,7 @@ function acceptableFormFacts(detail) {
|
|
|
270
308
|
const rewritten = detail !== null && typeof detail === "object" ? detail.editRewritten : undefined;
|
|
271
309
|
if (rewritten === null || typeof rewritten !== "object" || !Object.hasOwn(rewritten, "acceptableForm"))
|
|
272
310
|
return {};
|
|
273
|
-
const shown = approverFacingArgs(rewritten.acceptableForm);
|
|
311
|
+
const shown = approverFacingArgs(rewritten.acceptableForm, undefined);
|
|
274
312
|
return shown === undefined ? {} : { acceptableForm: shown };
|
|
275
313
|
}
|
|
276
314
|
export function checkpointRefusalAnswer(e, at) {
|
|
@@ -302,6 +340,12 @@ export function decidedActionOf(binding) {
|
|
|
302
340
|
export function createResumeLegs(ctx) {
|
|
303
341
|
const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor } = ctx;
|
|
304
342
|
const ctxOpening = (sessionId) => ({ sessionId, opener: deps.checkpointCtxSealing });
|
|
343
|
+
const replayCtxOf = (stored, restatement) => {
|
|
344
|
+
const restated = restateResumeCtx(stored, restatement);
|
|
345
|
+
if (restated.unattendedLeg === true)
|
|
346
|
+
return restated;
|
|
347
|
+
return stampReplayEntryMode(restated, deps.config);
|
|
348
|
+
};
|
|
305
349
|
const resumeFleetScope = (req, auth) => req ? (gatedSubject(req, deps.config) ?? "default") : (auth.subject ?? "default");
|
|
306
350
|
function createRememberIntent(sessionId, remember) {
|
|
307
351
|
let pending;
|
|
@@ -327,9 +371,23 @@ export function createResumeLegs(ctx) {
|
|
|
327
371
|
},
|
|
328
372
|
};
|
|
329
373
|
}
|
|
330
|
-
|
|
374
|
+
function createRuleIntent(persistRule) {
|
|
375
|
+
let reading;
|
|
376
|
+
return {
|
|
377
|
+
record: (r) => {
|
|
378
|
+
reading = r;
|
|
379
|
+
},
|
|
380
|
+
settle: async (committed) => {
|
|
381
|
+
if (!committed || reading === undefined)
|
|
382
|
+
return { rulePersisted: false, ruleRefusal: "rule_lane_unavailable" };
|
|
383
|
+
return redeemCardRule(deps.ruleConsent, reading, persistRule.slot, { inputWasEdited: persistRule.inputWasEdited, eligible: true });
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
async function resumeCheckpoint(sessionId, decision, reason, hostDecision, req, answer, binding, remember, acceptEarly, decider, restatement, persistRule) {
|
|
331
388
|
const cs = deps.checkpointStore;
|
|
332
389
|
const intent = remember !== undefined ? createRememberIntent(sessionId, remember) : undefined;
|
|
390
|
+
const ruleIntent = persistRule !== undefined ? createRuleIntent(persistRule) : undefined;
|
|
333
391
|
const token = await currentApprovalGateToken(cs, sessionId);
|
|
334
392
|
if (binding.checkpointToken && !sightsCurrentGate({ face: "checkpointToken", value: binding.checkpointToken }, token ? { checkpointToken: token } : null)) {
|
|
335
393
|
let seenUnreadable = false;
|
|
@@ -460,12 +518,36 @@ export function createResumeLegs(ctx) {
|
|
|
460
518
|
return approvalStaleAnswer(s57CurrentPending ? { currentPending: s57CurrentPending } : {});
|
|
461
519
|
}
|
|
462
520
|
const paForGrant = cp.pendingAction.kind === "tool_approval" ? cp.pendingAction : undefined;
|
|
521
|
+
const parkFacts = paForGrant !== undefined && paForGrant.toolName ? parkRowStandingAnswerFacts(paForGrant, cp.gate, deps.config, deploymentListAsks(deps.config, { toolName: paForGrant.toolName })) : undefined;
|
|
463
522
|
const rememberableTool = paForGrant !== undefined &&
|
|
464
|
-
|
|
523
|
+
parkFacts !== undefined &&
|
|
465
524
|
paForGrant.toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
466
|
-
standingAnswerDurablyRecordable(
|
|
525
|
+
standingAnswerDurablyRecordable(parkFacts)
|
|
467
526
|
? paForGrant.toolName
|
|
468
527
|
: null;
|
|
528
|
+
if (ruleIntent !== undefined) {
|
|
529
|
+
const owner = ownerOfCheckpointScope(cp.scope);
|
|
530
|
+
if (paForGrant === undefined || parkFacts === undefined || !token || !paForGrant.toolCallId || !paForGrant.boundInputHash)
|
|
531
|
+
ruleIntent.record({ kind: "absent", refusal: "rule_material_absent" });
|
|
532
|
+
else {
|
|
533
|
+
const asked = deps.toolApproval !== undefined ? await deps.toolApproval.readParkedAskOfGate(cp.sessionId, { boundCallId: paForGrant.toolCallId, boundInputHash: paForGrant.boundInputHash }) : { kind: "none" };
|
|
534
|
+
switch (asked.kind) {
|
|
535
|
+
case "row":
|
|
536
|
+
ruleIntent.record(readCardRuleRecordOfAskRow(asked.row, owner));
|
|
537
|
+
break;
|
|
538
|
+
case "unreadable":
|
|
539
|
+
ruleIntent.record({ kind: "absent", refusal: "rule_store_error" });
|
|
540
|
+
break;
|
|
541
|
+
case "none":
|
|
542
|
+
ruleIntent.record(readCardRuleRecordOfParkRow(paForGrant, { owner, governanceForced: parkFacts.governanceForced, scopeRoot: await cs.cardScopeRootOf(token) }));
|
|
543
|
+
break;
|
|
544
|
+
default: {
|
|
545
|
+
const unhandled = asked;
|
|
546
|
+
throw new Error(`resumeCheckpoint: unhandled parked-ask reading ${JSON.stringify(unhandled)}`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
469
551
|
const boundGrant = intent
|
|
470
552
|
? (overrideSessionId) => intent.record({ ...(overrideSessionId !== undefined ? { overrideSessionId } : {}), rememberableToolName: rememberableTool })
|
|
471
553
|
: undefined;
|
|
@@ -490,7 +572,11 @@ export function createResumeLegs(ctx) {
|
|
|
490
572
|
const landAfterCommit = async (out) => {
|
|
491
573
|
const committed = decisionCommittedOf(out);
|
|
492
574
|
noteLateSettleIfAccepted(committed);
|
|
493
|
-
return
|
|
575
|
+
return {
|
|
576
|
+
...out,
|
|
577
|
+
...(intent !== undefined ? { rememberApplied: await intent.settle(committed) } : {}),
|
|
578
|
+
...(ruleIntent !== undefined ? { ruleReceipt: await ruleIntent.settle(committed) } : {}),
|
|
579
|
+
};
|
|
494
580
|
};
|
|
495
581
|
const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
|
|
496
582
|
if (parkedForkQuotaDenial)
|
|
@@ -569,73 +655,56 @@ export function createResumeLegs(ctx) {
|
|
|
569
655
|
if (!plan.ok)
|
|
570
656
|
return plan.deny;
|
|
571
657
|
const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
|
|
572
|
-
const live = await deliverToHoldingRun(origin, { token, outcome: plan.outcome, decision: parkedReq.decision, fingerprint, restated: restatement !== undefined });
|
|
573
|
-
if (live.kind === "answered")
|
|
574
|
-
return live.answer;
|
|
575
658
|
const decisions = deps.workflowParkDecisions;
|
|
576
|
-
|
|
577
|
-
if (decisions === undefined || runStore === undefined) {
|
|
659
|
+
if (decisions === undefined || deps.runStore === undefined) {
|
|
578
660
|
return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
|
|
579
661
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return undefined;
|
|
583
|
-
const run = await runFactsOf(runStore, held.deliveredTaskId);
|
|
584
|
-
return run != null && !isTerminalRunStatus(run.status) ? acceptedResumingReceipt(held.deliveredTaskId, held.hostSessionId, NO_SETTLEMENT_EVIDENCE) : undefined;
|
|
585
|
-
};
|
|
586
|
-
const replay = await liveReceiptOf(await decisions.get(token));
|
|
587
|
-
if (replay !== undefined)
|
|
588
|
-
return replay;
|
|
589
|
-
let recordFailure;
|
|
590
|
-
const answerOfRecordFailure = async (failed) => {
|
|
591
|
-
if (failed.kind === "faulted")
|
|
592
|
-
return faultedAnswerOf(failed.err, CONTINUATION_CLAIM_FACE.faulted);
|
|
662
|
+
if (origin.run.status === "running") {
|
|
663
|
+
let verdict;
|
|
593
664
|
try {
|
|
594
|
-
|
|
665
|
+
verdict = await decisions.recordForRunningHolder({ token, runId: plan.runId, hostSessionId: plan.hostSessionId, outcome: plan.outcome, fingerprint, deliveredTaskId: plan.runId, acceptedAtMs: Date.now() }, { restated: restatement !== undefined });
|
|
595
666
|
}
|
|
596
|
-
catch (
|
|
597
|
-
return faultedAnswerOf(
|
|
667
|
+
catch (err) {
|
|
668
|
+
return faultedAnswerOf(err, () => holderFenceFaultAnswer(plan.runId));
|
|
598
669
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
if (!recorded) {
|
|
612
|
-
recordFailure = { kind: "not_recorded", deliveredTaskId };
|
|
613
|
-
throw new Error(DELIVERY_NOT_RECORDED);
|
|
670
|
+
switch (verdict) {
|
|
671
|
+
case "not_running":
|
|
672
|
+
break;
|
|
673
|
+
case "not_held":
|
|
674
|
+
case "restated":
|
|
675
|
+
case "other_decision":
|
|
676
|
+
return answerOfHolderFence(verdict, plan.runId);
|
|
677
|
+
case "stands":
|
|
678
|
+
return answerOfHolderRedeem(await redeemHere(plan.runId, origin.run.scope, { token, outcome: plan.outcome }), plan.runId, parkedReq.decision);
|
|
679
|
+
default: {
|
|
680
|
+
const unhandled = verdict;
|
|
681
|
+
throw new Error(`unhandled workflow holder fence verdict: ${String(unhandled)}`);
|
|
614
682
|
}
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
const hostToken = await cs
|
|
618
|
-
.findPendingTokenBySession(plan.hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" })
|
|
619
|
-
.catch(() => undefined);
|
|
620
|
-
const admittedPayer = decodeCheckpointScope(cp.scope);
|
|
621
|
-
let out;
|
|
622
|
-
try {
|
|
623
|
-
out = hostToken
|
|
624
|
-
? await resumeWake(plan.hostSessionId, plan.message, decider?.subject, req, acceptEarly, delivery, admittedPayer, restatement)
|
|
625
|
-
: await startFreshHostTurn(plan.hostSessionId, plan.message.text, admittedPayer, req, delivery, plan.runId, restatement);
|
|
683
|
+
}
|
|
626
684
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
685
|
+
const laned = await deliverViaResumeLane({
|
|
686
|
+
hostSessionId: plan.hostSessionId,
|
|
687
|
+
runId: plan.runId,
|
|
688
|
+
runScope: origin.run.scope,
|
|
689
|
+
token,
|
|
690
|
+
outcome: plan.outcome,
|
|
691
|
+
fingerprint,
|
|
692
|
+
message: plan.message,
|
|
693
|
+
...(restatement !== undefined ? { restatement } : {}),
|
|
694
|
+
initiator: { kind: "decide", req, caller: decider?.subject, ...(acceptEarly === true ? { acceptEarly: true } : {}), admittedPayer: decodeCheckpointScope(cp.scope) },
|
|
695
|
+
});
|
|
696
|
+
switch (laned.kind) {
|
|
697
|
+
case "launched":
|
|
698
|
+
case "replayed":
|
|
699
|
+
case "refused":
|
|
700
|
+
return laned.out;
|
|
701
|
+
case "record_failed":
|
|
702
|
+
return await answerOfRecordFailure(laned.failure, plan.hostSessionId);
|
|
703
|
+
default: {
|
|
704
|
+
const unhandled = laned;
|
|
705
|
+
throw new Error(`unhandled resume lane delivery: ${JSON.stringify(unhandled)}`);
|
|
706
|
+
}
|
|
632
707
|
}
|
|
633
|
-
const failed = recordFailure;
|
|
634
|
-
if (failed !== undefined)
|
|
635
|
-
return await answerOfRecordFailure(failed);
|
|
636
|
-
if (acceptedTaskIdOf(out) === undefined)
|
|
637
|
-
return (await liveReceiptOf(await decisions.get(token))) ?? out;
|
|
638
|
-
return out;
|
|
639
708
|
}
|
|
640
709
|
}
|
|
641
710
|
const runCtx = await ctxPromise;
|
|
@@ -644,7 +713,7 @@ export function createResumeLegs(ctx) {
|
|
|
644
713
|
if (runCtx === undefined || runCtx.ctx === null)
|
|
645
714
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
646
715
|
const { runSessionId, ctx: storedCtx } = runCtx;
|
|
647
|
-
const ctx =
|
|
716
|
+
const ctx = replayCtxOf(storedCtx, restatement);
|
|
648
717
|
const auth = { sessionId: runSessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
649
718
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
650
719
|
if (!resolved.ok)
|
|
@@ -691,6 +760,7 @@ export function createResumeLegs(ctx) {
|
|
|
691
760
|
onNotice: (n) => engineNotices.push(n),
|
|
692
761
|
...(ctx.unattendedLeg === true ? { unattendedLeg: true } : {}),
|
|
693
762
|
...(ctx.projectContext !== undefined ? { projectContext: ctx.projectContext } : {}),
|
|
763
|
+
...(ctx.memorySeed !== undefined ? { memorySeed: ctx.memorySeed } : {}),
|
|
694
764
|
lease,
|
|
695
765
|
execution,
|
|
696
766
|
});
|
|
@@ -771,7 +841,6 @@ export function createResumeLegs(ctx) {
|
|
|
771
841
|
const legKey = createHash("sha256").update(String(token)).digest("hex");
|
|
772
842
|
const streamApprovalOn = resolveStreamApprovalGate({
|
|
773
843
|
toolApprovalEnabled: Boolean(deps.toolApproval),
|
|
774
|
-
streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
|
|
775
844
|
backend: deps.backend,
|
|
776
845
|
checkpointStore: deps.checkpointStore,
|
|
777
846
|
}).active;
|
|
@@ -797,7 +866,7 @@ export function createResumeLegs(ctx) {
|
|
|
797
866
|
let legClaim;
|
|
798
867
|
let engineHandedOff = false;
|
|
799
868
|
let restored;
|
|
800
|
-
const
|
|
869
|
+
const claimWindowCancelRow = () => (restored?.kind === "ended" && restored.row?.errorCode === CANCELLED_CODE ? restored.row : undefined);
|
|
801
870
|
if (args.mintFreshRun && taskId && deps.runStore) {
|
|
802
871
|
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, taskId) };
|
|
803
872
|
}
|
|
@@ -948,7 +1017,8 @@ export function createResumeLegs(ctx) {
|
|
|
948
1017
|
if (placementReject) {
|
|
949
1018
|
if (inflightRuns.get(claimedTask) === cancelCtrl)
|
|
950
1019
|
inflightRuns.delete(claimedTask);
|
|
951
|
-
|
|
1020
|
+
const cancelledRow = claimWindowCancelRow();
|
|
1021
|
+
return cancelledRow !== undefined ? settledLegAnswer({ taskId: claimedTask, sessionId, plane: planeOfEndedRow(cancelledRow), reparked: false, evidence: NO_SETTLEMENT_EVIDENCE }) : placementReject;
|
|
952
1022
|
}
|
|
953
1023
|
}
|
|
954
1024
|
markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, subject);
|
|
@@ -979,7 +1049,7 @@ export function createResumeLegs(ctx) {
|
|
|
979
1049
|
...heldDecisions,
|
|
980
1050
|
...(workflowDecision !== undefined && taskId !== undefined ? { afterCheckpointResolve: () => workflowDecision.commitBeforeLaunch(taskId) } : {}),
|
|
981
1051
|
};
|
|
982
|
-
|
|
1052
|
+
commitLegBindings(deps, undefined, sessionId, args.legFacts?.sessionBindings);
|
|
983
1053
|
if (args.onResumeCommitted)
|
|
984
1054
|
await args.onResumeCommitted();
|
|
985
1055
|
let unregisterEngineNotice;
|
|
@@ -1036,7 +1106,7 @@ export function createResumeLegs(ctx) {
|
|
|
1036
1106
|
const verifyTailContentMode = resumeTaskConfig.forwardSubagentEvents === true ? "on" : "progress_only";
|
|
1037
1107
|
const verifyInternals = {
|
|
1038
1108
|
...launchInternals,
|
|
1039
|
-
...compositionLegRoot(args.legFacts?.
|
|
1109
|
+
...compositionLegRoot(args.legFacts?.sessionBindings.cwd),
|
|
1040
1110
|
...(taskId ? { onActivity: () => recordTurnActivity(taskId) } : {}),
|
|
1041
1111
|
onForwardEvent: (e) => {
|
|
1042
1112
|
fleetPub?.onForwardEvent(e);
|
|
@@ -1148,15 +1218,18 @@ export function createResumeLegs(ctx) {
|
|
|
1148
1218
|
const append = (type, data) => (rs && taskId ? serialAppend(type, data) : Promise.resolve());
|
|
1149
1219
|
cancelLedgerAppend = append;
|
|
1150
1220
|
await openEngineNoticePort(append);
|
|
1151
|
-
const anchorOwner = subject ?? null;
|
|
1152
1221
|
const sessionFactsOf = sessionFactsReadOf(deps.sessionStorage);
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
:
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
:
|
|
1222
|
+
const anchors = createRunAnchorWriter({
|
|
1223
|
+
seat: deps.backend?.landedAttendants(),
|
|
1224
|
+
sessionId,
|
|
1225
|
+
owner: subject ?? null,
|
|
1226
|
+
promptKey: taskId && freshRunClaimed ? taskId : undefined,
|
|
1227
|
+
witness: args.legFacts?.sessionWitness,
|
|
1228
|
+
occupantOf: sessionOccupantReadOf(deps.sessionStorage),
|
|
1229
|
+
leafOf: sessionFactsOf === undefined ? undefined : async (id) => (await sessionFactsOf(id))?.leafId,
|
|
1230
|
+
});
|
|
1231
|
+
const captureTurnAnchor = anchors.turn;
|
|
1232
|
+
const captureUserMessageAnchor = anchors.prompt;
|
|
1160
1233
|
const anchor = new TurnAnchorCapture(captureTurnAnchor, "resume", captureUserMessageAnchor);
|
|
1161
1234
|
const flush = async () => {
|
|
1162
1235
|
if (reasoning) {
|
|
@@ -1430,16 +1503,19 @@ export function createResumeLegs(ctx) {
|
|
|
1430
1503
|
const disposition = resumeRefusalDisposition(e);
|
|
1431
1504
|
if (disposition === "cancelled") {
|
|
1432
1505
|
const abortedText = (await settleCardForCancel()) ? CARD_SETTLED_BY_CANCEL_MESSAGE : e.message;
|
|
1506
|
+
const handleCause = cancelCtrl.cause();
|
|
1507
|
+
if (handleCause === undefined)
|
|
1508
|
+
recordFailOpen("server.runs.abort-cause-missing", `task=${taskId ?? ""} arm=resume-aborted`);
|
|
1509
|
+
const c = mintCancelledResult({ taskId: taskId ?? "", sessionId, startedAtMs: resumeLegStartedAt, message: abortedText, cause: handleCause ?? "cancel_verb" });
|
|
1510
|
+
const cancelled = outwardPlane(c.terminal);
|
|
1511
|
+
let landed;
|
|
1433
1512
|
if (claimedRow && taskId && deps.runStore) {
|
|
1434
|
-
const handleCause = cancelCtrl.cause();
|
|
1435
|
-
if (handleCause === undefined)
|
|
1436
|
-
recordFailOpen("server.runs.abort-cause-missing", `task=${taskId} arm=resume-aborted`);
|
|
1437
|
-
const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: abortedText, cause: handleCause ?? "cancel_verb" });
|
|
1438
1513
|
await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-resume-aborted ${errorText(err)}`));
|
|
1439
|
-
await deps.runStore.setTerminal(taskId, "failed", c,
|
|
1514
|
+
await deps.runStore.setTerminal(taskId, "failed", c, cancelled.errorMessage ?? null).catch(() => undefined);
|
|
1515
|
+
landed = await landedTerminalRow(deps.runStore, taskId, "resume-aborted");
|
|
1440
1516
|
}
|
|
1441
1517
|
settleFleet("failed");
|
|
1442
|
-
return {
|
|
1518
|
+
return settledLegAnswer({ taskId, sessionId, plane: landed !== undefined ? planeOfEndedRow(landed) : cancelled, reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
|
|
1443
1519
|
}
|
|
1444
1520
|
const retriable = disposition === "retriable";
|
|
1445
1521
|
let reparkEnded = false;
|
|
@@ -1466,22 +1542,26 @@ export function createResumeLegs(ctx) {
|
|
|
1466
1542
|
}
|
|
1467
1543
|
const thrownCause = cancelCtrl.cause();
|
|
1468
1544
|
if (thrownCause !== undefined) {
|
|
1545
|
+
const c = mintCancelledResult({ taskId: taskId ?? "", sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", cause: thrownCause });
|
|
1546
|
+
const cancelled = outwardPlane(c.terminal);
|
|
1547
|
+
let landed;
|
|
1469
1548
|
if (taskId && deps.runStore) {
|
|
1470
1549
|
await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
|
|
1471
|
-
const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", cause: thrownCause });
|
|
1472
1550
|
await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-thrown-cancel ${errorText(err)}`));
|
|
1473
|
-
await deps.runStore.setTerminal(taskId, "failed", c,
|
|
1551
|
+
await deps.runStore.setTerminal(taskId, "failed", c, cancelled.errorMessage ?? null).catch(() => undefined);
|
|
1552
|
+
landed = await landedTerminalRow(deps.runStore, taskId, "thrown-cancel");
|
|
1474
1553
|
}
|
|
1475
1554
|
settleFleet("failed");
|
|
1476
|
-
return {
|
|
1555
|
+
return settledLegAnswer({ taskId, sessionId, plane: landed !== undefined ? planeOfEndedRow(landed) : cancelled, reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
|
|
1477
1556
|
}
|
|
1478
1557
|
if (!engineHandedOff && legClaim !== undefined) {
|
|
1479
1558
|
const claim = legClaim;
|
|
1480
1559
|
await withdrawClaim(deps, claim, `the resume could not be handed to the engine: ${outwardThrownMessage(e, errorText(e))}`, "faulted");
|
|
1481
1560
|
const parkedAgain = claim.kind === "resumed" && restored?.kind !== "ended";
|
|
1482
1561
|
settleFleet(parkedAgain ? reparkStatus : "failed");
|
|
1483
|
-
|
|
1484
|
-
|
|
1562
|
+
const cancelledRow = claimWindowCancelRow();
|
|
1563
|
+
if (cancelledRow !== undefined)
|
|
1564
|
+
return settledLegAnswer({ taskId, sessionId, plane: planeOfEndedRow(cancelledRow), reparked: false, evidence: NO_SETTLEMENT_EVIDENCE });
|
|
1485
1565
|
return resumeClaimFaultAnswerOf(e);
|
|
1486
1566
|
}
|
|
1487
1567
|
const heldParkWord = heldPark === undefined ? undefined : heldParkOf(heldPark);
|
|
@@ -1536,20 +1616,13 @@ export function createResumeLegs(ctx) {
|
|
|
1536
1616
|
await deps.runStore.setTerminal(taskId, resumePlane.status, sealed, resumePlane.errorMessage ?? null);
|
|
1537
1617
|
}
|
|
1538
1618
|
settleFleet(parkEnded !== undefined ? "failed" : checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed, sealed ? failureCodeOf(sealed.terminal) : undefined));
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
bindingEnforced: true,
|
|
1547
|
-
...(answered.errorCode ? { errorCode: answered.errorCode } : {}),
|
|
1548
|
-
...(answered.errorMessage ? { errorMessage: redactErrorMessage(answered.errorMessage) ?? "" } : {}),
|
|
1549
|
-
...(checkpointReopened && parkEnded === undefined ? { retriable: true } : {}),
|
|
1550
|
-
...buildSettlementEvidence({ at: "engine_terminal", commitment: args.commitment }),
|
|
1551
|
-
},
|
|
1552
|
-
};
|
|
1619
|
+
return settledLegAnswer({
|
|
1620
|
+
taskId,
|
|
1621
|
+
sessionId,
|
|
1622
|
+
plane: parkEnded !== undefined ? planeOfEndedRow(parkEnded.row) : resumePlane,
|
|
1623
|
+
reparked: checkpointReopened && parkEnded === undefined,
|
|
1624
|
+
evidence: buildSettlementEvidence({ at: "engine_terminal", commitment: args.commitment }),
|
|
1625
|
+
});
|
|
1553
1626
|
}
|
|
1554
1627
|
async function mayDiscloseRowError(cs, token, decider) {
|
|
1555
1628
|
if (decider === undefined || decider.operator)
|
|
@@ -1623,7 +1696,7 @@ export function createResumeLegs(ctx) {
|
|
|
1623
1696
|
return resumeCtxUnreadableAnswer();
|
|
1624
1697
|
if (ctxRead.kind === "absent")
|
|
1625
1698
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1626
|
-
const ctx =
|
|
1699
|
+
const ctx = replayCtxOf(ctxRead.ctx, restatement);
|
|
1627
1700
|
const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
1628
1701
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1629
1702
|
if (!resolved.ok)
|
|
@@ -1668,7 +1741,7 @@ export function createResumeLegs(ctx) {
|
|
|
1668
1741
|
}),
|
|
1669
1742
|
};
|
|
1670
1743
|
}
|
|
1671
|
-
const ctx =
|
|
1744
|
+
const ctx = replayCtxOf(storedCtx, restatement);
|
|
1672
1745
|
const windowDenial = await usageWindowDenialFor(subject === undefined ? undefined : personOf(recoveredSubject(subject)));
|
|
1673
1746
|
if (windowDenial)
|
|
1674
1747
|
return { status: windowDenial.status, body: windowDenial.body };
|
|
@@ -1680,7 +1753,7 @@ export function createResumeLegs(ctx) {
|
|
|
1680
1753
|
const { spec, engineNotices } = resolved;
|
|
1681
1754
|
const hostSpec = { ...spec, objective };
|
|
1682
1755
|
const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
|
|
1683
|
-
prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), seat: createSubmissionSeat({ deployment: deps.config }), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1756
|
+
prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), bodyPermissionModeWrite: { stored: ctx.permissionModeWrite }, seat: createSubmissionSeat({ deployment: deps.config }), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1684
1757
|
fleetScope: resumeFleetScope(req, auth),
|
|
1685
1758
|
elicitOwner: subject ?? null,
|
|
1686
1759
|
source: "workflow_parked_decide",
|
|
@@ -1706,7 +1779,7 @@ export function createResumeLegs(ctx) {
|
|
|
1706
1779
|
const token = (await cs.findPendingTokenBySession(sessionId, undefined, wakeBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
|
|
1707
1780
|
if (!token)
|
|
1708
1781
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1709
|
-
const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config) };
|
|
1782
|
+
const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config, "operate") };
|
|
1710
1783
|
if (!who.operator) {
|
|
1711
1784
|
const scope = await cs.peekPendingScope(sessionId, wakeBinding).then((s) => (s === undefined ? cs.peekPendingScope(sessionId) : s)).catch(() => undefined);
|
|
1712
1785
|
if (!keyAdmits("scope.decide", who, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE))) {
|
|
@@ -1757,7 +1830,7 @@ export function createResumeLegs(ctx) {
|
|
|
1757
1830
|
return resumeCtxUnreadableAnswer();
|
|
1758
1831
|
if (ctxRead.kind === "absent")
|
|
1759
1832
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1760
|
-
const ctx =
|
|
1833
|
+
const ctx = replayCtxOf(ctxRead.ctx, restatement);
|
|
1761
1834
|
const auth = { sessionId: cp.sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
1762
1835
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1763
1836
|
if (!resolved.ok)
|
|
@@ -1784,7 +1857,7 @@ export function createResumeLegs(ctx) {
|
|
|
1784
1857
|
...(workflowDecision !== undefined ? { workflowDecision } : {}),
|
|
1785
1858
|
...(engineNotices.length > 0 ? { engineNotices } : {}),
|
|
1786
1859
|
...(acceptEarly === true ? { acceptEarly: true } : {}),
|
|
1787
|
-
...(req !== undefined ? { callerInitiated: true } : {}),
|
|
1860
|
+
...(req !== undefined || workflowDecision !== undefined ? { callerInitiated: true } : {}),
|
|
1788
1861
|
...(ownerLeaseAdmittedFor !== undefined && auth.subject === ownerLeaseAdmittedFor ? { ownerLeaseAdmitted: true } : {}),
|
|
1789
1862
|
});
|
|
1790
1863
|
}
|
|
@@ -1792,6 +1865,183 @@ export function createResumeLegs(ctx) {
|
|
|
1792
1865
|
resolved.peerLease.release();
|
|
1793
1866
|
}
|
|
1794
1867
|
}
|
|
1868
|
+
async function answerOfRecordFailure(failed, hostSessionId) {
|
|
1869
|
+
if (failed.kind === "faulted")
|
|
1870
|
+
return faultedAnswerOf(failed.err, CONTINUATION_CLAIM_FACE.faulted);
|
|
1871
|
+
const runStore = deps.runStore;
|
|
1872
|
+
if (runStore === undefined)
|
|
1873
|
+
throw new Error("workflow park decide: a decision row failed to land without a run store — the claim fence it was written under is the run store");
|
|
1874
|
+
try {
|
|
1875
|
+
return await refusalAfterLostClaim(deps, runStore, hostSessionId, failed.deliveredTaskId);
|
|
1876
|
+
}
|
|
1877
|
+
catch (e) {
|
|
1878
|
+
return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
async function deliverViaResumeLane(d) {
|
|
1882
|
+
const decisions = deps.workflowParkDecisions;
|
|
1883
|
+
const runStore = deps.runStore;
|
|
1884
|
+
const cs = deps.checkpointStore;
|
|
1885
|
+
if (decisions === undefined || runStore === undefined || cs === undefined) {
|
|
1886
|
+
return { kind: "refused", out: { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) } };
|
|
1887
|
+
}
|
|
1888
|
+
const liveReceiptOf = async (held) => {
|
|
1889
|
+
if (held === null || held.fingerprint !== d.fingerprint)
|
|
1890
|
+
return undefined;
|
|
1891
|
+
const run = await runFactsOf(runStore, held.deliveredTaskId);
|
|
1892
|
+
return run != null && !isTerminalRunStatus(run.status) ? acceptedResumingReceipt(held.deliveredTaskId, held.hostSessionId, NO_SETTLEMENT_EVIDENCE) : undefined;
|
|
1893
|
+
};
|
|
1894
|
+
const replay = await liveReceiptOf(await decisions.get(d.token));
|
|
1895
|
+
if (replay !== undefined)
|
|
1896
|
+
return { kind: "replayed", out: replay };
|
|
1897
|
+
await runChannelEnded(d.runId, d.runScope);
|
|
1898
|
+
const condition = d.initiator.kind === "run_ended" ? { expect: d.fingerprint } : undefined;
|
|
1899
|
+
let recordFailure;
|
|
1900
|
+
const delivery = {
|
|
1901
|
+
carried: [{ runId: d.runId, token: d.token, outcome: d.outcome }],
|
|
1902
|
+
commitBeforeLaunch: async (deliveredTaskId) => {
|
|
1903
|
+
let recorded;
|
|
1904
|
+
try {
|
|
1905
|
+
recorded = await decisions.record({ token: d.token, runId: d.runId, hostSessionId: d.hostSessionId, outcome: d.outcome, fingerprint: d.fingerprint, deliveredTaskId, acceptedAtMs: Date.now() }, condition);
|
|
1906
|
+
}
|
|
1907
|
+
catch (err) {
|
|
1908
|
+
recordFailure = { kind: "faulted", err };
|
|
1909
|
+
throw err;
|
|
1910
|
+
}
|
|
1911
|
+
if (!recorded) {
|
|
1912
|
+
recordFailure = { kind: "not_recorded", deliveredTaskId };
|
|
1913
|
+
throw new Error(DELIVERY_NOT_RECORDED);
|
|
1914
|
+
}
|
|
1915
|
+
},
|
|
1916
|
+
};
|
|
1917
|
+
const hostToken = await cs.findPendingTokenBySession(d.hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" }).catch(() => undefined);
|
|
1918
|
+
const req = d.initiator.kind === "decide" ? d.initiator.req : undefined;
|
|
1919
|
+
const acceptEarly = d.initiator.kind === "decide" ? d.initiator.acceptEarly : undefined;
|
|
1920
|
+
let out;
|
|
1921
|
+
try {
|
|
1922
|
+
out = hostToken
|
|
1923
|
+
? await resumeWake(d.hostSessionId, d.message, d.initiator.caller, req, acceptEarly, delivery, d.initiator.admittedPayer, d.restatement)
|
|
1924
|
+
: await startFreshHostTurn(d.hostSessionId, d.message.text, d.initiator.admittedPayer, req, delivery, d.runId, d.restatement);
|
|
1925
|
+
}
|
|
1926
|
+
catch (err) {
|
|
1927
|
+
const failed = recordFailure;
|
|
1928
|
+
if (failed === undefined)
|
|
1929
|
+
throw err;
|
|
1930
|
+
return { kind: "record_failed", failure: failed };
|
|
1931
|
+
}
|
|
1932
|
+
const failed = recordFailure;
|
|
1933
|
+
if (failed !== undefined)
|
|
1934
|
+
return { kind: "record_failed", failure: failed };
|
|
1935
|
+
if (acceptedTaskIdOf(out) === undefined) {
|
|
1936
|
+
const raced = await liveReceiptOf(await decisions.get(d.token));
|
|
1937
|
+
return raced !== undefined ? { kind: "replayed", out: raced } : { kind: "refused", out };
|
|
1938
|
+
}
|
|
1939
|
+
return { kind: "launched", out };
|
|
1940
|
+
}
|
|
1941
|
+
async function handOverRunEndedDecisions(runId) {
|
|
1942
|
+
if (isAdoptionQuiescing())
|
|
1943
|
+
throw new Error(`workflow run ${runId}: an adoption arc is running in this process — the decision handoff yields and is retried on the next recovery sweep`);
|
|
1944
|
+
const handing = handOverHeldRows(runId);
|
|
1945
|
+
trackMaintenanceLeg(handing);
|
|
1946
|
+
await handing;
|
|
1947
|
+
}
|
|
1948
|
+
async function handOverHeldRows(runId) {
|
|
1949
|
+
const decisions = deps.workflowParkDecisions;
|
|
1950
|
+
const records = deps.workflowRunStore;
|
|
1951
|
+
const cs = deps.checkpointStore;
|
|
1952
|
+
const index = deps.workflowAgentSessionIndex;
|
|
1953
|
+
if (decisions === undefined || records === undefined || cs === undefined || index === undefined)
|
|
1954
|
+
return;
|
|
1955
|
+
const run = await records.get(runId);
|
|
1956
|
+
if (run === null)
|
|
1957
|
+
return;
|
|
1958
|
+
const parks = readRunParks(run);
|
|
1959
|
+
if (parks === undefined) {
|
|
1960
|
+
deps.logger?.warn?.("workflow_park_handoff_refused", { runId, why: "parks_unreadable" });
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
const held = heldParksOf(runId, parks);
|
|
1964
|
+
if (run.status === "running") {
|
|
1965
|
+
for (const park of held) {
|
|
1966
|
+
if ((await decisions.get(park.token)) !== null) {
|
|
1967
|
+
throw new Error(`workflow run ${runId}: its completion arrived while its record still reads running (the terminal record write did not land) and it holds an accepted decision — leaving the completion pending until recovery ends the record`);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
for (const park of held) {
|
|
1973
|
+
const row = await decisions.get(park.token);
|
|
1974
|
+
if (row === null)
|
|
1975
|
+
continue;
|
|
1976
|
+
const deliverable = await deliverableEntryOf({ checkpointStore: cs, workflowAgentSessionIndex: index, workflowRunStore: records }, row);
|
|
1977
|
+
if (deliverable.kind === "unreadable")
|
|
1978
|
+
throw new Error(`workflow run ${runId}: the card or the holder of a recorded decision could not be read — leaving the completion pending for the next recovery sweep`);
|
|
1979
|
+
if (deliverable.kind === "not_deliverable" || deliverable.entry.runId !== runId)
|
|
1980
|
+
continue;
|
|
1981
|
+
const result = await handOverOne(runId, run.scope, deliverable, row);
|
|
1982
|
+
deps.metrics?.inc("workflow_park_handoff_total", { result: result.kind });
|
|
1983
|
+
switch (result.kind) {
|
|
1984
|
+
case "delivered":
|
|
1985
|
+
continue;
|
|
1986
|
+
case "retry":
|
|
1987
|
+
throw new Error(`workflow run ${runId}: the decision handoff must be retried (${result.why}) — leaving the completion pending for the next recovery sweep`);
|
|
1988
|
+
case "refused":
|
|
1989
|
+
deps.logger?.warn?.("workflow_park_handoff_refused", { runId, why: result.why });
|
|
1990
|
+
continue;
|
|
1991
|
+
default: {
|
|
1992
|
+
const unhandled = result;
|
|
1993
|
+
throw new Error(`unhandled workflow park handoff result: ${JSON.stringify(unhandled)}`);
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
async function handOverOne(runId, runScope, parkEntry, row) {
|
|
1999
|
+
const cs = deps.checkpointStore;
|
|
2000
|
+
const hostSessionId = parkEntry.origin.run.originatingSessionId;
|
|
2001
|
+
if (hostSessionId === undefined || hostSessionId === "")
|
|
2002
|
+
return { kind: "refused", why: "host_unknown" };
|
|
2003
|
+
const ownerScope = parkEntry.card.scope;
|
|
2004
|
+
const hostToken = await cs.findPendingTokenBySession(hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" });
|
|
2005
|
+
if (hostToken) {
|
|
2006
|
+
const hostCard = await cs.get(hostToken);
|
|
2007
|
+
if (hostCard !== null && hostCard.scope !== ownerScope)
|
|
2008
|
+
return { kind: "refused", why: "owner_mismatch" };
|
|
2009
|
+
}
|
|
2010
|
+
const parts = checkpointPartsOf(ownerScope);
|
|
2011
|
+
const quota = ownerCostQuotaDenied(parts?.person);
|
|
2012
|
+
if (quota !== undefined)
|
|
2013
|
+
return handoffResultOf(quota, "payer_cost_quota");
|
|
2014
|
+
const lease = await ownerFleetLeaseDenied(parts?.person);
|
|
2015
|
+
if (lease !== undefined)
|
|
2016
|
+
return handoffResultOf(lease, "payer_fleet_lease");
|
|
2017
|
+
const laned = await deliverViaResumeLane({
|
|
2018
|
+
hostSessionId,
|
|
2019
|
+
runId,
|
|
2020
|
+
runScope,
|
|
2021
|
+
token: row.token,
|
|
2022
|
+
outcome: row.outcome,
|
|
2023
|
+
fingerprint: row.fingerprint,
|
|
2024
|
+
message: workflowParkGuidance(runId, parkEntry.origin.park.callKey, row.outcome.decision === "allow" ? "approve" : "deny"),
|
|
2025
|
+
initiator: { kind: "run_ended", caller: parts?.subject, admittedPayer: decodeCheckpointScope(ownerScope) },
|
|
2026
|
+
});
|
|
2027
|
+
switch (laned.kind) {
|
|
2028
|
+
case "launched":
|
|
2029
|
+
case "replayed":
|
|
2030
|
+
return { kind: "delivered" };
|
|
2031
|
+
case "refused":
|
|
2032
|
+
return handoffResultOf(laned.out);
|
|
2033
|
+
case "record_failed": {
|
|
2034
|
+
if (laned.failure.kind === "faulted")
|
|
2035
|
+
return { kind: "retry", why: "store_fault" };
|
|
2036
|
+
const now = await deps.workflowParkDecisions.get(row.token);
|
|
2037
|
+
return now?.fingerprint === row.fingerprint ? { kind: "retry", why: "claim_lost" } : { kind: "refused", why: "superseded" };
|
|
2038
|
+
}
|
|
2039
|
+
default: {
|
|
2040
|
+
const unhandled = laned;
|
|
2041
|
+
throw new Error(`unhandled resume lane delivery: ${JSON.stringify(unhandled)}`);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
1795
2045
|
async function preparePlanReview(sessionId, log, decider, sighting, restatement) {
|
|
1796
2046
|
const cs = deps.checkpointStore;
|
|
1797
2047
|
const refuse = (answer) => ({ ok: false, answer });
|
|
@@ -1865,7 +2115,7 @@ export function createResumeLegs(ctx) {
|
|
|
1865
2115
|
return refuse(resumeCtxUnreadableAnswer());
|
|
1866
2116
|
if (ctxRead.kind === "absent")
|
|
1867
2117
|
return refuse({ status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) });
|
|
1868
|
-
const ctx =
|
|
2118
|
+
const ctx = replayCtxOf(ctxRead.ctx, restatement);
|
|
1869
2119
|
const replay = storedBodyReplayRefusal(ctx, deps.config);
|
|
1870
2120
|
if (replay !== undefined)
|
|
1871
2121
|
return refuse(refuseStoredBodyReplay(sessionId, replay));
|
|
@@ -1881,7 +2131,7 @@ export function createResumeLegs(ctx) {
|
|
|
1881
2131
|
throw new Error("drivePlanReview: permissionModeAfter was passed for a task whose stored permission mode is not \"plan\" — the caller must refuse this before any state changes (see the plan_review route's pre-nonce gate)");
|
|
1882
2132
|
}
|
|
1883
2133
|
const approvedMode = planReviewDecisionExitsPlan(decision) && effMode === "plan" ? (permissionModeAfter ?? "default") : undefined;
|
|
1884
|
-
const rebuildCtx = approvedMode === undefined ? ctx :
|
|
2134
|
+
const rebuildCtx = approvedMode === undefined ? ctx : withStoredPermissionMode(ctx, approvedMode, "plan_review");
|
|
1885
2135
|
const resolved = await resolveResumeSpecOrBlocked(rebuildCtx, req, auth);
|
|
1886
2136
|
if (!resolved.ok)
|
|
1887
2137
|
return resolved.answer;
|
|
@@ -1920,6 +2170,6 @@ export function createResumeLegs(ctx) {
|
|
|
1920
2170
|
local: { images: createImagesLocal(deps), sessions: createSessionsLocal(), sessionSync: createSessionSyncLocal(), capabilities: createCapabilitiesLocal() },
|
|
1921
2171
|
legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview, sessionNotify: sessionNotifyDoor },
|
|
1922
2172
|
};
|
|
1923
|
-
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
|
|
2173
|
+
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor, handOverRunEndedDecisions };
|
|
1924
2174
|
}
|
|
1925
2175
|
//# sourceMappingURL=resume-legs.js.map
|