@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
|
@@ -5,6 +5,14 @@ import { approvalPayloadFingerprint } from "../plugins/approval-payload-fingerpr
|
|
|
5
5
|
import { createObjectColumnReader, isJsonObject } from "../plugins/sql-json-column.js";
|
|
6
6
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
7
7
|
import { FENCE_LANDED } from "../plugins/store-contracts.js";
|
|
8
|
+
import { heldParksOf, readRunParks } from "./workflow-agent-session-index.js";
|
|
9
|
+
import { recordWriterOf } from "./workflow-notify-journal.js";
|
|
10
|
+
export function holderFenceAdmits(run, d, restated) {
|
|
11
|
+
const parks = readRunParks(run);
|
|
12
|
+
if (parks === undefined || !heldParksOf(d.runId, parks).some((p) => p.token === d.token))
|
|
13
|
+
return "not_held";
|
|
14
|
+
return restated ? "restated" : "land";
|
|
15
|
+
}
|
|
8
16
|
function seatName(v) {
|
|
9
17
|
if (v === undefined)
|
|
10
18
|
return "none";
|
|
@@ -14,7 +22,8 @@ function seatName(v) {
|
|
|
14
22
|
export function parkDecisionStoreRefusal(seats) {
|
|
15
23
|
const wanted = seats.workflowAgentSessionIndex !== undefined ? seats.runStore : undefined;
|
|
16
24
|
const decisions = seats.workflowParkDecisions;
|
|
17
|
-
|
|
25
|
+
const recordWriter = seats.workflowRunStore === undefined ? undefined : recordWriterOf(seats.workflowRunStore);
|
|
26
|
+
if (decisions?.claims === wanted && (decisions === undefined || decisions.records === recordWriter))
|
|
18
27
|
return undefined;
|
|
19
28
|
const pair = `run store: ${seatName(seats.runStore)}; workflow park decision store: ${decisions === undefined ? "none" : `${seatName(decisions)} bound to ${seatName(decisions.claims)}`}`;
|
|
20
29
|
if (decisions === undefined) {
|
|
@@ -27,9 +36,14 @@ export function parkDecisionStoreRefusal(seats) {
|
|
|
27
36
|
"a decision store is only read and written by that lane, which needs both the park index and the run store the decisions are fenced by; " +
|
|
28
37
|
"wire the lane (park index and run store) or drop the decision store; refusing to start rather than keep a store no lane fences");
|
|
29
38
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
if (decisions.claims !== wanted) {
|
|
40
|
+
return (`the workflow park decision store is not bound to this server's run store (${pair}) — ` +
|
|
41
|
+
"its writes are fenced by the run store it was built on, so a different run store means decisions recorded where the session claims are not checked; " +
|
|
42
|
+
"take runStore and workflowParkDecisions from the same store backend (run() and workflowParkDecisions()); refusing to start rather than record decisions the session claim cannot fence");
|
|
43
|
+
}
|
|
44
|
+
return (`the workflow park decision store is not bound to the workflow record store this server writes run records through (workflow record writer: ${seatName(recordWriter)}; decision store's record fence: ${seatName(decisions.records)}) — ` +
|
|
45
|
+
"while the run that holds a card is running, a decision row is written in the same atomic step that checks the run's record still reads running and still holds the card, so the fence must be the store every record write goes through; " +
|
|
46
|
+
"pass the record store the workflow run store wraps to the store backend's workflowParkDecisions(); refusing to start rather than record decisions a run's end cannot be ordered against");
|
|
33
47
|
}
|
|
34
48
|
export function parkDecisionFingerprint(outcome, restatement) {
|
|
35
49
|
const payload = approvalPayloadFingerprint({
|
|
@@ -76,13 +90,15 @@ function readRow(raw) {
|
|
|
76
90
|
const LEDGER_LINE_SHAPE = { what: "a workflow park decision row", read: readRow };
|
|
77
91
|
export class LocalWorkflowParkDecisionStore {
|
|
78
92
|
claims;
|
|
93
|
+
records;
|
|
79
94
|
fsyncEnabled;
|
|
80
95
|
ledgerPath;
|
|
81
96
|
gate;
|
|
82
97
|
rows = new Map();
|
|
83
98
|
log;
|
|
84
|
-
constructor(claims, root, fsyncEnabled = true) {
|
|
99
|
+
constructor(claims, records, root, fsyncEnabled = true) {
|
|
85
100
|
this.claims = claims;
|
|
101
|
+
this.records = records;
|
|
86
102
|
this.fsyncEnabled = fsyncEnabled;
|
|
87
103
|
if (root === undefined) {
|
|
88
104
|
this.ledgerPath = undefined;
|
|
@@ -92,14 +108,37 @@ export class LocalWorkflowParkDecisionStore {
|
|
|
92
108
|
const dir = join(root, "workflow-park-decisions");
|
|
93
109
|
ensureDir(dir);
|
|
94
110
|
this.ledgerPath = join(dir, "decisions.jsonl");
|
|
95
|
-
const
|
|
96
|
-
this.gate = gate;
|
|
97
|
-
for (const d of records)
|
|
111
|
+
const replayed = replayJsonlGuarded(this.ledgerPath, "workflow-park-decisions", LEDGER_LINE_SHAPE);
|
|
112
|
+
this.gate = replayed.gate;
|
|
113
|
+
for (const d of replayed.records)
|
|
98
114
|
this.rows.set(d.token, d);
|
|
99
115
|
}
|
|
100
|
-
async record(decision) {
|
|
116
|
+
async record(decision, condition) {
|
|
117
|
+
this.gate?.assertUsable();
|
|
118
|
+
let superseded = false;
|
|
119
|
+
const held = this.claims.whileHoldingClaim(decision.hostSessionId, decision.deliveredTaskId, () => {
|
|
120
|
+
if (condition !== undefined && this.rows.get(decision.token)?.fingerprint !== condition.expect) {
|
|
121
|
+
superseded = true;
|
|
122
|
+
return FENCE_LANDED;
|
|
123
|
+
}
|
|
124
|
+
return this.landNow(decision);
|
|
125
|
+
});
|
|
126
|
+
return held && !superseded;
|
|
127
|
+
}
|
|
128
|
+
async recordForRunningHolder(decision, request) {
|
|
101
129
|
this.gate?.assertUsable();
|
|
102
|
-
|
|
130
|
+
const fenced = await this.records.whileRunning(decision.runId, (run) => {
|
|
131
|
+
const admits = holderFenceAdmits(run, decision, request.restated);
|
|
132
|
+
if (admits !== "land")
|
|
133
|
+
return admits;
|
|
134
|
+
const existing = this.rows.get(decision.token);
|
|
135
|
+
if (existing === undefined) {
|
|
136
|
+
this.landNow(decision);
|
|
137
|
+
return "stands";
|
|
138
|
+
}
|
|
139
|
+
return existing.fingerprint === decision.fingerprint ? "stands" : "other_decision";
|
|
140
|
+
});
|
|
141
|
+
return fenced.running ? fenced.value : "not_running";
|
|
103
142
|
}
|
|
104
143
|
landNow(decision) {
|
|
105
144
|
if (this.ledgerPath !== undefined) {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **持有进程的拉取腿**:跑着一条持有停驻卡的 workflow run 的进程,在维护拍上读这些卡的决定行,把立住的决定在本地交给引擎(`redeemWorkflowParks`)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么需要它
|
|
5
|
+
* 持有卡的 run 仍读作 `running` 时,决断落成一条决定行(记录栅栏,律的属主 = `workflow-park-decision.ts` 文件头)。引擎只收本进程里那条 run 的决定 ——
|
|
6
|
+
* 决断恰落在跑那条 run 的进程上 ⇒ 当场交(`/decide` 的本进程快路);落在别的副本上 ⇒ 行在库里,**没有任何一条本地事件**会把它交给持有进程。
|
|
7
|
+
* ⇒ 持有进程自己回头看行:搭维护拍(`REAP_INTERVAL_SEC`),不新开定时器族、不按副本路由(与审批族悬挂 ask 的跨副本执行通知同一条裁定)。
|
|
8
|
+
*
|
|
9
|
+
* ## 两件
|
|
10
|
+
* · {@link HeldParksHere} —— **本进程执行器视图**:哪几条 run 的执行器在本进程里跑、它们此刻持有哪些 token。journaling 装饰器在本进程引擎每一笔**落成**的记录写上
|
|
11
|
+
* 刷新它(`parks[]` 里 `parkedBy === runId` 的条目);**只在执行器收场时删**(引擎的观察通道走完)。写抛 / CAS 输 / `parks[]` 读不出 ⇒ 不删、保留上一份 token
|
|
12
|
+
* (引擎吞掉记录写失败照跑,「本进程写成功过」不等于执行器的寿命)。视图只选候选,判官是决定行 + 卡状态 + 引擎。
|
|
13
|
+
* · {@link createWorkflowParkHolderPull} —— 拉取腿:每条候选 (run, token) 一次决定行主键读;有行 ⇒ 与起跑读者同一只逐行判(`deliverableEntryOf`:卡仍 pending ∧ 当下持有者
|
|
14
|
+
* 是这条 run)⇒ 在本地交给引擎;答词按 `holderPullDisposition` 处置(交上了 / 下一拍 / 交给收场送达)。每拍有帽、有墙钟预算、整数偏移轮转(与审批族悬挂轮询共用
|
|
15
|
+
* {@link boundedRotation});截断那一拍响亮。每一读带期限,读失败 ⇒ 本拍跳过这条、F 类留痕(`server.workflow-park-holder.read-failed`)、下拍再来。
|
|
16
|
+
* 本进程没有执行中的持有停驻 run ⇒ 一拍零店读。
|
|
17
|
+
*/
|
|
18
|
+
import type { CheckpointToken, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
|
|
19
|
+
import { type HeldWorkflowParkDecisionSources } from "../parked-decide.js";
|
|
20
|
+
import { type WorkflowAgentSessionIndex } from "./workflow-agent-session-index.js";
|
|
21
|
+
import type { WorkflowParkDecisionStore } from "./workflow-park-decision.js";
|
|
22
|
+
/** 视图里的一条 run:它的 scope 与它此刻持有的 token(上一笔落成的写读出的那一份)。 */
|
|
23
|
+
export interface HeldParkRun {
|
|
24
|
+
readonly runId: string;
|
|
25
|
+
readonly scope: string;
|
|
26
|
+
readonly tokens: readonly CheckpointToken[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 本进程执行器视图(见文件头)。`ended` = 「这条 run 的执行器在本进程里收场了」的读法(缺省 = 引擎观察通道走完;测试换成可控的那一只)。
|
|
30
|
+
* 登记是惰性的:一条 run 第一次有一笔落成的写持有 token 时才登记并挂收场;此前它不在视图里(没有持有停驻就没有可拉的东西)。
|
|
31
|
+
*/
|
|
32
|
+
export declare class HeldParksHere {
|
|
33
|
+
private readonly ended;
|
|
34
|
+
private readonly runs;
|
|
35
|
+
constructor(ended?: (runId: string, scope: string) => Promise<void>);
|
|
36
|
+
/** journaling 装饰器在本进程引擎的一笔**落成**的记录写之后调(put 落成 / update CAS 赢)。`parks[]` 读不出 ⇒ 保留上一份(不删)。 */
|
|
37
|
+
noteLanded(runId: string, run: WorkflowRun): void;
|
|
38
|
+
/** 此刻的候选(快照;顺序 = 登记序)。 */
|
|
39
|
+
candidates(): HeldParkRun[];
|
|
40
|
+
}
|
|
41
|
+
/** 拉取腿每拍的帽与墙钟预算(审批族悬挂轮询同一尺度:常态几条,帽与预算是退化态的护栏)。每读期限与悬挂轮询的点读同值。 */
|
|
42
|
+
export declare const HOLDER_PULL_MAX_PER_TICK = 64;
|
|
43
|
+
export declare const HOLDER_PULL_BUDGET_MS = 5000;
|
|
44
|
+
export declare const HOLDER_PULL_READ_TIMEOUT_MS = 2000;
|
|
45
|
+
export interface WorkflowParkHolderPullDeps {
|
|
46
|
+
readonly held: HeldParksHere;
|
|
47
|
+
readonly decisions: WorkflowParkDecisionStore;
|
|
48
|
+
readonly checkpointStore: NonNullable<HeldWorkflowParkDecisionSources["checkpointStore"]>;
|
|
49
|
+
readonly workflowAgentSessionIndex: WorkflowAgentSessionIndex;
|
|
50
|
+
readonly workflowRunStore: Pick<WorkflowRunStore, "get">;
|
|
51
|
+
readonly warn?: (event: string, fields: Record<string, unknown>) => void;
|
|
52
|
+
readonly now?: () => number;
|
|
53
|
+
}
|
|
54
|
+
/** 一拍的读数:`polled` = 真去读了决定行的候选数;`delivered` / `nextBeat` / `left` = 有可交付行的候选按处置计;`backlog` / `truncated` = 帽与预算截断。 */
|
|
55
|
+
export interface HolderPullTally {
|
|
56
|
+
readonly polled: number;
|
|
57
|
+
readonly delivered: number;
|
|
58
|
+
readonly nextBeat: number;
|
|
59
|
+
readonly left: number;
|
|
60
|
+
readonly backlog: number;
|
|
61
|
+
readonly truncated: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** 拉取腿(维护拍调;调用方守 in-flight,拍间不叠)。 */
|
|
64
|
+
export declare function createWorkflowParkHolderPull(deps: WorkflowParkHolderPullDeps): () => Promise<HolderPullTally>;
|
|
65
|
+
//# sourceMappingURL=workflow-park-holder.d.ts.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { boundedRotation } from "../bounded-rotation.js";
|
|
2
|
+
import { recordFailOpen } from "../observability/fail-open.js";
|
|
3
|
+
import { deliverableEntryOf, holderPullDisposition, redeemHere, runChannelEnded } from "../parked-decide.js";
|
|
4
|
+
import { heldParksOf, readRunParks } from "./workflow-agent-session-index.js";
|
|
5
|
+
export class HeldParksHere {
|
|
6
|
+
ended;
|
|
7
|
+
runs = new Map();
|
|
8
|
+
constructor(ended = runChannelEnded) {
|
|
9
|
+
this.ended = ended;
|
|
10
|
+
}
|
|
11
|
+
noteLanded(runId, run) {
|
|
12
|
+
const parks = readRunParks(run);
|
|
13
|
+
if (parks === undefined)
|
|
14
|
+
return;
|
|
15
|
+
const tokens = heldParksOf(runId, parks).map((p) => p.token);
|
|
16
|
+
if (this.runs.has(runId)) {
|
|
17
|
+
this.runs.set(runId, { runId, scope: run.scope, tokens });
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (tokens.length === 0)
|
|
21
|
+
return;
|
|
22
|
+
const entry = { runId, scope: run.scope, tokens };
|
|
23
|
+
this.runs.set(runId, entry);
|
|
24
|
+
const drop = () => void this.runs.delete(runId);
|
|
25
|
+
void this.ended(runId, run.scope).then(drop, (err) => {
|
|
26
|
+
recordFailOpen("server.workflow-park-holder.read-failed", `step=channel runId=${runId} err=${err instanceof Error ? err.message : String(err)}`);
|
|
27
|
+
drop();
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
candidates() {
|
|
31
|
+
return [...this.runs.values()];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const HOLDER_PULL_MAX_PER_TICK = 64;
|
|
35
|
+
export const HOLDER_PULL_BUDGET_MS = 5_000;
|
|
36
|
+
export const HOLDER_PULL_READ_TIMEOUT_MS = 2_000;
|
|
37
|
+
function within(p, ms, what) {
|
|
38
|
+
let timer;
|
|
39
|
+
const timeout = new Promise((_, reject) => {
|
|
40
|
+
timer = setTimeout(() => reject(new Error(`${what} did not answer within ${ms}ms`)), ms);
|
|
41
|
+
timer.unref?.();
|
|
42
|
+
});
|
|
43
|
+
p.catch(() => undefined);
|
|
44
|
+
return Promise.race([p, timeout]).finally(() => clearTimeout(timer));
|
|
45
|
+
}
|
|
46
|
+
export function createWorkflowParkHolderPull(deps) {
|
|
47
|
+
const cursor = { offset: 0 };
|
|
48
|
+
const sources = { checkpointStore: deps.checkpointStore, workflowAgentSessionIndex: deps.workflowAgentSessionIndex, workflowRunStore: deps.workflowRunStore };
|
|
49
|
+
return async () => {
|
|
50
|
+
const items = deps.held.candidates().flatMap((r) => r.tokens.map((token) => ({ runId: r.runId, scope: r.scope, token })));
|
|
51
|
+
let delivered = 0;
|
|
52
|
+
let nextBeat = 0;
|
|
53
|
+
let left = 0;
|
|
54
|
+
const { visited, backlog, truncated } = await boundedRotation([{ items, cursor }], { maxPerTick: HOLDER_PULL_MAX_PER_TICK, budgetMs: HOLDER_PULL_BUDGET_MS }, async ({ runId, scope, token }) => {
|
|
55
|
+
let row;
|
|
56
|
+
try {
|
|
57
|
+
row = await within(deps.decisions.get(token), HOLDER_PULL_READ_TIMEOUT_MS, "workflow park decision read");
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
recordFailOpen("server.workflow-park-holder.read-failed", `step=decision runId=${runId} err=${err instanceof Error ? err.message : String(err)}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (row === null)
|
|
64
|
+
return;
|
|
65
|
+
let deliverable;
|
|
66
|
+
try {
|
|
67
|
+
deliverable = await within(deliverableEntryOf(sources, row), HOLDER_PULL_READ_TIMEOUT_MS, "workflow park card read");
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
recordFailOpen("server.workflow-park-holder.read-failed", `step=card runId=${runId} err=${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (deliverable.kind !== "deliverable" || deliverable.entry.runId !== runId)
|
|
74
|
+
return;
|
|
75
|
+
const disposition = holderPullDisposition(await redeemHere(runId, scope, { token, outcome: row.outcome }), runId);
|
|
76
|
+
switch (disposition) {
|
|
77
|
+
case "delivered":
|
|
78
|
+
delivered++;
|
|
79
|
+
return;
|
|
80
|
+
case "next_beat":
|
|
81
|
+
nextBeat++;
|
|
82
|
+
return;
|
|
83
|
+
case "left":
|
|
84
|
+
left++;
|
|
85
|
+
return;
|
|
86
|
+
default: {
|
|
87
|
+
const unhandled = disposition;
|
|
88
|
+
throw new Error(`unhandled holder pull disposition: ${String(unhandled)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, deps.now);
|
|
92
|
+
if (truncated) {
|
|
93
|
+
deps.warn?.("workflow_park_holder_pull_truncated", { polled: visited, delivered, backlog, maxPerTick: HOLDER_PULL_MAX_PER_TICK, budgetMs: HOLDER_PULL_BUDGET_MS, resumeFromOffset: cursor.offset });
|
|
94
|
+
}
|
|
95
|
+
return { polled: visited, delivered, nextBeat, left, backlog, truncated };
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=workflow-park-holder.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **workflow 记录的进程内记录栅栏**(local 后端:File / InMemory 记录店;SQL 孪生是 `SqlWorkflowRunStore.whileRunning` 的行锁事务)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么在基店外包一层
|
|
5
|
+
* 持有一张停驻卡的 run 仍读作 `running` 时,决定行落在「这条 run 的记录仍在跑、仍持有这张卡」的原子段里(律的属主 = `workflow-park-decision.ts` 文件头)。
|
|
6
|
+
* 这一段要与这条 run 的**每一笔**记录写串行 —— 否则「判出在跑 → 落行」之间插进引擎的终态写,run 收场送达读不到这一行,决定被丢在已收场的 run 上。
|
|
7
|
+
* 本服务的记录写者有两个:引擎(经 journaling 装饰器 `JournalingWorkflowRunStore`)与 notify 门的收养翻转(`WorkflowNotifyGate.recover` 经基店翻 `running → failed`);
|
|
8
|
+
* core File 店的锁是它私有的。⇒ 互斥不能只放在 journaling 装饰器上:放在**基店外的这一只装饰器**里,两只写者都经它写,它就是本进程全部记录写者的同一只互斥。
|
|
9
|
+
*
|
|
10
|
+
* ## 律
|
|
11
|
+
* 按 runId 互斥:`put` / `update` / {@link FencedWorkflowRecordStore.whileRunning} 对同一条 run 一个接一个(先到先走);读(`get` / `listByScope`)与收割(只删终态行)
|
|
12
|
+
* 不进互斥(本装饰器不出按会话删那一口:与它所在的 journaling 装饰器同一个答案)。`whileRunning` 的 `fn` 是同步的(型上不许把写挪到段外),段里不许再经本店写同一条 run(会自锁)。
|
|
13
|
+
* 互斥只排同一进程里的写;SQL 后端的跨副本串行由行锁担(那里没有本装饰器)。
|
|
14
|
+
*/
|
|
15
|
+
import type { WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
|
|
16
|
+
import type { InProcessRecordFence, RecordFenced } from "./workflow-park-decision.js";
|
|
17
|
+
export declare class FencedWorkflowRecordStore implements WorkflowRunStore, InProcessRecordFence {
|
|
18
|
+
private readonly inner;
|
|
19
|
+
/** runId → 这条 run 上最后一段的落定(链尾);链空了就摘掉(有界 = 此刻有段在排的 run 数)。 */
|
|
20
|
+
private readonly tails;
|
|
21
|
+
constructor(inner: WorkflowRunStore);
|
|
22
|
+
/** 同一条 run 上的段一个接一个:等前一段落定(成败都算落定)再走本段。 */
|
|
23
|
+
private serial;
|
|
24
|
+
put(id: string, run: WorkflowRun): Promise<void>;
|
|
25
|
+
update(id: string, scope: string, run: WorkflowRun, expect?: {
|
|
26
|
+
rev: number;
|
|
27
|
+
}): Promise<boolean>;
|
|
28
|
+
whileRunning<T>(runId: string, fn: (run: WorkflowRun) => T): Promise<RecordFenced<T>>;
|
|
29
|
+
get(id: string): Promise<WorkflowRun | null>;
|
|
30
|
+
listByScope(...args: Parameters<WorkflowRunStore["listByScope"]>): ReturnType<WorkflowRunStore["listByScope"]>;
|
|
31
|
+
reap(scope: string, now: number, opts?: {
|
|
32
|
+
maxAgeMs?: number;
|
|
33
|
+
keep?: number;
|
|
34
|
+
}): Promise<number>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=workflow-record-fence.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export class FencedWorkflowRecordStore {
|
|
2
|
+
inner;
|
|
3
|
+
tails = new Map();
|
|
4
|
+
constructor(inner) {
|
|
5
|
+
this.inner = inner;
|
|
6
|
+
}
|
|
7
|
+
serial(runId, segment) {
|
|
8
|
+
const before = this.tails.get(runId) ?? Promise.resolve();
|
|
9
|
+
const result = before.then(segment);
|
|
10
|
+
const tail = result.then(() => undefined, () => undefined);
|
|
11
|
+
this.tails.set(runId, tail);
|
|
12
|
+
void tail.then(() => {
|
|
13
|
+
if (this.tails.get(runId) === tail)
|
|
14
|
+
this.tails.delete(runId);
|
|
15
|
+
});
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
put(id, run) {
|
|
19
|
+
return this.serial(id, () => this.inner.put(id, run));
|
|
20
|
+
}
|
|
21
|
+
update(id, scope, run, expect) {
|
|
22
|
+
return this.serial(id, () => this.inner.update(id, scope, run, expect));
|
|
23
|
+
}
|
|
24
|
+
whileRunning(runId, fn) {
|
|
25
|
+
return this.serial(runId, async () => {
|
|
26
|
+
const run = await this.inner.get(runId);
|
|
27
|
+
if (run === null || run.status !== "running")
|
|
28
|
+
return { running: false };
|
|
29
|
+
return { running: true, value: fn(run) };
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
get(id) {
|
|
33
|
+
return this.inner.get(id);
|
|
34
|
+
}
|
|
35
|
+
listByScope(...args) {
|
|
36
|
+
return this.inner.listByScope(...args);
|
|
37
|
+
}
|
|
38
|
+
reap(scope, now, opts) {
|
|
39
|
+
return this.inner.reap(scope, now, opts);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=workflow-record-fence.js.map
|
|
@@ -163,18 +163,45 @@ export declare function createOutboundDispatcher(env?: NodeJS.ProcessEnv): {
|
|
|
163
163
|
env: OutboundProxyEnv;
|
|
164
164
|
};
|
|
165
165
|
/**
|
|
166
|
-
*
|
|
166
|
+
* 建连失败**类** —— 闭集(三类),说「这一次建连失败的出路在哪一头」,由 {@link OUTBOUND_CONNECT_FAILURE_CODES} 的每个码各认一类(`failureClass`):
|
|
167
|
+
* · `refused` —— 对端把连接拒了(那个地址上没人监听 / 防火墙复位):出路在**地址那一头**(服务在不在、地址配得对不对);
|
|
168
|
+
* · `unresolved` —— 主机名解析不了(地址写错,或 DNS / VPN 不通):出路在**地址写法与名字解析**;
|
|
169
|
+
* · `unreachable` —— 建连没在时限内完成 / 无路由 / 网络不可达:出路在**网络路径**(VPN / 代理)。
|
|
170
|
+
* 建连失败的出路取自这三类上的一张表({@link MODEL_UNREACHABLE_REMEDIES},选句 {@link connectFailureRemedyOf}):用户面通告 `server.model_unreachable`
|
|
171
|
+
* (`model-unreachable-notice.ts`)与运维日志 `outbound_connect_failed` 的 `hint` 同读它,都不另写码 → 类的映射。
|
|
172
|
+
*/
|
|
173
|
+
export type OutboundConnectFailureClass = "refused" | "unresolved" | "unreachable";
|
|
174
|
+
/**
|
|
175
|
+
* 建连期失败码 —— **闭集**(码 → { 失败类,给运维的一句读法 })。只收**只可能**在建立连接时出现的码:undici 的建连截止
|
|
167
176
|
* (`UND_ERR_CONNECT_TIMEOUT`,TCP + TLS 没在传输层的建连时限内完成)与 OS 的拒连 / 解析不了 / 无路由。可能出现在**已建立**
|
|
168
177
|
* 连接上的码(`ECONNRESET` / `ETIMEDOUT` / `UND_ERR_SOCKET`)刻意不收 —— 它们判不出「够不着」,收进来就会把一次中途断流
|
|
169
|
-
* 说成「模型不可达、去查 VPN」。加一个码 =
|
|
178
|
+
* 说成「模型不可达、去查 VPN」。加一个码 = 加一行并写明它为什么只可能在建连时出现、它属哪一失败类(类缺 ⇒ 编译红)。
|
|
170
179
|
*/
|
|
171
180
|
export declare const OUTBOUND_CONNECT_FAILURE_CODES: {
|
|
172
|
-
readonly UND_ERR_CONNECT_TIMEOUT:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
readonly
|
|
177
|
-
|
|
181
|
+
readonly UND_ERR_CONNECT_TIMEOUT: {
|
|
182
|
+
readonly failureClass: "unreachable";
|
|
183
|
+
readonly reading: "the TCP + TLS connect did not complete within the transport's connect deadline";
|
|
184
|
+
};
|
|
185
|
+
readonly ECONNREFUSED: {
|
|
186
|
+
readonly failureClass: "refused";
|
|
187
|
+
readonly reading: "the peer actively refused the connection (nothing listening there, or a firewall reset it)";
|
|
188
|
+
};
|
|
189
|
+
readonly ENOTFOUND: {
|
|
190
|
+
readonly failureClass: "unresolved";
|
|
191
|
+
readonly reading: "the host name did not resolve";
|
|
192
|
+
};
|
|
193
|
+
readonly EAI_AGAIN: {
|
|
194
|
+
readonly failureClass: "unresolved";
|
|
195
|
+
readonly reading: "the DNS lookup failed temporarily";
|
|
196
|
+
};
|
|
197
|
+
readonly EHOSTUNREACH: {
|
|
198
|
+
readonly failureClass: "unreachable";
|
|
199
|
+
readonly reading: "there is no route to the host";
|
|
200
|
+
};
|
|
201
|
+
readonly ENETUNREACH: {
|
|
202
|
+
readonly failureClass: "unreachable";
|
|
203
|
+
readonly reading: "the network is unreachable";
|
|
204
|
+
};
|
|
178
205
|
};
|
|
179
206
|
export type OutboundConnectFailureCode = keyof typeof OUTBOUND_CONNECT_FAILURE_CODES;
|
|
180
207
|
/** 一次建连失败的事实(纯数据:日志行、诊断段、模型调用结局同一份)。`proxyInUse` = 这一跳走的代理**变量名**(不打值),直连 ⇒ `null`。 */
|
|
@@ -183,6 +210,42 @@ export interface OutboundConnectFailure {
|
|
|
183
210
|
readonly code: OutboundConnectFailureCode;
|
|
184
211
|
readonly proxyInUse: string | null;
|
|
185
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* 一个码的失败类({@link OutboundConnectFailureClass});闭集之外的码 ⇒ `undefined`(调用方必须处置这一臂,不是静默的一类)。纯函数、不抛。
|
|
215
|
+
* 类型上到不了 `undefined`(`OutboundConnectFailure.code` 是闭集型),但读者收 `string`:手造的失败事实、将来码型变宽,都落在这一臂上而不是 `undefined.failureClass` 抛。
|
|
216
|
+
*/
|
|
217
|
+
export declare function connectFailureClassOf(code: string): OutboundConnectFailureClass | undefined;
|
|
218
|
+
/**
|
|
219
|
+
* 一次建连失败的**出路** —— 同一件事的两种写法:`advice` 是给人读的一句(用户面通告的正文末句),`remedy` 是短句(通告的 `detail.remedy`,
|
|
220
|
+
* 也是运维日志 `outbound_connect_failed` 的 `hint` 尾句)。三张脸读**同一行**,不各写各的。
|
|
221
|
+
*/
|
|
222
|
+
export interface ConnectFailureRemedy {
|
|
223
|
+
readonly advice: string;
|
|
224
|
+
readonly remedy: string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* **失败类上的一张闭表**(键集 = {@link OutboundConnectFailureClass},加一类不补一行 ⇒ 编译红)。行说的是**模型端点**(端点地址、模型网关地址配置):
|
|
228
|
+
* 用户面通告只为模型调用铸,运维日志只在失败的请求属一次模型调用时读类行。契约附录 D.3 与 USAGE 列的就是这三行
|
|
229
|
+
* (`test/model-unreachable-notice.test.ts` 的「文书与表同源」一格读本表对文书)。
|
|
230
|
+
*/
|
|
231
|
+
export declare const MODEL_UNREACHABLE_REMEDIES: {
|
|
232
|
+
readonly refused: {
|
|
233
|
+
readonly advice: "Check that a service is listening at that address and that the model gateway address is configured correctly.";
|
|
234
|
+
readonly remedy: "check that a service is listening at the model endpoint address; check the model gateway address configuration";
|
|
235
|
+
};
|
|
236
|
+
readonly unresolved: {
|
|
237
|
+
readonly advice: "Check that the model gateway address is written correctly in the configuration and that DNS (and the VPN, if one is in use) can resolve it.";
|
|
238
|
+
readonly remedy: "check the model gateway address configuration; check DNS / VPN";
|
|
239
|
+
};
|
|
240
|
+
readonly unreachable: ConnectFailureRemedy;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* 选句 —— **唯一一处**(用户面通告与运维日志 `hint` 同调),规则先到先得:
|
|
244
|
+
* ① 失败的请求不属一次模型调用(`request: "other"`:中心、工具、MCP …)⇒ 通用句(类行说的是模型端点与网关地址配置,对别的主机不成立);
|
|
245
|
+
* ② 这一跳走了代理(`proxyInUse` 非空)⇒ 通用句(拒连 / 解析不了可能是**代理**那一头的事,出路仍是「查 VPN / 代理」);
|
|
246
|
+
* ③ 否则按失败类读闭表;码不在闭集里(类型上到不了,读者收 `string`)⇒ 通用句 —— 声明的未分类臂,不抛、不静默。
|
|
247
|
+
*/
|
|
248
|
+
export declare function connectFailureRemedyOf(failure: OutboundConnectFailure, request: "model_call" | "other"): ConnectFailureRemedy;
|
|
186
249
|
/** 一只请求错误的建连期失败码与它走的代理变量名(`undefined` = 不是建连失败)。原句不在这里 —— 它只给运维日志。 */
|
|
187
250
|
export declare function classifyOutboundConnectFailure(error: unknown): {
|
|
188
251
|
readonly code: OutboundConnectFailureCode;
|
|
@@ -339,14 +339,55 @@ export function createOutboundDispatcher(env = process.env) {
|
|
|
339
339
|
return { dispatcher: new OutboundDispatcher(new Agent(), proxied), posture: postureOf(v), env: v };
|
|
340
340
|
}
|
|
341
341
|
export const OUTBOUND_CONNECT_FAILURE_CODES = {
|
|
342
|
-
UND_ERR_CONNECT_TIMEOUT: "the TCP + TLS connect did not complete within the transport's connect deadline",
|
|
343
|
-
ECONNREFUSED: "the peer actively refused the connection (nothing listening there, or a firewall reset it)",
|
|
344
|
-
ENOTFOUND: "the host name did not resolve",
|
|
345
|
-
EAI_AGAIN: "the DNS lookup failed temporarily",
|
|
346
|
-
EHOSTUNREACH: "there is no route to the host",
|
|
347
|
-
ENETUNREACH: "the network is unreachable",
|
|
342
|
+
UND_ERR_CONNECT_TIMEOUT: { failureClass: "unreachable", reading: "the TCP + TLS connect did not complete within the transport's connect deadline" },
|
|
343
|
+
ECONNREFUSED: { failureClass: "refused", reading: "the peer actively refused the connection (nothing listening there, or a firewall reset it)" },
|
|
344
|
+
ENOTFOUND: { failureClass: "unresolved", reading: "the host name did not resolve" },
|
|
345
|
+
EAI_AGAIN: { failureClass: "unresolved", reading: "the DNS lookup failed temporarily" },
|
|
346
|
+
EHOSTUNREACH: { failureClass: "unreachable", reading: "there is no route to the host" },
|
|
347
|
+
ENETUNREACH: { failureClass: "unreachable", reading: "the network is unreachable" },
|
|
348
348
|
};
|
|
349
349
|
const isConnectFailureCode = (c) => typeof c === "string" && Object.hasOwn(OUTBOUND_CONNECT_FAILURE_CODES, c);
|
|
350
|
+
export function connectFailureClassOf(code) {
|
|
351
|
+
return isConnectFailureCode(code) ? OUTBOUND_CONNECT_FAILURE_CODES[code].failureClass : undefined;
|
|
352
|
+
}
|
|
353
|
+
const NETWORK_PATH_REMEDY = {
|
|
354
|
+
advice: "Check the VPN / proxy; if the proxy changed since the server started, restart it (proxy settings are read once at startup).",
|
|
355
|
+
remedy: "check VPN / proxy; restart if the proxy changed since boot",
|
|
356
|
+
};
|
|
357
|
+
export const MODEL_UNREACHABLE_REMEDIES = {
|
|
358
|
+
refused: {
|
|
359
|
+
advice: "Check that a service is listening at that address and that the model gateway address is configured correctly.",
|
|
360
|
+
remedy: "check that a service is listening at the model endpoint address; check the model gateway address configuration",
|
|
361
|
+
},
|
|
362
|
+
unresolved: {
|
|
363
|
+
advice: "Check that the model gateway address is written correctly in the configuration and that DNS (and the VPN, if one is in use) can resolve it.",
|
|
364
|
+
remedy: "check the model gateway address configuration; check DNS / VPN",
|
|
365
|
+
},
|
|
366
|
+
unreachable: NETWORK_PATH_REMEDY,
|
|
367
|
+
};
|
|
368
|
+
export function connectFailureRemedyOf(failure, request) {
|
|
369
|
+
switch (request) {
|
|
370
|
+
case "other":
|
|
371
|
+
return NETWORK_PATH_REMEDY;
|
|
372
|
+
case "model_call":
|
|
373
|
+
break;
|
|
374
|
+
default: {
|
|
375
|
+
const unhandled = request;
|
|
376
|
+
throw new Error(`connectFailureRemedyOf: unhandled request kind ${String(unhandled)}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (failure.proxyInUse !== null)
|
|
380
|
+
return NETWORK_PATH_REMEDY;
|
|
381
|
+
const failureClass = connectFailureClassOf(failure.code);
|
|
382
|
+
switch (failureClass) {
|
|
383
|
+
case undefined:
|
|
384
|
+
return NETWORK_PATH_REMEDY;
|
|
385
|
+
case "refused":
|
|
386
|
+
case "unresolved":
|
|
387
|
+
case "unreachable":
|
|
388
|
+
return MODEL_UNREACHABLE_REMEDIES[failureClass];
|
|
389
|
+
}
|
|
390
|
+
}
|
|
350
391
|
function scanConnectFailure(error) {
|
|
351
392
|
const queue = [error];
|
|
352
393
|
let proxyInUse = null;
|
|
@@ -438,7 +479,7 @@ function startConnectObserver(logger, nowMs) {
|
|
|
438
479
|
...(found.proxyHop !== null ? { proxyHop: found.proxyHop } : {}),
|
|
439
480
|
proxyReadAtMs: current.proxyReadAtMs,
|
|
440
481
|
sinceBootMs: Math.round(process.uptime() * 1000),
|
|
441
|
-
hint: `${OUTBOUND_CONNECT_FAILURE_CODES[failure.code]} — ${failure.proxyInUse !== null ? `this hop went through the proxy from ${failure.proxyInUse} (read once at boot)` : "this hop was a direct connection"};
|
|
482
|
+
hint: `${OUTBOUND_CONNECT_FAILURE_CODES[failure.code].reading} — ${failure.proxyInUse !== null ? `this hop went through the proxy from ${failure.proxyInUse} (read once at boot)` : "this hop was a direct connection"}; ${connectFailureRemedyOf(failure, call !== undefined ? "model_call" : "other").remedy}`,
|
|
442
483
|
});
|
|
443
484
|
if (call !== undefined)
|
|
444
485
|
call.last = { kind: "connect_failed", failure };
|
package/dist/owner-faces.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface Caller {
|
|
|
52
52
|
readonly principalRequired: boolean;
|
|
53
53
|
readonly multiTenant: boolean;
|
|
54
54
|
}
|
|
55
|
-
/** 单机形下 core
|
|
55
|
+
/** 单机形下 core 写侧给匿名任务落的那一格租户键(壳随请求带的那一个;换算 = `engine-identity.ts` 的 `engineScopeOf`):`j4` 一格的调用方条件。它是单机形的真租户键,不是哨兵。 */
|
|
56
56
|
export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
|
|
57
57
|
/**
|
|
58
58
|
* 🔴 **调用方与行属主之间唯一的桥**:两个品牌在类型上不可比(`Subject === DurableOwnerKey` 编译红),只在这里按字节比。调用方一侧是**主体**(分区键):
|
|
@@ -77,7 +77,7 @@ export declare function ownerKeyOf(persisted: string | null): DurableOwnerKey |
|
|
|
77
77
|
*/
|
|
78
78
|
export declare function ownerCellOf(owner: string | null | undefined): SessionOwnerCell | undefined;
|
|
79
79
|
/**
|
|
80
|
-
* **收纯串的协议内部口**的主体读法(恢复管线;不是铸点)
|
|
80
|
+
* **收纯串的协议内部口**的主体读法(恢复管线;不是铸点):活登记的按问读口 / 决断口的停驻赎回席(`tool-approval.ts` 协调器)、活问的应答口(`elicitation.ts` / `question.ts`)、
|
|
81
81
|
* 迟到决定的赎回席(`http/approval-sweeps.ts`)、停驻完成收件箱的排空门、peer 目录席 —— 这几扇口经纯串收「上游已铸的那一只主体」(HTTP 路由层的 `gatedSubject`
|
|
82
82
|
* 读数、续跑腿交来的 run 属主、引擎交来的 scope)。串就是一只已落成字节的属主键,按 {@link ownerKeyOf} → `partsOf` 恢复(坏形的 `_scn:` 串响亮抛),
|
|
83
83
|
* 不重判保留前缀 / 在册 / 宽度(那三判只在外部管线)。公开面改收 `Subject` 品牌是另一车(这几扇口的测试调用面数以百计)。
|