@sema-agent/server 1.322.0 → 2.0.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/dist/approval-hmac.d.ts +40 -0
- package/dist/approval-hmac.js +67 -0
- package/dist/approval.d.ts +31 -0
- package/dist/approval.js +72 -4
- package/dist/audit.d.ts +26 -0
- package/dist/audit.js +40 -1
- package/dist/auth-bridge.d.ts +10 -0
- package/dist/auth-bridge.js +47 -4
- package/dist/auth-keys.d.ts +19 -0
- package/dist/auth-keys.js +13 -0
- package/dist/bake-runner/main.d.ts +5 -0
- package/dist/bake-runner/main.js +43 -4
- package/dist/bake-runner/protocol.d.ts +57 -0
- package/dist/bake-runner/protocol.js +58 -3
- package/dist/bake-runner/runner.d.ts +54 -0
- package/dist/bake-runner/runner.js +87 -5
- package/dist/bench/l8/artifact.d.ts +63 -0
- package/dist/bench/l8/artifact.js +61 -2
- package/dist/bench/l8/escape.d.ts +36 -0
- package/dist/bench/l8/escape.js +25 -0
- package/dist/bench/l8/index.d.ts +14 -0
- package/dist/bench/l8/index.js +14 -0
- package/dist/bench/l8/probes.d.ts +74 -0
- package/dist/bench/l8/probes.js +60 -0
- package/dist/bench/l8/run-probes.d.ts +43 -0
- package/dist/bench/l8/run-probes.js +45 -2
- package/dist/bench/s1/arms.d.ts +126 -0
- package/dist/bench/s1/arms.js +188 -13
- package/dist/bench/s1/live-deps.d.ts +66 -0
- package/dist/bench/s1/live-deps.js +249 -11
- package/dist/bench/s1/oracle.d.ts +49 -0
- package/dist/bench/s1/oracle.js +36 -1
- package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
- package/dist/bench/s1/repair-oracle-adapter.js +30 -0
- package/dist/bench/s1/reviewer.d.ts +38 -0
- package/dist/bench/s1/reviewer.js +34 -0
- package/dist/bench/s1/row.d.ts +77 -0
- package/dist/bench/s1/row.js +62 -0
- package/dist/bench/s1/run-firm.d.ts +47 -0
- package/dist/bench/s1/run-firm.js +70 -4
- package/dist/bench/s1/runner-ctx.d.ts +71 -0
- package/dist/bench/s1/runner-ctx.js +36 -0
- package/dist/bench/s1/tasks.d.ts +108 -0
- package/dist/bench/s1/tasks.js +115 -0
- package/dist/boot-reclaim.d.ts +19 -0
- package/dist/boot-reclaim.js +20 -0
- package/dist/brain.d.ts +25 -0
- package/dist/brain.js +61 -1
- package/dist/budget.d.ts +66 -0
- package/dist/budget.js +128 -4
- package/dist/capabilities/builtin-tools.d.ts +3 -0
- package/dist/capabilities/builtin-tools.js +3 -0
- package/dist/capabilities/center-plugins.d.ts +17 -1
- package/dist/capabilities/center-plugins.js +45 -4
- package/dist/capabilities/center-prompts.d.ts +46 -0
- package/dist/capabilities/center-prompts.js +57 -3
- package/dist/capabilities/code-review-council.d.ts +28 -0
- package/dist/capabilities/code-review-council.js +40 -7
- package/dist/capabilities/collab-wire.d.ts +2 -0
- package/dist/capabilities/collab-workflows.d.ts +7 -0
- package/dist/capabilities/collab-workflows.js +44 -1
- package/dist/capabilities/oa-tools.d.ts +6 -0
- package/dist/capabilities/oa-tools.js +10 -0
- package/dist/capabilities/prompt.d.ts +14 -0
- package/dist/capabilities/prompt.js +14 -0
- package/dist/capabilities/prompts/code-review.d.ts +14 -0
- package/dist/capabilities/prompts/code-review.js +14 -0
- package/dist/capabilities/prompts/identity.d.ts +6 -0
- package/dist/capabilities/prompts/identity.js +6 -0
- package/dist/capabilities/prompts/team.d.ts +4 -0
- package/dist/capabilities/prompts/team.js +4 -0
- package/dist/capabilities/repo-tools.d.ts +11 -0
- package/dist/capabilities/repo-tools.js +8 -0
- package/dist/capabilities/sandbox-file-send.d.ts +95 -0
- package/dist/capabilities/sandbox-file-send.js +91 -3
- package/dist/capabilities/scenarios.d.ts +130 -0
- package/dist/capabilities/scenarios.js +180 -7
- package/dist/capabilities/select-environment-tool.d.ts +7 -0
- package/dist/capabilities/select-environment-tool.js +30 -0
- package/dist/capabilities/send-user-file-tool.d.ts +33 -0
- package/dist/capabilities/send-user-file-tool.js +65 -1
- package/dist/capabilities/skills.d.ts +29 -0
- package/dist/capabilities/skills.js +13 -2
- package/dist/capabilities/team.d.ts +22 -0
- package/dist/capabilities/team.js +22 -2
- package/dist/capabilities/tool-defer.d.ts +26 -0
- package/dist/capabilities/tool-defer.js +3 -0
- package/dist/config-center/apply-effective.d.ts +65 -0
- package/dist/config-center/apply-effective.js +204 -12
- package/dist/config-center/http-client.d.ts +34 -0
- package/dist/config-center/http-client.js +68 -0
- package/dist/config-center/restart-signal.d.ts +22 -0
- package/dist/config-center/restart-signal.js +39 -0
- package/dist/config-center/skills-mcp.d.ts +20 -1
- package/dist/config-center/skills-mcp.js +42 -7
- package/dist/config-center/types.d.ts +92 -1
- package/dist/config-lkg.d.ts +12 -0
- package/dist/config-lkg.js +41 -0
- package/dist/config-provider.d.ts +78 -0
- package/dist/config-provider.js +165 -2
- package/dist/config-types.d.ts +546 -0
- package/dist/config.d.ts +64 -0
- package/dist/config.js +455 -60
- package/dist/degenerate-instrument.d.ts +38 -0
- package/dist/degenerate-instrument.js +55 -3
- package/dist/elicitation.d.ts +39 -0
- package/dist/elicitation.js +87 -3
- package/dist/env-facts.d.ts +61 -0
- package/dist/env-facts.js +73 -7
- package/dist/fleet/fleet-bus.d.ts +185 -0
- package/dist/fleet/fleet-bus.js +333 -27
- package/dist/fleet/subagent-tail-bus.d.ts +11 -0
- package/dist/fleet/subagent-tail-bus.js +33 -2
- package/dist/fleet-client.d.ts +38 -0
- package/dist/fleet-client.js +44 -9
- package/dist/fleet-lease.d.ts +46 -0
- package/dist/fleet-lease.js +73 -5
- package/dist/hooks/branch-transcript.d.ts +8 -0
- package/dist/hooks/branch-transcript.js +33 -0
- package/dist/hooks/cc-stop-prompt.d.ts +42 -0
- package/dist/hooks/cc-stop-prompt.js +43 -1
- package/dist/hooks/hook-llm.d.ts +15 -0
- package/dist/hooks/hook-llm.js +47 -0
- package/dist/hooks/hook-runner.d.ts +89 -0
- package/dist/hooks/hook-runner.js +327 -18
- package/dist/http/idempotency.d.ts +31 -0
- package/dist/http/idempotency.js +34 -0
- package/dist/http/principal-gate.d.ts +17 -0
- package/dist/http/principal-gate.js +35 -3
- package/dist/http/route-ctx.d.ts +36 -0
- package/dist/http/routes/approvals-assistant.d.ts +25 -0
- package/dist/http/routes/approvals-assistant.js +253 -23
- package/dist/http/routes/attachments.js +22 -4
- package/dist/http/routes/capabilities.d.ts +7 -0
- package/dist/http/routes/capabilities.js +202 -1
- package/dist/http/routes/fleet.d.ts +6 -0
- package/dist/http/routes/fleet.js +94 -5
- package/dist/http/routes/images.d.ts +17 -0
- package/dist/http/routes/images.js +222 -14
- package/dist/http/routes/leader.d.ts +7 -0
- package/dist/http/routes/leader.js +10 -0
- package/dist/http/routes/memory-policy.d.ts +6 -0
- package/dist/http/routes/memory-policy.js +38 -6
- package/dist/http/routes/notify-wake.d.ts +10 -0
- package/dist/http/routes/notify-wake.js +19 -3
- package/dist/http/routes/observability.d.ts +6 -0
- package/dist/http/routes/observability.js +19 -2
- package/dist/http/routes/runs.d.ts +15 -0
- package/dist/http/routes/runs.js +464 -41
- package/dist/http/routes/session-sync.d.ts +15 -0
- package/dist/http/routes/session-sync.js +229 -19
- package/dist/http/routes/sessions-list.d.ts +6 -0
- package/dist/http/routes/sessions-list.js +35 -4
- package/dist/http/routes/sessions.d.ts +14 -0
- package/dist/http/routes/sessions.js +176 -31
- package/dist/http/routes/side-query.d.ts +8 -0
- package/dist/http/routes/side-query.js +26 -1
- package/dist/http/routes/tasks.d.ts +18 -0
- package/dist/http/routes/tasks.js +501 -38
- package/dist/http/routes/trace-usage.d.ts +10 -0
- package/dist/http/routes/trace-usage.js +66 -14
- package/dist/http/routes/workflows.d.ts +12 -0
- package/dist/http/routes/workflows.js +180 -19
- package/dist/http/run-meta.d.ts +11 -0
- package/dist/http/run-meta.js +6 -0
- package/dist/http/send.d.ts +19 -0
- package/dist/http/send.js +11 -0
- package/dist/http/server.d.ts +255 -0
- package/dist/http/server.js +921 -75
- package/dist/http/sse-log.d.ts +15 -0
- package/dist/http/sse-log.js +16 -0
- package/dist/http/tar.d.ts +9 -0
- package/dist/http/tar.js +21 -5
- package/dist/http/wire-gate.d.ts +9 -0
- package/dist/http/wire-gate.js +9 -0
- package/dist/http/wire-types.d.ts +187 -0
- package/dist/http/workspace-content.d.ts +8 -0
- package/dist/http/workspace-content.js +10 -0
- package/dist/images/bake-validate.d.ts +63 -0
- package/dist/images/bake-validate.js +71 -1
- package/dist/images/manifest.d.ts +19 -0
- package/dist/images/manifest.js +6 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +10 -5
- package/dist/key-resolver.d.ts +23 -0
- package/dist/key-resolver.js +27 -2
- package/dist/leader/diffout.d.ts +23 -0
- package/dist/leader/diffout.js +8 -1
- package/dist/leader/diffup.d.ts +32 -0
- package/dist/leader/diffup.js +43 -0
- package/dist/leader/endpoint.d.ts +20 -0
- package/dist/leader/endpoint.js +25 -2
- package/dist/leader/fanout.d.ts +60 -0
- package/dist/leader/fanout.js +29 -3
- package/dist/leader/grader-env-factory.d.ts +74 -0
- package/dist/leader/grader-env-factory.js +62 -3
- package/dist/leader/leader.d.ts +97 -0
- package/dist/leader/leader.js +151 -4
- package/dist/leader/merge.d.ts +94 -0
- package/dist/leader/merge.js +112 -9
- package/dist/leader/planner.d.ts +52 -0
- package/dist/leader/planner.js +47 -3
- package/dist/leader/repair-oracle.d.ts +61 -0
- package/dist/leader/repair-oracle.js +59 -1
- package/dist/leader/repair-wire.d.ts +78 -0
- package/dist/leader/repair-wire.js +79 -2
- package/dist/leader/wire.d.ts +79 -0
- package/dist/leader/wire.js +255 -8
- package/dist/lsp/e2b-bridge.d.ts +16 -0
- package/dist/lsp/e2b-bridge.js +32 -4
- package/dist/lsp/e2b-manager.d.ts +10 -0
- package/dist/lsp/e2b-manager.js +18 -2
- package/dist/lsp/lsp-frames.d.ts +12 -0
- package/dist/lsp/lsp-frames.js +12 -0
- package/dist/lsp/manager.d.ts +12 -0
- package/dist/lsp/manager.js +35 -2
- package/dist/lsp/types.d.ts +10 -0
- package/dist/lsp/ws-transport.d.ts +12 -0
- package/dist/lsp/ws-transport.js +53 -5
- package/dist/lsp-evict.d.ts +14 -0
- package/dist/lsp-evict.js +15 -1
- package/dist/main.js +2132 -96
- package/dist/memory-export.d.ts +1 -0
- package/dist/memory-export.js +4 -0
- package/dist/memory-scope.d.ts +49 -0
- package/dist/memory-scope.js +87 -4
- package/dist/memory-sync-client.d.ts +24 -0
- package/dist/memory-sync-client.js +41 -2
- package/dist/memory-sync.d.ts +23 -0
- package/dist/memory-sync.js +70 -1
- package/dist/model-select.d.ts +39 -0
- package/dist/model-select.js +42 -1
- package/dist/observability/cost-quota.d.ts +20 -0
- package/dist/observability/cost-quota.js +4 -0
- package/dist/observability/cost-taxonomy.d.ts +45 -0
- package/dist/observability/cost-taxonomy.js +34 -0
- package/dist/observability/logger.d.ts +1 -0
- package/dist/observability/logger.js +6 -0
- package/dist/observability/metrics.d.ts +13 -0
- package/dist/observability/metrics.js +63 -0
- package/dist/observability/otel-exporter.d.ts +9 -0
- package/dist/observability/otel-exporter.js +11 -3
- package/dist/observability/principal-context.d.ts +9 -0
- package/dist/observability/principal-context.js +9 -0
- package/dist/observability/prompt-manifest.d.ts +37 -0
- package/dist/observability/prompt-manifest.js +35 -1
- package/dist/observability/rate-limit.d.ts +10 -0
- package/dist/observability/rate-limit.js +1 -0
- package/dist/observability/tool-trace.d.ts +24 -0
- package/dist/observability/tool-trace.js +41 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
- package/dist/orchestration/hardened-vm-runner.js +119 -4
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
- package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
- package/dist/orchestration/hardened-vm-worker.js +27 -0
- package/dist/orchestration/subagent-steer.d.ts +44 -0
- package/dist/orchestration/subagent-steer.js +45 -1
- package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
- package/dist/orchestration/workflow-agent-steer.js +80 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
- package/dist/orchestration/workflow-completion-inbox.js +283 -32
- package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
- package/dist/orchestration/workflow-notify-journal.js +187 -13
- package/dist/parked-decide.d.ts +61 -0
- package/dist/parked-decide.js +58 -1
- package/dist/per-task-image.d.ts +54 -0
- package/dist/per-task-image.js +41 -0
- package/dist/plan-cache-probe.d.ts +35 -0
- package/dist/plan-cache-probe.js +18 -3
- package/dist/plugins/approval-exemption-store.d.ts +7 -0
- package/dist/plugins/approval-exemption-store.js +28 -2
- package/dist/plugins/approval-store-sql.d.ts +64 -0
- package/dist/plugins/approval-store-sql.js +32 -0
- package/dist/plugins/background-agent-store-sql.d.ts +55 -0
- package/dist/plugins/background-agent-store-sql.js +91 -4
- package/dist/plugins/background-shell-support.d.ts +98 -0
- package/dist/plugins/background-shell-support.js +117 -13
- package/dist/plugins/blob-backend.d.ts +104 -0
- package/dist/plugins/blob-backend.js +163 -6
- package/dist/plugins/breaker-state-sql.d.ts +65 -1
- package/dist/plugins/breaker-state-sql.js +46 -8
- package/dist/plugins/caching-session-store.d.ts +42 -0
- package/dist/plugins/caching-session-store.js +63 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
- package/dist/plugins/checkpoint-store-sql.js +239 -11
- package/dist/plugins/file-outcome-sink.d.ts +4 -0
- package/dist/plugins/file-outcome-sink.js +9 -0
- package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
- package/dist/plugins/file-resume-anchor-store.js +43 -4
- package/dist/plugins/file-run-store.d.ts +90 -0
- package/dist/plugins/file-run-store.js +145 -13
- package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
- package/dist/plugins/file-snapshot-store-sql.js +178 -10
- package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
- package/dist/plugins/file-workflow-journal-store.js +10 -0
- package/dist/plugins/fork-routing-session-store.d.ts +47 -0
- package/dist/plugins/fork-routing-session-store.js +51 -3
- package/dist/plugins/host-platform.d.ts +69 -0
- package/dist/plugins/host-platform.js +81 -2
- package/dist/plugins/image-bake-store-sql.d.ts +136 -1
- package/dist/plugins/image-bake-store-sql.js +241 -7
- package/dist/plugins/image-index-sql.d.ts +46 -0
- package/dist/plugins/image-index-sql.js +113 -4
- package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
- package/dist/plugins/k8s-bg-scripts.js +88 -4
- package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
- package/dist/plugins/k8s-exec-protocol.js +41 -0
- package/dist/plugins/local-checkpoint-store.d.ts +40 -0
- package/dist/plugins/local-checkpoint-store.js +86 -7
- package/dist/plugins/local-session-store.d.ts +157 -0
- package/dist/plugins/local-session-store.js +289 -34
- package/dist/plugins/local-task-attachment-store.js +14 -2
- package/dist/plugins/mailbox-store-sql.d.ts +38 -0
- package/dist/plugins/mailbox-store-sql.js +39 -6
- package/dist/plugins/memory-engine-pg.d.ts +30 -0
- package/dist/plugins/memory-engine-pg.js +122 -4
- package/dist/plugins/memory-engine-tidb.d.ts +26 -0
- package/dist/plugins/memory-engine-tidb.js +115 -5
- package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
- package/dist/plugins/memory-engine-vector-util.js +5 -0
- package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
- package/dist/plugins/memory-resume-anchor-store.js +17 -0
- package/dist/plugins/memory-run-store.d.ts +63 -0
- package/dist/plugins/memory-run-store.js +73 -8
- package/dist/plugins/memory-session-policy-store.d.ts +17 -0
- package/dist/plugins/memory-session-policy-store.js +17 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
- package/dist/plugins/memory-sync-store-pg.js +45 -2
- package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
- package/dist/plugins/memory-sync-store-tidb.js +31 -1
- package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
- package/dist/plugins/outcome-ledger-sql.js +97 -3
- package/dist/plugins/pg-approval-store.d.ts +7 -0
- package/dist/plugins/pg-approval-store.js +7 -0
- package/dist/plugins/pg-breaker-state.d.ts +6 -0
- package/dist/plugins/pg-breaker-state.js +6 -0
- package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
- package/dist/plugins/pg-checkpoint-store.js +8 -0
- package/dist/plugins/pg-cost-quota.d.ts +17 -0
- package/dist/plugins/pg-cost-quota.js +6 -0
- package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/pg-file-snapshot-store.js +6 -0
- package/dist/plugins/pg-image-bake.d.ts +9 -0
- package/dist/plugins/pg-image-bake.js +9 -0
- package/dist/plugins/pg-image-index.d.ts +9 -0
- package/dist/plugins/pg-image-index.js +9 -0
- package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
- package/dist/plugins/pg-outcome-ledger.js +9 -0
- package/dist/plugins/pg-pool.d.ts +50 -0
- package/dist/plugins/pg-pool.js +78 -0
- package/dist/plugins/pg-query.d.ts +11 -0
- package/dist/plugins/pg-rate-limiter.d.ts +23 -0
- package/dist/plugins/pg-rate-limiter.js +12 -2
- package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/pg-resume-anchor-store.js +5 -0
- package/dist/plugins/pg-run-store.d.ts +7 -0
- package/dist/plugins/pg-run-store.js +7 -0
- package/dist/plugins/pg-safe-json.d.ts +13 -0
- package/dist/plugins/pg-safe-json.js +40 -4
- package/dist/plugins/pg-session-policy-store.d.ts +5 -0
- package/dist/plugins/pg-session-policy-store.js +5 -0
- package/dist/plugins/pg-session-storage.d.ts +72 -0
- package/dist/plugins/pg-session-storage.js +152 -20
- package/dist/plugins/pg-session-store.d.ts +10 -0
- package/dist/plugins/pg-session-store.js +10 -0
- package/dist/plugins/pg-tool-result-store.d.ts +7 -0
- package/dist/plugins/pg-tool-result-store.js +7 -0
- package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-journal-store.js +7 -0
- package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-run-store.js +7 -0
- package/dist/plugins/posix-shell-fs.d.ts +3 -0
- package/dist/plugins/posix-shell-fs.js +31 -1
- package/dist/plugins/remote-env-adb.d.ts +25 -0
- package/dist/plugins/remote-env-adb.js +95 -12
- package/dist/plugins/remote-env-e2b.d.ts +146 -0
- package/dist/plugins/remote-env-e2b.js +371 -40
- package/dist/plugins/remote-env-file-error.d.ts +34 -0
- package/dist/plugins/remote-env-file-error.js +37 -0
- package/dist/plugins/remote-env-host.d.ts +151 -0
- package/dist/plugins/remote-env-host.js +468 -70
- package/dist/plugins/remote-env-k8s.d.ts +135 -0
- package/dist/plugins/remote-env-k8s.js +318 -32
- package/dist/plugins/remote-env-local-docker.d.ts +65 -0
- package/dist/plugins/remote-env-local-docker.js +149 -24
- package/dist/plugins/remote-env-ssh.d.ts +35 -0
- package/dist/plugins/remote-env-ssh.js +117 -20
- package/dist/plugins/remote-scratchpad.d.ts +38 -0
- package/dist/plugins/remote-scratchpad.js +32 -2
- package/dist/plugins/remote-shell.d.ts +22 -0
- package/dist/plugins/remote-shell.js +27 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
- package/dist/plugins/resume-anchor-store-sql.js +11 -0
- package/dist/plugins/roster-store-sql.d.ts +27 -0
- package/dist/plugins/roster-store-sql.js +54 -0
- package/dist/plugins/run-store-sql.d.ts +194 -0
- package/dist/plugins/run-store-sql.js +210 -9
- package/dist/plugins/s3-presign.d.ts +20 -0
- package/dist/plugins/s3-presign.js +49 -2
- package/dist/plugins/scheduler-support.d.ts +12 -0
- package/dist/plugins/scheduler-support.js +75 -3
- package/dist/plugins/send-file-ledger.d.ts +15 -0
- package/dist/plugins/send-file-ledger.js +53 -4
- package/dist/plugins/send-user-file.d.ts +77 -0
- package/dist/plugins/send-user-file.js +92 -4
- package/dist/plugins/session-policy-store-sql.d.ts +15 -0
- package/dist/plugins/session-policy-store-sql.js +75 -3
- package/dist/plugins/session-store.d.ts +45 -0
- package/dist/plugins/session-store.js +51 -0
- package/dist/plugins/sql-driver.d.ts +77 -0
- package/dist/plugins/sql-driver.js +4 -0
- package/dist/plugins/sql-escape.d.ts +8 -0
- package/dist/plugins/sql-escape.js +8 -0
- package/dist/plugins/sql-row-helpers.d.ts +25 -0
- package/dist/plugins/sql-row-helpers.js +25 -0
- package/dist/plugins/store-backend.d.ts +103 -0
- package/dist/plugins/store-backend.js +120 -27
- package/dist/plugins/store-contracts.d.ts +62 -0
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +60 -0
- package/dist/plugins/task-attachment-store.js +49 -3
- package/dist/plugins/task-list-store-sql.d.ts +25 -0
- package/dist/plugins/task-list-store-sql.js +21 -0
- package/dist/plugins/tidb-approval-store.d.ts +6 -0
- package/dist/plugins/tidb-approval-store.js +6 -0
- package/dist/plugins/tidb-breaker-state.d.ts +5 -0
- package/dist/plugins/tidb-breaker-state.js +5 -0
- package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
- package/dist/plugins/tidb-checkpoint-store.js +7 -0
- package/dist/plugins/tidb-cost-quota.d.ts +6 -0
- package/dist/plugins/tidb-cost-quota.js +1 -0
- package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/tidb-file-snapshot-store.js +6 -0
- package/dist/plugins/tidb-image-bake.d.ts +8 -0
- package/dist/plugins/tidb-image-bake.js +8 -0
- package/dist/plugins/tidb-image-index.d.ts +8 -0
- package/dist/plugins/tidb-image-index.js +8 -0
- package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
- package/dist/plugins/tidb-outcome-ledger.js +10 -0
- package/dist/plugins/tidb-pool.d.ts +56 -0
- package/dist/plugins/tidb-pool.js +181 -1
- package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
- package/dist/plugins/tidb-rate-limiter.js +5 -2
- package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/tidb-resume-anchor-store.js +5 -0
- package/dist/plugins/tidb-run-store.d.ts +7 -0
- package/dist/plugins/tidb-run-store.js +7 -0
- package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
- package/dist/plugins/tidb-session-policy-store.js +5 -0
- package/dist/plugins/tidb-session-storage.d.ts +43 -0
- package/dist/plugins/tidb-session-storage.js +62 -3
- package/dist/plugins/tidb-session-store.d.ts +142 -0
- package/dist/plugins/tidb-session-store.js +264 -16
- package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
- package/dist/plugins/tidb-tool-result-store.js +7 -0
- package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/tidb-workflow-journal-store.js +7 -0
- package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
- package/dist/plugins/tidb-workflow-run-store.js +8 -0
- package/dist/plugins/tool-result-store-sql.d.ts +58 -0
- package/dist/plugins/tool-result-store-sql.js +38 -2
- package/dist/plugins/web-search.d.ts +35 -0
- package/dist/plugins/web-search.js +45 -9
- package/dist/plugins/workflow-journal-limits.d.ts +10 -0
- package/dist/plugins/workflow-journal-limits.js +10 -0
- package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
- package/dist/plugins/workflow-journal-store-sql.js +59 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
- package/dist/plugins/workflow-run-store-sql.js +84 -6
- package/dist/plugins/worktree-isolation.d.ts +45 -0
- package/dist/plugins/worktree-isolation.js +105 -6
- package/dist/plugins/write-behind-counter.d.ts +56 -1
- package/dist/plugins/write-behind-counter.js +53 -14
- package/dist/principal-jwt.d.ts +24 -0
- package/dist/principal-jwt.js +60 -5
- package/dist/project-memory.d.ts +22 -0
- package/dist/project-memory.js +144 -15
- package/dist/prompts-domain-validate.d.ts +28 -0
- package/dist/prompts-domain-validate.js +42 -1
- package/dist/question.d.ts +33 -0
- package/dist/question.js +69 -2
- package/dist/resource-suspend.d.ts +21 -0
- package/dist/resource-suspend.js +16 -0
- package/dist/router/route-orchestration.d.ts +78 -0
- package/dist/router/route-orchestration.js +77 -0
- package/dist/run-local.d.ts +32 -0
- package/dist/run-local.js +172 -8
- package/dist/runs.d.ts +189 -4
- package/dist/runs.js +465 -24
- package/dist/runtime-caps-resolver.d.ts +106 -0
- package/dist/runtime-caps-resolver.js +89 -4
- package/dist/runtime-governance.d.ts +84 -0
- package/dist/runtime-governance.js +127 -1
- package/dist/sandbox-pkg-source.d.ts +23 -0
- package/dist/sandbox-pkg-source.js +37 -0
- package/dist/sealed-key.d.ts +54 -0
- package/dist/sealed-key.js +68 -3
- package/dist/security.d.ts +108 -0
- package/dist/security.js +145 -6
- package/dist/sema-registry.d.ts +21 -0
- package/dist/sema-registry.js +21 -0
- package/dist/session-leaf-bus.d.ts +31 -0
- package/dist/session-leaf-bus.js +32 -0
- package/dist/session-sync-content.d.ts +46 -0
- package/dist/session-sync-content.js +47 -1
- package/dist/session-sync-kernel.d.ts +89 -0
- package/dist/session-sync-kernel.js +48 -3
- package/dist/session-sync.d.ts +125 -0
- package/dist/session-sync.js +181 -8
- package/dist/session-titler.d.ts +26 -0
- package/dist/session-titler.js +41 -7
- package/dist/session-watch.d.ts +53 -1
- package/dist/session-watch.js +73 -9
- package/dist/sighup-idle.d.ts +30 -0
- package/dist/sighup-idle.js +12 -1
- package/dist/spec-fields.d.ts +91 -3
- package/dist/spec-fields.js +116 -4
- package/dist/task-cwd.d.ts +50 -0
- package/dist/task-cwd.js +68 -1
- package/dist/task-mcp.d.ts +47 -0
- package/dist/task-mcp.js +29 -0
- package/dist/task-settings.d.ts +175 -0
- package/dist/task-settings.js +226 -11
- package/dist/task-workflow.d.ts +67 -0
- package/dist/task-workflow.js +75 -8
- package/dist/tool-approval.d.ts +91 -0
- package/dist/tool-approval.js +215 -0
- package/dist/trace/artifacts.d.ts +9 -0
- package/dist/trace/artifacts.js +30 -5
- package/dist/trace/core-keyset-guard.d.ts +18 -0
- package/dist/trace/ledger-sink.d.ts +43 -0
- package/dist/trace/ledger-sink.js +64 -5
- package/dist/trace/project.d.ts +133 -0
- package/dist/trace/project.js +189 -2
- package/dist/trace/redact.d.ts +19 -0
- package/dist/trace/redact.js +66 -9
- package/dist/usage-analytics.d.ts +26 -0
- package/dist/usage-analytics.js +26 -3
- package/package.json +1 -1
package/dist/parked-decide.d.ts
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 件3d `/decide` 消费 parked 后台子代——server 半场辅件(设计稿:sema-internal
|
|
3
|
+
* server/docs/DECIDE-PARKED-DESIGN.md;黑板 [1587];core 裁定 [1574]/[1584])。
|
|
4
|
+
*
|
|
5
|
+
* 本模块先落判别器:`POST /v1/approvals/:sessionId/decide` 路由在既有 session→token 映射拿到
|
|
6
|
+
* pending checkpoint 后,用它判定该 cp 是否属于一个 parked 后台子代——命中则走 claim →
|
|
7
|
+
* 裸 `ToolSpec.execute`(ctx.reviveClaim)赎回腿,不中则零回归走既有任务级 resumeCheckpoint 腿。
|
|
8
|
+
* 判别必须 parked-first:legacy 腿的 `resumeStream` 会绕开 bg registry(无 consumeParkedFlip、
|
|
9
|
+
* 行永 parked、生命周期分叉)。
|
|
10
|
+
*/
|
|
1
11
|
import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, TaskRegistry, ToolSpec } from "@sema-agent/core";
|
|
2
12
|
export interface ParkedAgentMatch {
|
|
3
13
|
handle: string;
|
|
4
14
|
row: BackgroundAgentRecord;
|
|
5
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* pending checkpoint → parked bg 行匹配。
|
|
18
|
+
*
|
|
19
|
+
* 键链(core 1.390 事实):park 时 cp 落 `sourceTaskId: sessionId`(子会话 id,**不是** bg handle),
|
|
20
|
+
* 而 bg 行同样存该子会话 id(`row.sessionId`)与绑定 token(`row.parkedCheckpointToken`)。
|
|
21
|
+
* `listByScope` 只回 summary(含 handle/sessionId、不含 token),故两步:summary.sessionId 初筛 →
|
|
22
|
+
* `get(handle, scope)` 全行复核 token。
|
|
23
|
+
*
|
|
24
|
+
* token 复核是硬门,不是优化:行 REOPENED 后可在**新** token 下 re-park,旧 cp 的 decide 不得
|
|
25
|
+
* 匹配到它(后续 `claimParkedAgent` 的 CAS/binding_broken 是兜底,不是第一道门)。同理,list 与
|
|
26
|
+
* get 之间行被 stop/decide 抢走(离开 parked)时诚实 miss——调用方拿 undefined 走 legacy 腿,
|
|
27
|
+
* 该腿对已消失的 pending cp 有自己的 404/409 处置。
|
|
28
|
+
*/
|
|
6
29
|
export declare function findParkedAgentForCheckpoint(agentStore: BackgroundAgentStore, cp: {
|
|
7
30
|
token: string;
|
|
8
31
|
scope: string;
|
|
@@ -11,9 +34,19 @@ export declare function findParkedAgentForCheckpoint(agentStore: BackgroundAgent
|
|
|
11
34
|
export interface ParkedDecideDeps {
|
|
12
35
|
agentStore: BackgroundAgentStore;
|
|
13
36
|
checkpointStore: Pick<CheckpointStore, "get">;
|
|
37
|
+
/** 与 reaper/scenarios 同一个 registry(claim/rollback 的 CAS 与 in-memory handle 收敛在同处)。 */
|
|
14
38
|
registry: Pick<TaskRegistry, "claimParkedAgent" | "rollbackParkedClaim">;
|
|
39
|
+
/** boot 期从生产装配(buildScenarios)取的裸 Agent ToolSpec——与 spawn 用同一装配路径,
|
|
40
|
+
* subRunner/bg opts/checkpointStore 同实例天然成立([1587] 设计稿 §4)。 */
|
|
15
41
|
reviveTool: ToolSpec;
|
|
42
|
+
/** revive args 的 `subagent_type` 成员性判定集([1588] Q1 修正:非 roster 成员必须省略,否则
|
|
43
|
+
* unknown subagent_type 拒;字面比对 general-purpose 在 roster 撞名时会错省)。缺省空集=恒省略。 */
|
|
16
44
|
knownAgentTypes?: ReadonlySet<string>;
|
|
45
|
+
/** [1596]/[1597] 跨进程父约束重供席:按部署配置**重建的同语义**父策略链工厂(host 任务的 toolPolicy
|
|
46
|
+
* 解析槽一条,单层链;exempt 探针锚= row.rootSessionId,与 remember grant 锚同键)。core 1.396 起
|
|
47
|
+
* `parkedResume.inheritedGate` 席位把它透传进 resume 的官方重供通道——不供 = 重启后带
|
|
48
|
+
* requiresParentConstraint 的 checkpoint 恒被 pre-CAS 门拒(retryable 假话,永不可赎回)。链长形状
|
|
49
|
+
* 校验在 core(fail-closed,供错链长照拒)。 */
|
|
17
50
|
rebuildInheritedGate?: (row: BackgroundAgentRecord) => unknown;
|
|
18
51
|
warn?: (event: string, fields: Record<string, unknown>) => void;
|
|
19
52
|
}
|
|
@@ -21,21 +54,49 @@ export interface ParkedDecideRequest {
|
|
|
21
54
|
token: string;
|
|
22
55
|
scope: string;
|
|
23
56
|
sessionId: string;
|
|
57
|
+
/** cp.pendingAction 原样(outcome 铸造的 persisted 回落源,与 legacy 腿 D-1 姿势逐字同形)。 */
|
|
24
58
|
pendingAction: unknown;
|
|
25
59
|
decision: "approve" | "deny";
|
|
26
60
|
reason?: string;
|
|
61
|
+
/** D-1 decision-binding echo(操作员在 GET 看到的 boundCallId/boundInputHash 原样透传;server
|
|
62
|
+
* 绝不重算,core resume 侧做 fail-closed 等值校验——与 legacy 腿同姿势)。 */
|
|
27
63
|
binding?: {
|
|
28
64
|
boundCallId?: string;
|
|
29
65
|
boundInputHash?: string;
|
|
30
66
|
updatedInput?: unknown;
|
|
31
67
|
};
|
|
68
|
+
/** body 带了 `remember:"session"` 时路由传入的 grant 执行器([1591] 候裁② 的 server 侧修,经两轮
|
|
69
|
+
* 行为探针实证):豁免必须锚在**行的 root/host 会话 id**——部署侧三个豁免探针(policy 层/fs-write
|
|
70
|
+
* 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`sourceTaskId` 只在
|
|
71
|
+
* onAsk 层的 AskRequest,durable 车道无 onAsk),grant 落子代会话则键永不相交(G-F4 原案);落
|
|
72
|
+
* root 会话则宿主键闭包立即命中,复活子代的后续同工具 ask 被短路(探针 v2 实证),语义与同步车道/
|
|
73
|
+
* 宿主任务的「本会话不再询问」一致(= host 会话树全域)。行无 root 锚(病态形)⇒ claim 前诚实 400。 */
|
|
32
74
|
grantRemember?: (rootSessionId: string) => Promise<void>;
|
|
75
|
+
/** body 带了 `answer`(复审 F6):parked 腿无 onQuestion 挂点,显式 400 与 legacy 腿对同一
|
|
76
|
+
* 畸形输入的拒绝姿势对齐(legacy:「answer 仅在 approve AskUserQuestion 时合法」),不静默吞。 */
|
|
33
77
|
answerPresent?: boolean;
|
|
78
|
+
/** claim CAS 赢了(≈ legacy 腿的 markResuming 赢)之后、execute 之前触发——remember 豁免 grant
|
|
79
|
+
* 的挂点(调用方自吞错,绝不抛落赎回)。claim 败/判别 miss 恒不触发。 */
|
|
34
80
|
onDecideCommitted?: () => Promise<void>;
|
|
35
81
|
}
|
|
36
82
|
export interface ParkedDecideResult {
|
|
37
83
|
status: number;
|
|
38
84
|
body: Record<string, unknown>;
|
|
39
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* `/decide` parked 赎回腿(design/153 件3d server 半场;[1574]/[1584]/[1588] core 裁定形)。
|
|
88
|
+
*
|
|
89
|
+
* 返回 `undefined` = 该 pending checkpoint 不属于任何 parked 后台子代——调用方走既有任务级
|
|
90
|
+
* resumeCheckpoint 腿(零回归);返回结果对象 = 赎回腿已受理/已拒,调用方直接回 HTTP。
|
|
91
|
+
*
|
|
92
|
+
* 链:判别(findParkedAgentForCheckpoint)→ `claimParkedAgent`(access = 行镜像双轴
|
|
93
|
+
* `{scope: row.scope, owner: row.owner}`,[1588] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
|
|
94
|
+
* → 裸 `reviveTool.execute(args, ctx.reviveClaim)`。execute 一旦发起 drive,rollback 全在 core 内
|
|
95
|
+
* (driveParkedResume);server 只在「claim 成功但 drive 从未发起」窗口补 `rollbackParkedClaim`
|
|
96
|
+
* ([1588] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
|
|
97
|
+
*
|
|
98
|
+
* 200 是**受理**语义(drive 是 core 内 fire-and-forget):失败经行/notification 面 + REOPENED
|
|
99
|
+
* re-park 诚实可见,操作员可再决。
|
|
100
|
+
*/
|
|
40
101
|
export declare function decideParkedAgent(deps: ParkedDecideDeps, req: ParkedDecideRequest): Promise<ParkedDecideResult | undefined>;
|
|
41
102
|
//# sourceMappingURL=parked-decide.d.ts.map
|
package/dist/parked-decide.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pending checkpoint → parked bg 行匹配。
|
|
3
|
+
*
|
|
4
|
+
* 键链(core 1.390 事实):park 时 cp 落 `sourceTaskId: sessionId`(子会话 id,**不是** bg handle),
|
|
5
|
+
* 而 bg 行同样存该子会话 id(`row.sessionId`)与绑定 token(`row.parkedCheckpointToken`)。
|
|
6
|
+
* `listByScope` 只回 summary(含 handle/sessionId、不含 token),故两步:summary.sessionId 初筛 →
|
|
7
|
+
* `get(handle, scope)` 全行复核 token。
|
|
8
|
+
*
|
|
9
|
+
* token 复核是硬门,不是优化:行 REOPENED 后可在**新** token 下 re-park,旧 cp 的 decide 不得
|
|
10
|
+
* 匹配到它(后续 `claimParkedAgent` 的 CAS/binding_broken 是兜底,不是第一道门)。同理,list 与
|
|
11
|
+
* get 之间行被 stop/decide 抢走(离开 parked)时诚实 miss——调用方拿 undefined 走 legacy 腿,
|
|
12
|
+
* 该腿对已消失的 pending cp 有自己的 404/409 处置。
|
|
13
|
+
*/
|
|
1
14
|
export async function findParkedAgentForCheckpoint(agentStore, cp) {
|
|
2
15
|
const parked = await agentStore.listByScope(cp.scope, { status: "parked" });
|
|
3
16
|
for (const s of parked) {
|
|
@@ -12,6 +25,9 @@ export async function findParkedAgentForCheckpoint(agentStore, cp) {
|
|
|
12
25
|
}
|
|
13
26
|
return undefined;
|
|
14
27
|
}
|
|
28
|
+
/** [1588] Q1 裁定的 revive args 铸法:占位 prompt(objective 在 driveParkedResume 被丢弃,仅过非空门)、
|
|
29
|
+
* `run_in_background: true` 必须(revive.no_background 拒)、`name` 必传承重(名门校验+下游 park 资格
|
|
30
|
+
* 谓词吃 agentName)、`subagent_type` 按 roster 成员性判。 */
|
|
15
31
|
function mintReviveArgs(row, knownAgentTypes) {
|
|
16
32
|
return {
|
|
17
33
|
prompt: row.description ?? "resume parked agent",
|
|
@@ -21,16 +37,34 @@ function mintReviveArgs(row, knownAgentTypes) {
|
|
|
21
37
|
...(row.agentType !== undefined && knownAgentTypes.has(row.agentType) ? { subagent_type: row.agentType } : {}),
|
|
22
38
|
};
|
|
23
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* `/decide` parked 赎回腿(design/153 件3d server 半场;[1574]/[1584]/[1588] core 裁定形)。
|
|
42
|
+
*
|
|
43
|
+
* 返回 `undefined` = 该 pending checkpoint 不属于任何 parked 后台子代——调用方走既有任务级
|
|
44
|
+
* resumeCheckpoint 腿(零回归);返回结果对象 = 赎回腿已受理/已拒,调用方直接回 HTTP。
|
|
45
|
+
*
|
|
46
|
+
* 链:判别(findParkedAgentForCheckpoint)→ `claimParkedAgent`(access = 行镜像双轴
|
|
47
|
+
* `{scope: row.scope, owner: row.owner}`,[1588] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
|
|
48
|
+
* → 裸 `reviveTool.execute(args, ctx.reviveClaim)`。execute 一旦发起 drive,rollback 全在 core 内
|
|
49
|
+
* (driveParkedResume);server 只在「claim 成功但 drive 从未发起」窗口补 `rollbackParkedClaim`
|
|
50
|
+
* ([1588] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
|
|
51
|
+
*
|
|
52
|
+
* 200 是**受理**语义(drive 是 core 内 fire-and-forget):失败经行/notification 面 + REOPENED
|
|
53
|
+
* re-park 诚实可见,操作员可再决。
|
|
54
|
+
*/
|
|
24
55
|
export async function decideParkedAgent(deps, req) {
|
|
25
56
|
let match;
|
|
26
57
|
try {
|
|
27
58
|
match = await findParkedAgentForCheckpoint(deps.agentStore, { token: req.token, scope: req.scope, sessionId: req.sessionId });
|
|
28
59
|
}
|
|
29
60
|
catch (e) {
|
|
61
|
+
// 复审 F2:bg 店瞬态读故障绝不能把(含任务级在内的)decide 变裸 500——诚实按 miss 处理,
|
|
62
|
+
// legacy 腿对 parked cp 有自己的 409 处置(retriable),任务级 cp 照常 resume。
|
|
30
63
|
try {
|
|
31
64
|
deps.warn?.("parked_decide_probe_failed", { error: e instanceof Error ? e.message : String(e) });
|
|
32
65
|
}
|
|
33
66
|
catch {
|
|
67
|
+
// warn 自身故障不改变结果面
|
|
34
68
|
}
|
|
35
69
|
return undefined;
|
|
36
70
|
}
|
|
@@ -39,16 +73,22 @@ export async function decideParkedAgent(deps, req) {
|
|
|
39
73
|
const row = match.row;
|
|
40
74
|
const rememberRoot = req.grantRemember !== undefined ? (row.rootSessionId ?? row.parentSessionId) : undefined;
|
|
41
75
|
if (req.grantRemember !== undefined && rememberRoot === undefined) {
|
|
76
|
+
// remember 的 grant 必须锚在 root/host 会话(探针闭包键);行无任何会话锚 = 无处可落,claim 前诚实拒。
|
|
42
77
|
return { status: 400, body: { error: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", errorCode: "decide.parked_remember_unsupported", taskId: match.handle } };
|
|
43
78
|
}
|
|
44
79
|
if (req.answerPresent === true) {
|
|
80
|
+
// 复审 F6:与 legacy 腿同姿势显式拒,不静默丢弃操作员的输入。
|
|
45
81
|
return { status: 400, body: { error: "body.answer is not supported when deciding a parked background agent (no question hookpoint on the revive path)", errorCode: "decide.parked_answer_unsupported", taskId: match.handle } };
|
|
46
82
|
}
|
|
47
83
|
const pendingTool = req.pendingAction?.toolName;
|
|
48
84
|
if (pendingTool === "AskUserQuestion" && req.decision === "approve") {
|
|
85
|
+
// 复审 F1:只拦 approve(approve 必须携 answer 才有意义,而 parked 腿无 onQuestion 挂点);
|
|
86
|
+
// deny 放行走赎回(deny outcome 不需要 answer),决策面不留死角。claim 之前拒,claim 不被消费。
|
|
49
87
|
return { status: 400, body: { error: "pending action is AskUserQuestion — approve is not supported for a parked background agent (deny it, stop the agent, or let the gate expire)", errorCode: "decide.parked_question_unsupported", taskId: match.handle } };
|
|
50
88
|
}
|
|
51
89
|
if (row.name === undefined) {
|
|
90
|
+
// forwardDurableApproval 只对具名子代成立,parked 行理应恒有 name;缺 = 行受损,claim 前诚实拒
|
|
91
|
+
// ([1588] Q1:name 必传承重——省略会把 revive 降级成匿名形)。
|
|
52
92
|
return { status: 409, body: { error: "parked row carries no agent name — the revive path requires a named agent (row damaged?)", errorCode: "decide.row_unrevivable", taskId: match.handle } };
|
|
53
93
|
}
|
|
54
94
|
const stores = { agentStore: deps.agentStore, checkpointStore: deps.checkpointStore };
|
|
@@ -58,11 +98,13 @@ export async function decideParkedAgent(deps, req) {
|
|
|
58
98
|
case "store_unreachable":
|
|
59
99
|
return { status: 503, body: { error: "the durable agent store is unreachable — retry", errorCode: "decide.store_unreachable", taskId: match.handle } };
|
|
60
100
|
case "claim_lost":
|
|
101
|
+
// 复审 F8:claim_lost 也覆盖「上一轮 rollback 落 retry(claim 悬挂)」的形——那时要等 reaper 的
|
|
102
|
+
// stale-claim 清算窗(BG_AGENT_PARK_CLAIM_STALE_MS)过后才能再决,文案如实给出两种可能。
|
|
61
103
|
return { status: 409, body: { error: "the parked agent is already claimed — either a concurrent decide won (re-check the pending list), or a stale claim is pending automatic cleanup (retry after the stale-claim window)", errorCode: "decide.claim_lost", taskId: match.handle } };
|
|
62
104
|
case "binding_broken":
|
|
63
105
|
case "checkpoint_not_pending":
|
|
64
106
|
return { status: 409, body: { error: "the approval gate moved under this decide (re-parked or already settled) — re-check the pending list", errorCode: "decide.gate_moved", taskId: match.handle } };
|
|
65
|
-
default:
|
|
107
|
+
default: // not_found | not_parked——行在判别与 claim 之间被 stop/另一 decide 抢走
|
|
66
108
|
return { status: 409, body: { error: "the parked agent moved under this decide (stopped or already decided)", errorCode: "decide.not_parked", taskId: match.handle } };
|
|
67
109
|
}
|
|
68
110
|
}
|
|
@@ -71,12 +113,17 @@ export async function decideParkedAgent(deps, req) {
|
|
|
71
113
|
await req.onDecideCommitted?.();
|
|
72
114
|
}
|
|
73
115
|
catch {
|
|
116
|
+
// remember-grant 类挂点自吞错(与 legacy 腿 grantOnCommit 同姿势):绝不让豁免记账故障打断赎回。
|
|
74
117
|
}
|
|
75
118
|
if (req.grantRemember !== undefined && rememberRoot !== undefined) {
|
|
76
119
|
try {
|
|
120
|
+
// claim 赢(≈ legacy 腿 markResuming CAS 赢)后、drive 前落店——复活腿自己的下一个同工具 ask
|
|
121
|
+
// 即可命中豁免(与 legacy 腿 1.294 grant-timing 裁定同向)。grant 失败由路由闭包自记 warn 并
|
|
122
|
+
// 让 rememberApplied 如实为 false,不阻断赎回。
|
|
77
123
|
await req.grantRemember(rememberRoot);
|
|
78
124
|
}
|
|
79
125
|
catch {
|
|
126
|
+
// 同上:豁免记账故障不进赎回结果面
|
|
80
127
|
}
|
|
81
128
|
}
|
|
82
129
|
const pa = req.pendingAction;
|
|
@@ -98,15 +145,20 @@ export async function decideParkedAgent(deps, req) {
|
|
|
98
145
|
parkedResume: {
|
|
99
146
|
ticket,
|
|
100
147
|
outcome,
|
|
148
|
+
// [1597] 席位:重建父约束链(同进程时 core 的内存 registry 也能自动重供,席位供了也无害
|
|
149
|
+
// ——core 侧 count 校验对得上即用;跨进程/重启形全靠这里)。
|
|
101
150
|
...(deps.rebuildInheritedGate ? { inheritedGate: deps.rebuildInheritedGate(row) } : {}),
|
|
102
151
|
},
|
|
103
152
|
},
|
|
104
153
|
};
|
|
154
|
+
// 复审 F7:warn 回调自身故障(duck-typed logger 缺方法/日志面抖动)绝不能改写 rollback 的结果面——
|
|
155
|
+
// 已成功的回滚若因 warn 抛错逃逸成 500/reject,操作员会对着"失败"重试一个其实已回纯的行。
|
|
105
156
|
const quietWarn = (event, fields) => {
|
|
106
157
|
try {
|
|
107
158
|
deps.warn?.(event, fields);
|
|
108
159
|
}
|
|
109
160
|
catch {
|
|
161
|
+
// 观测面故障不进结果面
|
|
110
162
|
}
|
|
111
163
|
};
|
|
112
164
|
const rollback = async (why) => {
|
|
@@ -138,6 +190,11 @@ export async function decideParkedAgent(deps, req) {
|
|
|
138
190
|
}
|
|
139
191
|
const isErr = typeof receipt === "object" && receipt !== null && receipt.isError === true;
|
|
140
192
|
if (isErr) {
|
|
193
|
+
// execute 的入参级早退臂(revive.no_background/name 门/type 门等)return 于任何 registry 动作之前,
|
|
194
|
+
// core 不代滚([1588] Q2 核定)——这仍在「drive 未发起」窗口,server 补滚。
|
|
195
|
+
// 复审 G-F5 口径补充:isError 不恒等于「早退未滚」——core 的 parked_resume.startup_failed 臂是
|
|
196
|
+
// drive 已发起且 core 已自滚后的 isError;此处补滚在 rollbackParkedClaim 的 claimId CAS 下退化为
|
|
197
|
+
// 无害 "lost"([1588] Q2 幂等核定),结果面仍诚实(操作员重查 pending 列表即可自愈)。
|
|
141
198
|
const disp = await rollback("execute_rejected");
|
|
142
199
|
const content = receipt.content;
|
|
143
200
|
return {
|
package/dist/per-task-image.d.ts
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §7 P0.5 — per-task sandbox image binding (門B "用户按需选像"). IMAGE-API-DESIGN §7.
|
|
3
|
+
*
|
|
4
|
+
* The caller sends a PROFILE (intent) on the run body — NEVER a digest. The trusted control plane (this service,
|
|
5
|
+
* with the caller's principal) resolves the profile → a pullable `repo@digest`, FAIL-CLOSED, re-admitting by the
|
|
6
|
+
* SAME per-principal visibility the `/v1/images/select` admission uses. Why profile-not-digest: a digest is a
|
|
7
|
+
* stable, enumerable sha256 with no caller-binding — trusting a caller-supplied digest is fail-OPEN (a user could
|
|
8
|
+
* pass another tenant's digest to pull an image they can't see). Resolving inside the trust boundary closes that.
|
|
9
|
+
*
|
|
10
|
+
* The resolved ref reaches the worker-global {@link import("@sema-agent/core").ExecutionEnvFactory} (which
|
|
11
|
+
* only receives core's deliberately-minimal `{sessionId}` context) via {@link PerTaskImageRegistry} — core's own
|
|
12
|
+
* doctrine: "richer routing is captured in the factory closure by the trusted control plane". This module is that
|
|
13
|
+
* capture, kept narrow + unit-testable.
|
|
14
|
+
*/
|
|
1
15
|
import type { ImageViewer, ImageIndexEntry } from "./plugins/store-contracts.js";
|
|
16
|
+
/** Minimal slice of the image index the per-task resolver needs (a testable seam — the real `imageIndex`'s
|
|
17
|
+
* `latestPublished` returns the full {@link ImageIndexEntry}, which is assignable to this Pick). */
|
|
2
18
|
export interface SandboxImageResolver {
|
|
3
19
|
latestPublished(profile: string, viewer: ImageViewer): Promise<Pick<ImageIndexEntry, "repo" | "digest" | "capabilities"> | null>;
|
|
4
20
|
}
|
|
@@ -11,17 +27,55 @@ export type SandboxImageResolution = {
|
|
|
11
27
|
status: number;
|
|
12
28
|
message: string;
|
|
13
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a requested sandbox image PROFILE to a pullable `repo@digest`, FAIL-CLOSED, re-admitting by `viewer`:
|
|
32
|
+
* - `latestPublished(profile, viewer)` applies the SAME `visibilityClause` + `status='published'` filter the
|
|
33
|
+
* select admission uses. Not visible / not published ⇒ `{ok:false, 404}` (never silent-allow).
|
|
34
|
+
* - each `capabilitiesNeeded` entry must be a known boolean capability AND true on the resolved image, else fail.
|
|
35
|
+
* Pure over the injected `index` ⇒ unit-testable with a fake resolver.
|
|
36
|
+
*
|
|
37
|
+
* NOTE (review LOW — error-code asymmetry, DELIBERATE): a not-visible / capability-miss here returns 404, whereas
|
|
38
|
+
* the operator-facing `POST /v1/images/select` returns 409 + `missing`. That is intentional: task admission is an
|
|
39
|
+
* UNTRUSTED-caller gate that must NOT distinguish "profile exists but you can't see it" from "doesn't exist"
|
|
40
|
+
* (revealing that leaks the existence of other tenants' images), so it collapses both to 404. The select catalog
|
|
41
|
+
* is the operator's own scoped view, where the richer 409 + `missing` detail is safe.
|
|
42
|
+
*/
|
|
14
43
|
export declare function resolveSandboxImageRef(opts: {
|
|
15
44
|
profile: string;
|
|
16
45
|
capabilitiesNeeded?: readonly string[];
|
|
17
46
|
viewer: ImageViewer;
|
|
18
47
|
index: SandboxImageResolver;
|
|
19
48
|
}): Promise<SandboxImageResolution>;
|
|
49
|
+
/**
|
|
50
|
+
* The trusted-control-plane bridge from `resolveSpec` (resolves the per-task image with the caller's principal) to
|
|
51
|
+
* the worker-global `ExecutionEnvFactory` (gets only core's minimal `{sessionId, taskId?}`). NOT a durable store
|
|
52
|
+
* and NOT a cache: `resolveSpec` REPOPULATES it on EVERY call — initial AND resume, on whichever replica runs
|
|
53
|
+
* resolveSpec immediately before the factory — so a cross-replica resume re-resolves LIVE (the resume re-admit
|
|
54
|
+
* discipline: a stale persisted digest can never bypass admission), and there is nothing durable to go stale.
|
|
55
|
+
*
|
|
56
|
+
* KEYED BY sessionId — the ONLY identifier stable across the factory `ctx` on every path (adversarial-review
|
|
57
|
+
* round-2): `/v1/runs` mints its OWN durable taskId that clobbers `spec.taskId`, so keying by taskId misses on the
|
|
58
|
+
* primary path; `sessionId` survives the spec spread on every path. `get()` is NON-removing (the factory may be
|
|
59
|
+
* invoked >once per logical task). Cleanup is by bounded eviction (oldest-first) — each entry is a tiny string; an
|
|
60
|
+
* evicted task is long finished.
|
|
61
|
+
*
|
|
62
|
+
* ⚠️ KNOWN narrow edge (same-principal correctness, NOT a security breach): two CONCURRENT requests for the SAME
|
|
63
|
+
* session (necessarily the same owner — session ownership is enforced) race `set()`; a request the run-claim later
|
|
64
|
+
* rejects (409) can leave its image bound for the active run. Both images are the same principal's own admitted
|
|
65
|
+
* images, so the worst case is the user's run using the user's OTHER selected image. The hardening
|
|
66
|
+
* (register-after-claim, keyed by the durable run id) needs the registry threaded into the server claim path —
|
|
67
|
+
* tracked as a follow-up. cascade/verify + a profile are rejected up front (they strip/replace the session).
|
|
68
|
+
*/
|
|
20
69
|
export declare class PerTaskImageRegistry {
|
|
21
70
|
private readonly maxEntries;
|
|
22
71
|
private readonly map;
|
|
23
72
|
constructor(maxEntries?: number);
|
|
73
|
+
/** Register the resolved `repo@digest` for a session. A re-set (resume / a later same-session task) overwrites;
|
|
74
|
+
* on overflow the oldest insertion is evicted so an orphaned entry (a resolveSpec not followed by a factory
|
|
75
|
+
* call, e.g. a rejected/pre-exec-failed request) stays bounded. */
|
|
24
76
|
set(sessionId: string, ref: string): void;
|
|
77
|
+
/** Read the ref for a session (NON-removing — the factory may be invoked more than once per logical task).
|
|
78
|
+
* `undefined` ⇒ no per-task image for this session ⇒ the factory uses its worker-global default image. */
|
|
25
79
|
get(sessionId: string | undefined): string | undefined;
|
|
26
80
|
}
|
|
27
81
|
//# sourceMappingURL=per-task-image.d.ts.map
|
package/dist/per-task-image.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
+
/** Boolean capability keys a caller may require. `nestedBuildMode` is a posture string, not a boolean gate, so it
|
|
2
|
+
* is intentionally NOT requestable here (capability admission is allow-on-true only). */
|
|
1
3
|
const REQUESTABLE_CAPS = new Set(["browser", "db", "nestedBuild"]);
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a requested sandbox image PROFILE to a pullable `repo@digest`, FAIL-CLOSED, re-admitting by `viewer`:
|
|
6
|
+
* - `latestPublished(profile, viewer)` applies the SAME `visibilityClause` + `status='published'` filter the
|
|
7
|
+
* select admission uses. Not visible / not published ⇒ `{ok:false, 404}` (never silent-allow).
|
|
8
|
+
* - each `capabilitiesNeeded` entry must be a known boolean capability AND true on the resolved image, else fail.
|
|
9
|
+
* Pure over the injected `index` ⇒ unit-testable with a fake resolver.
|
|
10
|
+
*
|
|
11
|
+
* NOTE (review LOW — error-code asymmetry, DELIBERATE): a not-visible / capability-miss here returns 404, whereas
|
|
12
|
+
* the operator-facing `POST /v1/images/select` returns 409 + `missing`. That is intentional: task admission is an
|
|
13
|
+
* UNTRUSTED-caller gate that must NOT distinguish "profile exists but you can't see it" from "doesn't exist"
|
|
14
|
+
* (revealing that leaks the existence of other tenants' images), so it collapses both to 404. The select catalog
|
|
15
|
+
* is the operator's own scoped view, where the richer 409 + `missing` detail is safe.
|
|
16
|
+
*/
|
|
2
17
|
export async function resolveSandboxImageRef(opts) {
|
|
3
18
|
const entry = await opts.index.latestPublished(opts.profile, opts.viewer);
|
|
4
19
|
if (!entry) {
|
|
@@ -13,14 +28,38 @@ export async function resolveSandboxImageRef(opts) {
|
|
|
13
28
|
return { ok: false, status: 404, message: `sandbox image for profile "${opts.profile}" does not provide capability "${cap}"` };
|
|
14
29
|
}
|
|
15
30
|
}
|
|
31
|
+
// capabilities ride along for RFC A1 envFacts (the resolved entry is already in hand — no second query).
|
|
16
32
|
return { ok: true, ref: `${entry.repo}@${entry.digest}`, capabilities: entry.capabilities };
|
|
17
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The trusted-control-plane bridge from `resolveSpec` (resolves the per-task image with the caller's principal) to
|
|
36
|
+
* the worker-global `ExecutionEnvFactory` (gets only core's minimal `{sessionId, taskId?}`). NOT a durable store
|
|
37
|
+
* and NOT a cache: `resolveSpec` REPOPULATES it on EVERY call — initial AND resume, on whichever replica runs
|
|
38
|
+
* resolveSpec immediately before the factory — so a cross-replica resume re-resolves LIVE (the resume re-admit
|
|
39
|
+
* discipline: a stale persisted digest can never bypass admission), and there is nothing durable to go stale.
|
|
40
|
+
*
|
|
41
|
+
* KEYED BY sessionId — the ONLY identifier stable across the factory `ctx` on every path (adversarial-review
|
|
42
|
+
* round-2): `/v1/runs` mints its OWN durable taskId that clobbers `spec.taskId`, so keying by taskId misses on the
|
|
43
|
+
* primary path; `sessionId` survives the spec spread on every path. `get()` is NON-removing (the factory may be
|
|
44
|
+
* invoked >once per logical task). Cleanup is by bounded eviction (oldest-first) — each entry is a tiny string; an
|
|
45
|
+
* evicted task is long finished.
|
|
46
|
+
*
|
|
47
|
+
* ⚠️ KNOWN narrow edge (same-principal correctness, NOT a security breach): two CONCURRENT requests for the SAME
|
|
48
|
+
* session (necessarily the same owner — session ownership is enforced) race `set()`; a request the run-claim later
|
|
49
|
+
* rejects (409) can leave its image bound for the active run. Both images are the same principal's own admitted
|
|
50
|
+
* images, so the worst case is the user's run using the user's OTHER selected image. The hardening
|
|
51
|
+
* (register-after-claim, keyed by the durable run id) needs the registry threaded into the server claim path —
|
|
52
|
+
* tracked as a follow-up. cascade/verify + a profile are rejected up front (they strip/replace the session).
|
|
53
|
+
*/
|
|
18
54
|
export class PerTaskImageRegistry {
|
|
19
55
|
maxEntries;
|
|
20
56
|
map = new Map();
|
|
21
57
|
constructor(maxEntries = 4096) {
|
|
22
58
|
this.maxEntries = maxEntries;
|
|
23
59
|
}
|
|
60
|
+
/** Register the resolved `repo@digest` for a session. A re-set (resume / a later same-session task) overwrites;
|
|
61
|
+
* on overflow the oldest insertion is evicted so an orphaned entry (a resolveSpec not followed by a factory
|
|
62
|
+
* call, e.g. a rejected/pre-exec-failed request) stays bounded. */
|
|
24
63
|
set(sessionId, ref) {
|
|
25
64
|
this.map.delete(sessionId);
|
|
26
65
|
this.map.set(sessionId, ref);
|
|
@@ -30,6 +69,8 @@ export class PerTaskImageRegistry {
|
|
|
30
69
|
this.map.delete(oldest);
|
|
31
70
|
}
|
|
32
71
|
}
|
|
72
|
+
/** Read the ref for a session (NON-removing — the factory may be invoked more than once per logical task).
|
|
73
|
+
* `undefined` ⇒ no per-task image for this session ⇒ the factory uses its worker-global default image. */
|
|
33
74
|
get(sessionId) {
|
|
34
75
|
return sessionId === undefined ? undefined : this.map.get(sessionId);
|
|
35
76
|
}
|
|
@@ -1,21 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan-cache recurrence probe — INSTRUMENT-FIRST (search AI → service, 团队/给service-AI.md [1];
|
|
3
|
+
* core design/42). Zero-LLM, zero-dependency, pure in-memory.
|
|
4
|
+
*
|
|
5
|
+
* Measures the **per-scope recurrence rate of task objectives**: the unproven "省钱" premise behind a
|
|
6
|
+
* proposed core *plan-caching* feature (store a successful run's generalized plan → a similar new task
|
|
7
|
+
* retrieves it as a hint). The 2-juror review wanted real data before core builds the producer hook:
|
|
8
|
+
* does an agent's traffic actually re-pose near-duplicate objectives per tenant? (arXiv 2602.18922:
|
|
9
|
+
* heterogeneous queries can hit 0–12%.) We hold the real multi-tenant traffic, so this is ours to count.
|
|
10
|
+
*
|
|
11
|
+
* **The token criterion is copied verbatim from core `src/core/strategy-store.ts`** (`tokens()` /
|
|
12
|
+
* `significant()` / `find()` lines 46-52, 107-110) — otherwise we'd measure something other than what
|
|
13
|
+
* plan-cache retrieval would actually use. Note the **asymmetry**: a stored problem is matched on its
|
|
14
|
+
* full `tokens()` set, the query on its `significant()` set, and a hit = every significant query token
|
|
15
|
+
* is present in some stored problem (`significant(new) ⊆ tokens(historical)`).
|
|
16
|
+
*
|
|
17
|
+
* Fidelity choices (stated to search AI for confirmation): the history ring holds only **completed**
|
|
18
|
+
* tasks (plan-cache only stores plans from successful runs), while the hit test runs for **every**
|
|
19
|
+
* finished task; `qSig` length is bucketed so a hit can be told apart from a short-objective fluke
|
|
20
|
+
* (the juror's `qSig>=3` gate).
|
|
21
|
+
*/
|
|
1
22
|
import type { Metrics } from "./observability/metrics.js";
|
|
2
23
|
import type { Logger } from "./observability/logger.js";
|
|
24
|
+
/** Lowercased word tokens (core口径). */
|
|
3
25
|
export declare function tokens(s: string): string[];
|
|
26
|
+
/** Meaningful tokens: ≥3 chars, not a stopword (core口径). */
|
|
4
27
|
export declare function significant(s: string): string[];
|
|
28
|
+
/** Per-scope view for the 2-week handoff back to search AI. */
|
|
5
29
|
export interface ScopeRecurrence {
|
|
6
30
|
tasks: number;
|
|
7
31
|
hits: number;
|
|
8
32
|
hitRate: number;
|
|
33
|
+
/** qSig-length histogram (index 0..QSIG_CAP; last bucket = QSIG_CAP+). */
|
|
9
34
|
qsig: number[];
|
|
10
35
|
}
|
|
11
36
|
export declare const QSIG_CAP = 12;
|
|
37
|
+
/**
|
|
38
|
+
* In-memory recurrence tracker. One per process (single replica per worker in prod; cross-replica
|
|
39
|
+
* aggregation is unnecessary for a 2-week instrument — each instance reports its own slice).
|
|
40
|
+
*/
|
|
12
41
|
export declare class PlanCacheProbe {
|
|
13
42
|
private readonly metrics?;
|
|
14
43
|
private readonly logger?;
|
|
15
44
|
private readonly byScope;
|
|
16
45
|
constructor(metrics?: Metrics | undefined, logger?: Logger | undefined);
|
|
46
|
+
/**
|
|
47
|
+
* Record one finished task. `completed` = it succeeded (only those enter the history ring). Pure
|
|
48
|
+
* in-memory + a counter/histogram + a debug log line; never throws into the caller.
|
|
49
|
+
*/
|
|
17
50
|
record(scopeRaw: string | undefined, objective: string, completed: boolean): void;
|
|
51
|
+
/** Per-scope recurrence snapshot for the handoff (token-gated dump endpoint). */
|
|
18
52
|
dump(): Record<string, ScopeRecurrence>;
|
|
53
|
+
/** LRU get-or-create: re-insert on access so the oldest-touched scope is evicted past the cap. */
|
|
19
54
|
private touch;
|
|
20
55
|
}
|
|
21
56
|
//# sourceMappingURL=plan-cache-probe.d.ts.map
|
package/dist/plan-cache-probe.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
+
// Verbatim from core strategy-store.ts (keep in sync if core changes its stopword set).
|
|
1
2
|
const STOP = new Set([
|
|
2
3
|
"the", "and", "for", "with", "from", "this", "that", "into", "your", "you", "are", "was", "were", "has",
|
|
3
4
|
"have", "had", "not", "but", "all", "any", "can", "use", "using", "via", "then", "than", "out", "get",
|
|
4
5
|
"got", "its", "it's", "their", "them", "they", "what", "when", "which", "who", "how", "why", "a", "an",
|
|
5
6
|
"of", "to", "in", "on", "is", "it", "or", "as", "at", "by", "be", "do", "if", "so", "no", "up", "we",
|
|
6
7
|
]);
|
|
8
|
+
/** Lowercased word tokens (core口径). */
|
|
7
9
|
export function tokens(s) {
|
|
8
10
|
return s.toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
9
11
|
}
|
|
12
|
+
/** Meaningful tokens: ≥3 chars, not a stopword (core口径). */
|
|
10
13
|
export function significant(s) {
|
|
11
14
|
return tokens(s).filter((t) => t.length >= 3 && !STOP.has(t));
|
|
12
15
|
}
|
|
13
|
-
const RING = 1000;
|
|
14
|
-
const MAX_SCOPES = 2000;
|
|
15
|
-
export const QSIG_CAP = 12;
|
|
16
|
+
const RING = 1000; // most-recent completed tasks per scope (= search AI's N=1000)
|
|
17
|
+
const MAX_SCOPES = 2000; // LRU cap on tracked scopes — bounds memory under high tenant cardinality
|
|
18
|
+
export const QSIG_CAP = 12; // qSig-length histogram cap (>=12 collapses into the last bucket)
|
|
19
|
+
/**
|
|
20
|
+
* In-memory recurrence tracker. One per process (single replica per worker in prod; cross-replica
|
|
21
|
+
* aggregation is unnecessary for a 2-week instrument — each instance reports its own slice).
|
|
22
|
+
*/
|
|
16
23
|
export class PlanCacheProbe {
|
|
17
24
|
metrics;
|
|
18
25
|
logger;
|
|
@@ -21,10 +28,16 @@ export class PlanCacheProbe {
|
|
|
21
28
|
this.metrics = metrics;
|
|
22
29
|
this.logger = logger;
|
|
23
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Record one finished task. `completed` = it succeeded (only those enter the history ring). Pure
|
|
33
|
+
* in-memory + a counter/histogram + a debug log line; never throws into the caller.
|
|
34
|
+
*/
|
|
24
35
|
record(scopeRaw, objective, completed) {
|
|
25
36
|
const scope = scopeRaw && scopeRaw.length > 0 ? scopeRaw : "anon";
|
|
26
37
|
const qSig = significant(objective);
|
|
27
38
|
const st = this.touch(scope);
|
|
39
|
+
// Hit = some historical (completed) task's full token set ⊇ this task's significant tokens.
|
|
40
|
+
// qSig empty → never a hit (mirrors find()'s `qSig.length===0 → []`, no injection).
|
|
28
41
|
let hit = false;
|
|
29
42
|
if (qSig.length > 0) {
|
|
30
43
|
for (const hist of st.ring) {
|
|
@@ -47,6 +60,7 @@ export class PlanCacheProbe {
|
|
|
47
60
|
this.metrics?.observe("plan_cache_qsig", qSig.length);
|
|
48
61
|
this.logger?.debug("plan-cache recurrence probe", { scope, qSig: qSig.length, hit, completed });
|
|
49
62
|
}
|
|
63
|
+
/** Per-scope recurrence snapshot for the handoff (token-gated dump endpoint). */
|
|
50
64
|
dump() {
|
|
51
65
|
const out = {};
|
|
52
66
|
for (const [scope, st] of this.byScope) {
|
|
@@ -59,6 +73,7 @@ export class PlanCacheProbe {
|
|
|
59
73
|
}
|
|
60
74
|
return out;
|
|
61
75
|
}
|
|
76
|
+
/** LRU get-or-create: re-insert on access so the oldest-touched scope is evicted past the cap. */
|
|
62
77
|
touch(scope) {
|
|
63
78
|
let st = this.byScope.get(scope);
|
|
64
79
|
if (st) {
|
|
@@ -6,10 +6,15 @@ export interface ApprovalExemptionRow {
|
|
|
6
6
|
createdAt: number;
|
|
7
7
|
}
|
|
8
8
|
export interface ApprovalExemptionStore {
|
|
9
|
+
/** Record the exemption (idempotent upsert; a re-grant refreshes grantedBy, createdAt keeps the FIRST grant). */
|
|
9
10
|
grant(sessionId: string, toolName: string, grantedBy: string | null): Promise<void>;
|
|
11
|
+
/** The ask-gate probe. Callers MUST fail-closed on a rejected promise (ask anyway). */
|
|
10
12
|
has(sessionId: string, toolName: string): Promise<boolean>;
|
|
13
|
+
/** All exemptions for a session (the GET /v1/approvals UI surface). */
|
|
11
14
|
list(sessionId: string): Promise<ApprovalExemptionRow[]>;
|
|
15
|
+
/** Revoke one exemption; false = nothing to revoke (idempotent). */
|
|
12
16
|
revoke(sessionId: string, toolName: string): Promise<boolean>;
|
|
17
|
+
/** E21 — purge ALL exemptions for a session (session delete wiring). Idempotent (affected count). */
|
|
13
18
|
deleteBySession(sessionId: string): Promise<number>;
|
|
14
19
|
}
|
|
15
20
|
export declare class TiDBApprovalExemptionStore implements ApprovalExemptionStore {
|
|
@@ -44,6 +49,7 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
|
|
|
44
49
|
private readonly logs;
|
|
45
50
|
constructor(root: string);
|
|
46
51
|
private pathFor;
|
|
52
|
+
/** Replay every session log (torn-tail-safe; last-wins with revoke tombstones). Index keyed by the SANITIZED id. */
|
|
47
53
|
private hydrate;
|
|
48
54
|
private logFor;
|
|
49
55
|
grant(sessionId: string, toolName: string, grantedBy: string | null): Promise<void>;
|
|
@@ -51,6 +57,7 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
|
|
|
51
57
|
list(sessionId: string): Promise<ApprovalExemptionRow[]>;
|
|
52
58
|
revoke(sessionId: string, toolName: string): Promise<boolean>;
|
|
53
59
|
deleteBySession(sessionId: string): Promise<number>;
|
|
60
|
+
/** Release every open append-log fd (LocalBackend.close → graceful-restart re-open). */
|
|
54
61
|
dispose(): void;
|
|
55
62
|
}
|
|
56
63
|
//# sourceMappingURL=approval-exemption-store.d.ts.map
|
|
@@ -1,6 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session per-toolName approval exemption ("本会话不再询问",
|
|
3
|
+
* design: docs/design/APPROVAL-SESSION-EXEMPTION.md).
|
|
4
|
+
*
|
|
5
|
+
* SEMANTICS (the boundary that keeps this an APPROVAL MEMORY, not a policy loosen): a granted row makes the
|
|
6
|
+
* F4 ask-gate SKIP the human ask for that (sessionId, canonicalToolName) — it is consulted ONLY after
|
|
7
|
+
* `APPROVAL_DENY` and `APPROVAL_NEVER_AUTO` (both always win), and never touches the session-policy layer
|
|
8
|
+
* (tighten-only stays intact). Keyed in CANONICAL tool-name space (the same rename-smuggling discipline as
|
|
9
|
+
* the require/deny sets). Lifecycle = session-bound: E21 session DELETE purges via deleteBySession.
|
|
10
|
+
*
|
|
11
|
+
* Four twins behind one interface (the resume-anchor pattern): TiDB/PG = durable cross-replica SQL rows
|
|
12
|
+
* (idempotent upsert on the (session_id, tool_name) PK); File = per-session JSONL append log (fsync — a
|
|
13
|
+
* lost grant re-asks, but a torn log must not FABRICATE one), hydrated on boot, torn-tail-safe; Memory =
|
|
14
|
+
* tests / ephemeral. Consumers treat store FAILURE as fail-closed (ask anyway) — enforced at the call site.
|
|
15
|
+
*/
|
|
1
16
|
import { join } from "node:path";
|
|
2
17
|
import { existsSync, readdirSync, rmSync } from "node:fs";
|
|
3
18
|
import { AppendLog, ensureDir, readJsonlRecords, sanitizePathComponent } from "@sema-agent/core";
|
|
19
|
+
// ─── TiDB / MySQL twin ───────────────────────────────────────────────────────────────────────────────────
|
|
4
20
|
export class TiDBApprovalExemptionStore {
|
|
5
21
|
pool;
|
|
6
22
|
constructor(pool) {
|
|
@@ -8,7 +24,8 @@ export class TiDBApprovalExemptionStore {
|
|
|
8
24
|
}
|
|
9
25
|
async grant(sessionId, toolName, grantedBy) {
|
|
10
26
|
await this.pool.query("INSERT INTO approval_exemption (session_id, tool_name, granted_by, created_at) VALUES (?,?,?,?) " +
|
|
11
|
-
"ON DUPLICATE KEY UPDATE granted_by = VALUES(granted_by)",
|
|
27
|
+
"ON DUPLICATE KEY UPDATE granted_by = VALUES(granted_by)", // created_at keeps the first grant
|
|
28
|
+
[sessionId, toolName, grantedBy, new Date()]);
|
|
12
29
|
}
|
|
13
30
|
async has(sessionId, toolName) {
|
|
14
31
|
const [rows] = await this.pool.query("SELECT 1 FROM approval_exemption WHERE session_id = ? AND tool_name = ?", [sessionId, toolName]);
|
|
@@ -31,6 +48,7 @@ export class TiDBApprovalExemptionStore {
|
|
|
31
48
|
return r.affectedRows;
|
|
32
49
|
}
|
|
33
50
|
}
|
|
51
|
+
// ─── PG twin (dialect twin of the TiDB store — same contract, $n placeholders + ON CONFLICT) ─────────────
|
|
34
52
|
export class PgApprovalExemptionStore {
|
|
35
53
|
pool;
|
|
36
54
|
constructor(pool) {
|
|
@@ -67,6 +85,7 @@ export class PgApprovalExemptionStore {
|
|
|
67
85
|
return res.rowCount ?? 0;
|
|
68
86
|
}
|
|
69
87
|
}
|
|
88
|
+
// ─── Memory twin (tests / ephemeral) ─────────────────────────────────────────────────────────────────────
|
|
70
89
|
export class MemoryApprovalExemptionStore {
|
|
71
90
|
bySession = new Map();
|
|
72
91
|
async grant(sessionId, toolName, grantedBy) {
|
|
@@ -110,6 +129,7 @@ export class FileApprovalExemptionStore {
|
|
|
110
129
|
pathFor(sessionId) {
|
|
111
130
|
return join(this.dir, `${sanitizePathComponent(sessionId)}.jsonl`);
|
|
112
131
|
}
|
|
132
|
+
/** Replay every session log (torn-tail-safe; last-wins with revoke tombstones). Index keyed by the SANITIZED id. */
|
|
113
133
|
hydrate() {
|
|
114
134
|
let names;
|
|
115
135
|
try {
|
|
@@ -191,9 +211,13 @@ export class FileApprovalExemptionStore {
|
|
|
191
211
|
log.close();
|
|
192
212
|
this.logs.delete(key);
|
|
193
213
|
}
|
|
214
|
+
// 🔴 unlink BEFORE dropping the index, and FAIL LOUD if the file survives: a
|
|
215
|
+
// swallowed rm would let hydrate() resurrect purged exemptions after a restart — an E21 right-to-delete
|
|
216
|
+
// violation with PRIVILEGE attached (auto-approve rights), unlike the inert anchor-store twin. Throwing
|
|
217
|
+
// here aborts the caller's session purge before it deletes the session metadata (fail-loud, retryable).
|
|
194
218
|
const path = this.pathFor(sessionId);
|
|
195
219
|
try {
|
|
196
|
-
rmSync(path, { force: true });
|
|
220
|
+
rmSync(path, { force: true }); // force: missing file is fine (idempotent delete)
|
|
197
221
|
}
|
|
198
222
|
catch (e) {
|
|
199
223
|
if (existsSync(path))
|
|
@@ -202,12 +226,14 @@ export class FileApprovalExemptionStore {
|
|
|
202
226
|
this.bySession.delete(key);
|
|
203
227
|
return removed;
|
|
204
228
|
}
|
|
229
|
+
/** Release every open append-log fd (LocalBackend.close → graceful-restart re-open). */
|
|
205
230
|
dispose() {
|
|
206
231
|
for (const log of this.logs.values()) {
|
|
207
232
|
try {
|
|
208
233
|
log.close();
|
|
209
234
|
}
|
|
210
235
|
catch {
|
|
236
|
+
/* best-effort */
|
|
211
237
|
}
|
|
212
238
|
}
|
|
213
239
|
this.logs.clear();
|