@sema-agent/server 1.323.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 +58 -2
- 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/project-memory.d.ts
CHANGED
|
@@ -7,13 +7,35 @@ interface ProjectMemoryCtx {
|
|
|
7
7
|
sessionId?: string;
|
|
8
8
|
phase?: "fresh" | "resume" | "post-compact" | "post-clear";
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Build a `loadProjectMemory` for the host lane. Returns null (skip) unless hands are enabled AND cwd is a local
|
|
12
|
+
* directory. Reads the instruction-file chain (AGENTS.md → CLAUDE.md → .claude/CLAUDE.md, S-1) + (non-subagent)
|
|
13
|
+
* `git log -5` / `git status`, redacts secrets, and caps the total. A subagent gets a trimmed instruction file and
|
|
14
|
+
* no git narrative (cost control, H7). When an instruction file is hit the return is a `ProjectMemoryLoad`
|
|
15
|
+
* declaring it in `instructionSources` (path + sha256 over the raw bounded-read window) so core's
|
|
16
|
+
* instructions-change lane can probe it mid-run.
|
|
17
|
+
*
|
|
18
|
+
* Session snapshot cache (S-2): keyed on ctx.sessionId — a session keeps ONE stable instruction snapshot
|
|
19
|
+
* (mid-run file edits surface via the probe as tail attachments, never a silently re-rendered prefix).
|
|
20
|
+
* `phase: "post-compact"` forces a re-read (core re-renders the prefix there anyway). No entry for
|
|
21
|
+
* sessionless one-shot runs. (post-clear never arrives from core — RB-9 — so it is not a cache key here.)
|
|
22
|
+
*/
|
|
10
23
|
export declare function makeLoadProjectMemory(opts: {
|
|
11
24
|
logger?: {
|
|
12
25
|
debug?: (msg: string, data: Record<string, unknown>) => void;
|
|
13
26
|
};
|
|
14
27
|
maxBytes?: number;
|
|
28
|
+
/** TEST-ONLY: shrink the snapshot-cache bound so the settle-time trim is observable without 256 sessions. */
|
|
15
29
|
cacheMax?: number;
|
|
16
30
|
}): (ctx: ProjectMemoryCtx) => Promise<string | null | ProjectMemoryLoad>;
|
|
31
|
+
/**
|
|
32
|
+
* ② The `RunnerDeps.probeInstructionSources` seam: re-fingerprint the declared instruction files mid-run so
|
|
33
|
+
* core's instructions-change lane can append a tail attachment when one changes. Same read posture as the
|
|
34
|
+
* loader (lstat symlink gate → bounded read of the first `INSTRUCTION_READ_CAP` bytes → sha256) — any drift
|
|
35
|
+
* here would fabricate phantom "changed" signals every turn. Per-source failure → `contentHash: null`
|
|
36
|
+
* (source gone/unreadable); any unexpected top-level failure → `null` (probe abstains; core also races this
|
|
37
|
+
* against a 2s ceiling and treats a throw as null, but we stay honest on our side of the seam).
|
|
38
|
+
*/
|
|
17
39
|
export declare function makeProbeInstructionSources(): NonNullable<import("@sema-agent/core").RunnerDeps["probeInstructionSources"]>;
|
|
18
40
|
export {};
|
|
19
41
|
//# sourceMappingURL=project-memory.d.ts.map
|
package/dist/project-memory.js
CHANGED
|
@@ -1,46 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/113 C4 — `RunnerDeps.loadProjectMemory` (core 1.182): the DEPLOYMENT half that makes sema "open like CC" —
|
|
3
|
+
* inject the project's CLAUDE.md + recent git narrative as a read-only, fenced virtual memory layer at the tail of the
|
|
4
|
+
* env block, so a fresh "你好" lands on "I'm the AI for the acme-widget project…" instead of a blank greeting.
|
|
5
|
+
*
|
|
6
|
+
* core's half (1.182/1.184): it calls this once per prepare, fences+sanitizes the return as UNTRUSTED data (CLAUDE.md
|
|
7
|
+
* is data, not an instruction), caps it at MAX_MEMORY_BYTES, and (1.184) auto-prepends a TRUSTED framing line. We just
|
|
8
|
+
* return the content.
|
|
9
|
+
*
|
|
10
|
+
* 🔴 HOST/FILE LANE ONLY. The ctx hands us only `cwd` (a string) — NO executionEnv instance and NO sessionId. So we can
|
|
11
|
+
* read with the worker's own `fs`/`execFile` ONLY when cwd is a LOCAL path (the host lane). On a remote sandbox lane
|
|
12
|
+
* (e2b/k8s/ssh/adb/local-docker) cwd lives in the container — the worker can't read it, and there's no env handle in
|
|
13
|
+
* the ctx to exec through — so main.ts only wires this on the host lane; here we defensively re-check (stat the dir).
|
|
14
|
+
*/
|
|
1
15
|
import { promises as fs, constants as fsConstants } from "node:fs";
|
|
2
16
|
import { execFile } from "node:child_process";
|
|
3
17
|
import { createHmac, randomBytes } from "node:crypto";
|
|
4
18
|
import { isAbsolute, join, sep } from "node:path";
|
|
5
19
|
import { scrubSecretEnv } from "@sema-agent/core";
|
|
6
20
|
import { redactSecrets } from "./trace/redact.js";
|
|
21
|
+
/** The instruction-file name chain (core 1.302 S-1): AGENTS.md wins, CLAUDE.md is the fallback, then the
|
|
22
|
+
* `.claude/` nested form. The FIRST hit is the single declared instruction source. */
|
|
7
23
|
const INSTRUCTION_FILE_CHAIN = ["AGENTS.md", "CLAUDE.md", ".claude/CLAUDE.md"];
|
|
24
|
+
/** One byte budget shared by the loader AND the probe — the fingerprint is sha256 over the first
|
|
25
|
+
* `INSTRUCTION_READ_CAP` raw bytes, so both sides MUST read the same bounded window or every probe
|
|
26
|
+
* would report a phantom change. (Consequence: an edit past the cap is invisible to the probe —
|
|
27
|
+
* honest limit of the bounded-read design, same reason the injected content is capped.) */
|
|
8
28
|
const INSTRUCTION_READ_CAP = 24 * 1024;
|
|
29
|
+
/** Cap a string to a byte budget on a UTF-8 character boundary (never split a multi-byte char). */
|
|
9
30
|
function capUtf8(s, maxBytes) {
|
|
10
31
|
const buf = Buffer.from(s, "utf8");
|
|
11
32
|
if (buf.length <= maxBytes)
|
|
12
33
|
return s;
|
|
13
34
|
let end = maxBytes;
|
|
35
|
+
// back off to a UTF-8 lead byte (0xxxxxxx or 11xxxxxx) so we don't slice mid-character
|
|
14
36
|
while (end > 0 && (buf[end] & 0xc0) === 0x80)
|
|
15
37
|
end -= 1;
|
|
16
38
|
return buf.subarray(0, end).toString("utf8");
|
|
17
39
|
}
|
|
40
|
+
/** Bounded raw read of an ABSOLUTE path (lstat symlink gate → first `maxBytes` bytes). The shared primitive
|
|
41
|
+
* under both the loader and `makeProbeInstructionSources` — one read posture, one fingerprint. */
|
|
18
42
|
async function readRawCapped(target, maxBytes, truncatedFlag = { v: false }) {
|
|
19
43
|
let fh;
|
|
20
44
|
try {
|
|
45
|
+
// Symlink containment: a `CLAUDE.md` symlink must NOT read an arbitrary file outside the repo (double-review #3).
|
|
46
|
+
// 🔴 win32 真机(S6, 2026-07-04): `fsConstants.O_NOFOLLOW` is UNDEFINED on Windows Node, so `O_RDONLY | undefined`
|
|
47
|
+
// silently collapses to `O_RDONLY` (0) — the flag is a no-op and the symlink IS followed (verified: read out the
|
|
48
|
+
// outside file). O_NOFOLLOW only exists/atomically-enforces on POSIX. So gate portably with an explicit lstat
|
|
49
|
+
// symlink-reject: authoritative on win32 (where the open-flag can't enforce it), belt-and-suspenders on POSIX.
|
|
21
50
|
const lst = await fs.lstat(target);
|
|
22
51
|
if (lst.isSymbolicLink())
|
|
23
|
-
return null;
|
|
52
|
+
return null; // a symlinked CLAUDE.md → refuse (no arbitrary-file read), same as O_NOFOLLOW → ELOOP
|
|
24
53
|
if (lst.size > maxBytes)
|
|
25
|
-
truncatedFlag.v = true;
|
|
54
|
+
truncatedFlag.v = true; // S23: cap fired — surfaced as claudeTruncated on the injection event
|
|
55
|
+
// Keep O_NOFOLLOW in the flags too: on POSIX it closes the tiny lstat→open TOCTOU window atomically; on win32 it's
|
|
56
|
+
// a harmless 0. BOUNDED read of the first maxBytes bytes — never buffer the whole file, so a 50MB/hostile CLAUDE.md
|
|
57
|
+
// can't amplify memory (double-review #2: the old fs.readFile loaded the WHOLE file before capping).
|
|
26
58
|
fh = await fs.open(target, fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0));
|
|
27
59
|
const buf = Buffer.allocUnsafe(maxBytes);
|
|
28
60
|
const { bytesRead } = await fh.read(buf, 0, maxBytes, 0);
|
|
29
61
|
return buf.subarray(0, bytesRead);
|
|
30
62
|
}
|
|
31
63
|
catch {
|
|
32
|
-
return null;
|
|
64
|
+
return null; // ENOENT / EISDIR / ELOOP (a symlink, rejected by O_NOFOLLOW) / EACCES — absent or unreadable → no content
|
|
33
65
|
}
|
|
34
66
|
finally {
|
|
35
67
|
await fh?.close();
|
|
36
68
|
}
|
|
37
69
|
}
|
|
70
|
+
/** Keyed fingerprint over the RAW bounded-read window (pre-capUtf8 bytes — the ①"cap 前原始字节" contract).
|
|
71
|
+
* KEYED, not a plain digest (self-review, information-surface lens): core puts the short form of this
|
|
72
|
+
* fingerprint into the MODEL-VISIBLE instructions-change notice and the steering trace — a plain sha256
|
|
73
|
+
* of the raw bytes would let anyone holding a known template dictionary-compare low-entropy controlled
|
|
74
|
+
* fields against the digest. A per-process random key makes the digest correspond to nothing outside
|
|
75
|
+
* this process. Loader and probe share THIS one function (any split would fabricate phantom "changed"
|
|
76
|
+
* signals); sources are re-declared at every prepare in the declaring process, so a restart (new key)
|
|
77
|
+
* never gets compared against old fingerprints. */
|
|
38
78
|
const INSTRUCTION_HASH_KEY = randomBytes(16);
|
|
39
79
|
function instructionHash(raw) {
|
|
40
80
|
return `hmac-sha256:${createHmac("sha256", INSTRUCTION_HASH_KEY).update(raw).digest("hex")}`;
|
|
41
81
|
}
|
|
82
|
+
/** The "declared absent, watched for appearance" fingerprint for higher-priority chain members —
|
|
83
|
+
* core 1.310 ([1006]①) widened `instructionSources[].contentHash` to `string | null`, so this is a
|
|
84
|
+
* plain typed null (an appearing file renders as `hash absent → <hash>` in the change notice). */
|
|
42
85
|
const ABSENT_HASH = null;
|
|
86
|
+
/** Recover (root, rel) for a path the LOADER declared — every declared path is `root + one chain member`,
|
|
87
|
+
* so the chain suffix identifies the split unambiguously. The probe needs this to re-run the loader's
|
|
88
|
+
* parent-directory symlink gate each round (self-review: the probe checked only the final component, so
|
|
89
|
+
* swapping `.claude` for a symlink out of the repo MID-RUN made the probe fingerprint an outside file). */
|
|
43
90
|
function chainCoordinates(absPath) {
|
|
91
|
+
// LONGEST suffix wins: `…/.claude/CLAUDE.md` also ends with the bare `/CLAUDE.md` — matching in chain
|
|
92
|
+
// order would split off `.claude` into the root and skip the parent gate entirely (caught by the test).
|
|
44
93
|
let best = null;
|
|
45
94
|
for (const rel of INSTRUCTION_FILE_CHAIN) {
|
|
46
95
|
const suffix = sep + rel.split("/").join(sep);
|
|
@@ -50,6 +99,11 @@ function chainCoordinates(absPath) {
|
|
|
50
99
|
}
|
|
51
100
|
return best && { root: best.root, rel: best.rel };
|
|
52
101
|
}
|
|
102
|
+
/** Reject a symlink on ANY intermediate directory of `rel` under root (adversarial review F2): the final
|
|
103
|
+
* component's lstat/O_NOFOLLOW can't see a `.claude` DIRECTORY that is itself a symlink out of the repo
|
|
104
|
+
* (e.g. → ~/.claude) — the target file there lstat's as a plain file and would be read and injected.
|
|
105
|
+
* Same TOCTOU honesty as the final-component gate: the lstat→open window on a swapped intermediate dir
|
|
106
|
+
* is accepted (a local attacker with user rights can read the target directly anyway). */
|
|
53
107
|
async function hasSymlinkedParent(root, rel) {
|
|
54
108
|
const parts = rel.split("/").slice(0, -1);
|
|
55
109
|
let cur = root;
|
|
@@ -61,30 +115,60 @@ async function hasSymlinkedParent(root, rel) {
|
|
|
61
115
|
}
|
|
62
116
|
return false;
|
|
63
117
|
}
|
|
118
|
+
/** Run a fixed git subcommand under root with execFile (argv array → NO shell → no injection), timeout + maxBuffer.
|
|
119
|
+
* 🔴 The repo's own `.git/config` can otherwise STEER these read-only calls into code execution — double-review proved
|
|
120
|
+
* `core.fsmonitor=<prog>` runs `<prog>` on `git status` (auto-fires on every prepare in a hostile working dir). We
|
|
121
|
+
* neutralize the exec-config inlets: `-c core.fsmonitor=false -c core.hooksPath=/dev/null` override the repo's values,
|
|
122
|
+
* and GIT_CONFIG_GLOBAL/SYSTEM=/dev/null drop the global/system config so a planted one can't inject either. */
|
|
64
123
|
function git(root, args, maxBytes) {
|
|
65
124
|
const safeArgs = ["-c", "core.fsmonitor=false", "-c", "core.hooksPath=/dev/null", ...args];
|
|
66
125
|
return new Promise((res) => {
|
|
67
|
-
execFile("git", safeArgs,
|
|
126
|
+
execFile("git", safeArgs,
|
|
127
|
+
// scrubSecretEnv: a git hook / credential helper must not see the orchestrator's *_KEY/*_TOKEN/*_SECRET env.
|
|
128
|
+
// GIT_CONFIG_GLOBAL/SYSTEM=/dev/null: ignore ~/.gitconfig + /etc/gitconfig so a planted exec-config can't steer us.
|
|
129
|
+
{ cwd: root, timeout: 5000, maxBuffer: maxBytes, env: { ...scrubSecretEnv(process.env), GIT_CONFIG_GLOBAL: "/dev/null", GIT_CONFIG_SYSTEM: "/dev/null" } }, (err, stdout, stderr) => {
|
|
68
130
|
if (!err)
|
|
69
131
|
return res({ out: stdout.trim() });
|
|
132
|
+
// S23: the git narrative used to vanish with zero fingerprint — classify why (→ gitDropReason).
|
|
70
133
|
const e = err;
|
|
71
134
|
const fail = e.killed ? "timeout" : e.code === "ENOENT" ? "git-missing" : /not a git repository/i.test(String(stderr)) ? "non-repo" : /maxBuffer/i.test(String(e.message)) ? "maxbuffer" : "error";
|
|
72
135
|
res({ out: "", fail });
|
|
73
136
|
});
|
|
74
137
|
});
|
|
75
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Build a `loadProjectMemory` for the host lane. Returns null (skip) unless hands are enabled AND cwd is a local
|
|
141
|
+
* directory. Reads the instruction-file chain (AGENTS.md → CLAUDE.md → .claude/CLAUDE.md, S-1) + (non-subagent)
|
|
142
|
+
* `git log -5` / `git status`, redacts secrets, and caps the total. A subagent gets a trimmed instruction file and
|
|
143
|
+
* no git narrative (cost control, H7). When an instruction file is hit the return is a `ProjectMemoryLoad`
|
|
144
|
+
* declaring it in `instructionSources` (path + sha256 over the raw bounded-read window) so core's
|
|
145
|
+
* instructions-change lane can probe it mid-run.
|
|
146
|
+
*
|
|
147
|
+
* Session snapshot cache (S-2): keyed on ctx.sessionId — a session keeps ONE stable instruction snapshot
|
|
148
|
+
* (mid-run file edits surface via the probe as tail attachments, never a silently re-rendered prefix).
|
|
149
|
+
* `phase: "post-compact"` forces a re-read (core re-renders the prefix there anyway). No entry for
|
|
150
|
+
* sessionless one-shot runs. (post-clear never arrives from core — RB-9 — so it is not a cache key here.)
|
|
151
|
+
*/
|
|
76
152
|
export function makeLoadProjectMemory(opts) {
|
|
77
|
-
const totalCap = opts.maxBytes ?? 32 * 1024;
|
|
153
|
+
const totalCap = opts.maxBytes ?? 32 * 1024; // service self-cap, tighter than core's 100KiB MAX_MEMORY_BYTES backstop
|
|
78
154
|
const claudeCap = INSTRUCTION_READ_CAP;
|
|
79
155
|
const subagentClaudeCap = 4 * 1024;
|
|
80
156
|
const gitCap = 8 * 1024;
|
|
81
157
|
const cache = new Map();
|
|
82
158
|
const CACHE_MAX = opts.cacheMax ?? 256;
|
|
83
159
|
return async (ctx) => {
|
|
160
|
+
// All gates that decide WHETHER anything loads run BEFORE the cache (F3): a hands-less or bad-cwd call
|
|
161
|
+
// must answer null itself, never serve (or seed) a session slot it wasn't allowed to read.
|
|
84
162
|
if (!ctx.handsEnabled)
|
|
85
|
-
return null;
|
|
163
|
+
return null; // hands-less chat: no real project (H4)
|
|
86
164
|
if (!isAbsolute(ctx.cwd))
|
|
87
165
|
return null;
|
|
166
|
+
// Canonicalize through the FILESYSTEM, not lexically (self-review, information-surface lens): a
|
|
167
|
+
// lexical resolve() keeps symlinks and case aliases distinct — a symlinked cwd re-pointed at another
|
|
168
|
+
// project would keep hitting the OLD slot and serve project A's instruction snapshot inside project B,
|
|
169
|
+
// and a case alias would silently split one project across two slots. realpath is both the cache key
|
|
170
|
+
// AND the read root, so key and content can never disagree. Unresolvable cwd (gone/unreadable) → null,
|
|
171
|
+
// the same answer doLoad's stat gate would give.
|
|
88
172
|
let root;
|
|
89
173
|
try {
|
|
90
174
|
root = await fs.realpath(ctx.cwd);
|
|
@@ -92,17 +176,26 @@ export function makeLoadProjectMemory(opts) {
|
|
|
92
176
|
catch {
|
|
93
177
|
return null;
|
|
94
178
|
}
|
|
179
|
+
// Subagents share the parent's project but get a differently-capped view — never let the two shapes
|
|
180
|
+
// poison one cache slot; the subagent leg just stays uncached (cheap, trimmed read).
|
|
95
181
|
const cacheKey = ctx.sessionId && !ctx.isSubagent ? `${ctx.sessionId}\u0000${root}` : undefined;
|
|
96
182
|
if (cacheKey) {
|
|
97
183
|
const hit = cache.get(cacheKey);
|
|
98
184
|
if (hit && ctx.phase !== "post-compact")
|
|
99
185
|
return hit.load;
|
|
186
|
+
// Post-compact single-flight (codex lens-1 remainder): two post-compact calls on one slot must share
|
|
187
|
+
// ONE fresh read — each starting its own would leave the surviving snapshot dependent on launch
|
|
188
|
+
// order. An in-flight entry that was ITSELF started post-compact is that generation's read (the
|
|
189
|
+
// settle window is milliseconds; a next compaction landing inside it joins the same read — accepted).
|
|
100
190
|
if (hit && !hit.settled && hit.phase === "post-compact")
|
|
101
191
|
return hit.load;
|
|
102
192
|
}
|
|
103
193
|
const load = doLoad(ctx, root);
|
|
104
194
|
if (cacheKey) {
|
|
105
195
|
if (cache.size >= CACHE_MAX && !cache.has(cacheKey)) {
|
|
196
|
+
// Evict the oldest SETTLED entry only (codex lens-1 remainder): deleting an in-flight promise
|
|
197
|
+
// orphans its read (the key's next call starts a second one). No settled entry → allow a
|
|
198
|
+
// temporary over-cap; loads settle in milliseconds, so the map stays bounded in practice.
|
|
106
199
|
for (const [k, e] of cache) {
|
|
107
200
|
if (e.settled) {
|
|
108
201
|
cache.delete(k);
|
|
@@ -112,6 +205,10 @@ export function makeLoadProjectMemory(opts) {
|
|
|
112
205
|
}
|
|
113
206
|
const entry = { load, settled: false, phase: ctx.phase };
|
|
114
207
|
cache.set(cacheKey, entry);
|
|
208
|
+
// Release-review finding: a burst of >CACHE_MAX concurrent DISTINCT loads sails past the insert-time
|
|
209
|
+
// eviction (nothing settled to evict yet) and, without this, the map would stay at the burst's
|
|
210
|
+
// high-water mark forever (each later insert evicts exactly one settled entry, net zero). Trim back
|
|
211
|
+
// down to the cap as loads settle — oldest settled first, in-flight entries always survive.
|
|
115
212
|
const trimSettled = () => {
|
|
116
213
|
if (cache.size <= CACHE_MAX)
|
|
117
214
|
return;
|
|
@@ -128,6 +225,9 @@ export function makeLoadProjectMemory(opts) {
|
|
|
128
225
|
trimSettled();
|
|
129
226
|
}, () => {
|
|
130
227
|
entry.settled = true;
|
|
228
|
+
// A rejected load must not poison the slot (doLoad catches everything today; belt for future
|
|
229
|
+
// edits). Guard the delete on identity (codex lens-1): an OLD generation's failure must not
|
|
230
|
+
// evict the NEWER entry that a post-compact refresh has already installed in the same slot.
|
|
131
231
|
if (cache.get(cacheKey) === entry)
|
|
132
232
|
cache.delete(cacheKey);
|
|
133
233
|
trimSettled();
|
|
@@ -138,7 +238,12 @@ export function makeLoadProjectMemory(opts) {
|
|
|
138
238
|
async function doLoad(ctx, root) {
|
|
139
239
|
const st = await fs.stat(root).catch(() => null);
|
|
140
240
|
if (!st?.isDirectory())
|
|
141
|
-
return null;
|
|
241
|
+
return null; // remote-lane cwd not present locally, or a bad path → skip
|
|
242
|
+
// S-1 file-name chain: first hit wins and is the ONE declared instruction source.
|
|
243
|
+
// Consistent-snapshot selection (codex lens-1 remainder): the chain walk is not atomic — a
|
|
244
|
+
// higher-priority file created between "checked absent" and "picked the fallback" would silently
|
|
245
|
+
// lose to the fallback until a post-compact reload. After a non-top pick, re-verify the members
|
|
246
|
+
// above it; an appearance redoes the walk (bounded — after the retries the last pick stands).
|
|
142
247
|
const claudeTrunc = { v: false };
|
|
143
248
|
let claudeRaw = null;
|
|
144
249
|
let hitFile;
|
|
@@ -153,7 +258,7 @@ export function makeLoadProjectMemory(opts) {
|
|
|
153
258
|
for (let i = 0; i < INSTRUCTION_FILE_CHAIN.length; i++) {
|
|
154
259
|
const rel = INSTRUCTION_FILE_CHAIN[i];
|
|
155
260
|
if (rel.includes("/") && (await hasSymlinkedParent(root, rel)))
|
|
156
|
-
continue;
|
|
261
|
+
continue; // F2: a symlinked .claude dir escapes the repo
|
|
157
262
|
const raw = await readRawCapped(join(root, rel), claudeCap, claudeTrunc);
|
|
158
263
|
if (raw !== null) {
|
|
159
264
|
claudeRaw = capUtf8(raw.toString("utf8"), claudeCap);
|
|
@@ -164,10 +269,11 @@ export function makeLoadProjectMemory(opts) {
|
|
|
164
269
|
}
|
|
165
270
|
}
|
|
166
271
|
if (hitIndex <= 0)
|
|
167
|
-
break;
|
|
272
|
+
break; // top pick or nothing found: no higher-priority member to re-verify
|
|
168
273
|
let appeared = false;
|
|
169
274
|
for (const rel of INSTRUCTION_FILE_CHAIN.slice(0, hitIndex)) {
|
|
170
275
|
const higher = await fs.lstat(join(root, rel)).catch(() => null);
|
|
276
|
+
// A symlink would be REFUSED by the read gate — its appearance is not a better pick.
|
|
171
277
|
if (higher && !higher.isSymbolicLink()) {
|
|
172
278
|
appeared = true;
|
|
173
279
|
break;
|
|
@@ -177,9 +283,9 @@ export function makeLoadProjectMemory(opts) {
|
|
|
177
283
|
break;
|
|
178
284
|
}
|
|
179
285
|
const claude = ctx.isSubagent && claudeRaw ? capUtf8(claudeRaw, subagentClaudeCap) : claudeRaw;
|
|
180
|
-
const claudeTruncated = claudeTrunc.v || Boolean(ctx.isSubagent && claudeRaw && Buffer.byteLength(claudeRaw, "utf8") > subagentClaudeCap);
|
|
286
|
+
const claudeTruncated = claudeTrunc.v || Boolean(ctx.isSubagent && claudeRaw && Buffer.byteLength(claudeRaw, "utf8") > subagentClaudeCap); // S23
|
|
181
287
|
let gitNarrative = "";
|
|
182
|
-
let gitOk = true;
|
|
288
|
+
let gitOk = true; // S23: subagent (git not attempted) stays ok=absent-by-design
|
|
183
289
|
let gitDropReason;
|
|
184
290
|
if (!ctx.isSubagent) {
|
|
185
291
|
const [log, status] = await Promise.all([
|
|
@@ -192,22 +298,33 @@ export function makeLoadProjectMemory(opts) {
|
|
|
192
298
|
if (log.out)
|
|
193
299
|
parts.push(`## Recent commits\n${log.out}`);
|
|
194
300
|
if (status.out)
|
|
195
|
-
parts.push(`## Working tree\n${status.out.split("\n").slice(0, 40).join("\n")}`);
|
|
301
|
+
parts.push(`## Working tree\n${status.out.split("\n").slice(0, 40).join("\n")}`); // bound the dirty list
|
|
196
302
|
gitNarrative = parts.join("\n\n");
|
|
197
303
|
}
|
|
198
304
|
const sections = [];
|
|
199
305
|
if (claude && hitFile)
|
|
200
|
-
sections.push(`# ${hitFile}\n${claude}`);
|
|
306
|
+
sections.push(`# ${hitFile}\n${claude}`); // heading = the REAL file name (S-1)
|
|
201
307
|
if (gitNarrative)
|
|
202
308
|
sections.push(gitNarrative);
|
|
203
309
|
if (sections.length === 0)
|
|
204
310
|
return null;
|
|
311
|
+
// redact secrets BEFORE capping (a key must not survive into the injected context, where a tool could exfil it).
|
|
205
312
|
const redacted = redactSecrets(sections.join("\n\n"));
|
|
206
313
|
const capped = capUtf8(redacted, totalCap);
|
|
314
|
+
// S23: gitOk/gitDropReason/claudeTruncated — a silently-emptied narrative now has a fingerprint here.
|
|
315
|
+
// cacheSize: the snapshot cache's population at THIS load (bound observability — the settle-time trim
|
|
316
|
+
// keeps it ≤ the cap once in-flight bursts settle; also what the deterministic trim test asserts).
|
|
207
317
|
opts.logger?.debug?.("project_memory_loaded", { cwd: root, bytes: Buffer.byteLength(capped, "utf8"), isSubagent: ctx.isSubagent, gitOk, ...(gitDropReason ? { gitDropReason } : {}), claudeTruncated, ...(hitFile ? { instructionFile: hitFile } : {}), ...(ctx.phase ? { phase: ctx.phase } : {}), cacheSize: cache.size });
|
|
208
318
|
if (!capped)
|
|
209
319
|
return null;
|
|
320
|
+
// Declare the instruction source (①): absolute path + fingerprint. The hash is over the PRE-redaction,
|
|
321
|
+
// pre-cap raw window — the probe re-reads the file itself, so the fingerprint must be file-derived, not
|
|
322
|
+
// derived from the redacted/assembled injection text.
|
|
210
323
|
if (hitFile && hitHash) {
|
|
324
|
+
// Watch the chain members ABOVE the pick too (codex lens-1 remainder): core's change lane only
|
|
325
|
+
// probes DECLARED paths, so a higher-priority file appearing mid-run would otherwise never produce
|
|
326
|
+
// a signal until a post-compact reload. Absent members are pre-declared with the runtime's
|
|
327
|
+
// "absent" hash (ABSENT_HASH note) — appearance renders as `hash absent → <hash>` in the notice.
|
|
211
328
|
return {
|
|
212
329
|
content: capped,
|
|
213
330
|
instructionSources: [
|
|
@@ -219,15 +336,27 @@ export function makeLoadProjectMemory(opts) {
|
|
|
219
336
|
return capped;
|
|
220
337
|
}
|
|
221
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* ② The `RunnerDeps.probeInstructionSources` seam: re-fingerprint the declared instruction files mid-run so
|
|
341
|
+
* core's instructions-change lane can append a tail attachment when one changes. Same read posture as the
|
|
342
|
+
* loader (lstat symlink gate → bounded read of the first `INSTRUCTION_READ_CAP` bytes → sha256) — any drift
|
|
343
|
+
* here would fabricate phantom "changed" signals every turn. Per-source failure → `contentHash: null`
|
|
344
|
+
* (source gone/unreadable); any unexpected top-level failure → `null` (probe abstains; core also races this
|
|
345
|
+
* against a 2s ceiling and treats a throw as null, but we stay honest on our side of the seam).
|
|
346
|
+
*/
|
|
222
347
|
export function makeProbeInstructionSources() {
|
|
223
348
|
return async (sources) => {
|
|
224
349
|
try {
|
|
225
350
|
return await Promise.all(sources.map(async ({ path }) => {
|
|
226
351
|
if (!isAbsolute(path))
|
|
227
|
-
return { path, contentHash: null };
|
|
352
|
+
return { path, contentHash: null }; // we only ever declare absolute paths
|
|
353
|
+
// Re-run the loader's parent-directory symlink gate EVERY round (self-review: the probe checked
|
|
354
|
+
// only the final component, so swapping `.claude` for a symlink out of the repo mid-run made the
|
|
355
|
+
// probe fingerprint an outside file — and its short form reaches the model-visible notice).
|
|
356
|
+
// Declared paths are always root+chain-member, so the coordinates are recoverable from the path.
|
|
228
357
|
const coords = chainCoordinates(path);
|
|
229
358
|
if (coords && coords.rel.includes("/") && (await hasSymlinkedParent(coords.root, coords.rel))) {
|
|
230
|
-
return { path, contentHash: null };
|
|
359
|
+
return { path, contentHash: null }; // swapped-in symlinked parent → refuse, same as the loader
|
|
231
360
|
}
|
|
232
361
|
const raw = await readRawCapped(path, INSTRUCTION_READ_CAP);
|
|
233
362
|
return { path, contentHash: raw === null ? null : instructionHash(raw) };
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { type PromptTextDeclaration, type PublishedPromptArtifactEnvelope } from "@sema-agent/core";
|
|
2
|
+
/** [1057]⓪ 下发形(remote effective 的 additive key,JSON verbatim 面——不经 registry-core parse,所以
|
|
3
|
+
* cli 补位前 center 发的 `contentHash` 也原样到达)。 */
|
|
2
4
|
export interface EffectiveCenterPrompts {
|
|
5
|
+
/** `center:<contentDigest 前 12>` — 纯内容寻址(同内容重发布=同 packId,epoch 不误重 pin)。 */
|
|
3
6
|
packId: string;
|
|
7
|
+
/** canonical JSON 全量 sha256(非盐化,operator 对账位 [1050]②)。 */
|
|
4
8
|
contentDigest: string;
|
|
9
|
+
/** covering 已在 center 走完的基线终形(层信息不下发,worker 零解析义务)。 */
|
|
5
10
|
sections: PromptTextDeclaration[];
|
|
11
|
+
/** per-scenario 完整重算终形(整包替换基线,非增量);无键=用基线。 */
|
|
6
12
|
scenarioOverrides?: Record<string, PromptTextDeclaration[]>;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* 结构判形(防炸底线,非语义复检)。`ok:false` 时调用方拒绝采用该候选的 prompts 面并 warn——绝不让
|
|
16
|
+
* 一个坏 pack 把每个任务的 prepare 炸掉。校验与 core assemble 的 THROW 条件同形(id 规范/长度/core/
|
|
17
|
+
* 保留、slot 闭集)+ 下发信封两键形;`contentHash` 只查形(值的校验归 core 1.315,错值 core 丢弃+warn)。
|
|
18
|
+
*/
|
|
8
19
|
export declare function validateCenterPrompts(raw: unknown): {
|
|
9
20
|
ok: true;
|
|
10
21
|
value: EffectiveCenterPrompts;
|
|
@@ -12,13 +23,30 @@ export declare function validateCenterPrompts(raw: unknown): {
|
|
|
12
23
|
ok: false;
|
|
13
24
|
error: string;
|
|
14
25
|
};
|
|
26
|
+
/** core 引擎版本(verifyPromptArtifact 的 compatibleCore range 输入)——经 exports map 解析包根读
|
|
27
|
+
* package.json(`require('@sema-agent/core/package.json')` 被 exports 封死,ERR_PACKAGE_PATH_NOT_EXPORTED
|
|
28
|
+
* 第一手教训)。解析失败回 "0.0.0" = range-gated artifact 被诚实拒(fail-closed 响,绝不静默采用)。 */
|
|
15
29
|
export declare const CORE_ENGINE_VERSION: string;
|
|
30
|
+
/** validatePromptsDomain 的归一产物:两轴的已判形面 + 变更检测身份(adopt 去重键,跨轴稳定)。 */
|
|
16
31
|
export interface PromptsDomainFaces {
|
|
32
|
+
/** A 形(declaration 轴)——centerPromptProvider 继续消费(现行链路零改动)。 */
|
|
17
33
|
declarations?: EffectiveCenterPrompts;
|
|
34
|
+
/** B 形(catalog 轴)——core S1 verify 已过(digest 复算/上限/range 全管线);server 不解释内容,
|
|
35
|
+
* 原样交 core artifact 仓(e/b 班车接线位)。 */
|
|
18
36
|
catalog?: PublishedPromptArtifactEnvelope;
|
|
37
|
+
/** 采用去重键:两轴 digest 拼接(轴缺席记 "-")。 */
|
|
19
38
|
identity: string;
|
|
39
|
+
/** 观测面([985]a §3:`center_prompts_adopted` 增 axes,看两轴共存窗)。 */
|
|
20
40
|
axes: Array<"declarations" | "catalog">;
|
|
21
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* prompts 域候选门 v2(validateCenterPrompts 的双轴升级;整拒语义不变=任一在场轴坏形 ⇒ 整个 prompts
|
|
44
|
+
* 面拒绝采用,LKG/内置继续服务)。两形都认:
|
|
45
|
+
* - legacy 平铺(无 schemaVersion 键)= declaration 轴单轴(存量 center 停发平铺前的兼容窗);
|
|
46
|
+
* - `{schemaVersion:1, declarations?, catalog?}`(registry-core `EffectivePromptsWire`)= 至少一轴。
|
|
47
|
+
* catalog 轴的语义权威=core `verifyPromptArtifact`(形/digest 逐位复算/ARTIFACT_LIMITS/compatibleCore
|
|
48
|
+
* range 全在 core 一处——[1242]③ a 解,上限单真源永不漂)。
|
|
49
|
+
*/
|
|
22
50
|
export declare function validatePromptsDomain(raw: unknown): {
|
|
23
51
|
ok: true;
|
|
24
52
|
value: PromptsDomainFaces;
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prompts 域候选门(判形)——从 capabilities/center-prompts.ts **下沉**的中立叶子(design/158 S6,
|
|
3
|
+
* lens2 §G:`config-lkg.ts → capabilities/center-prompts.ts` 是全仓唯一一条显式分层反向边,config 层
|
|
4
|
+
* 值 import capabilities 层)。本模块只依赖 node 内置 + `@sema-agent/core`,不依赖 capabilities/
|
|
5
|
+
* config 任何东西,config-lkg(LKG 读侧复判)与 capabilities(候选门)同引即无反向边。
|
|
6
|
+
* center-prompts.ts 原位置 re-export 保兼容,语义/文案零改动——逐字搬运。
|
|
7
|
+
*
|
|
8
|
+
* ─── 以下为原 center-prompts.ts 的判形半场,注释原样保留 ───
|
|
9
|
+
*
|
|
10
|
+
* 本模块仅有的一层「形校验」不是语义复检,是**防炸底线**:core 对坏形声明的守卫是 THROW(assemble 期),
|
|
11
|
+
* 一个坏 pack 会让每个任务 prepare 炸掉——server 在采用前做结构判形,坏形=拒绝采用该候选的 prompts 面
|
|
12
|
+
* (warn 点名,沿用上一个好的/内置),任务面永不因配置坏形而全灭(config 候选门同精神,只作用于本域)。
|
|
13
|
+
*/
|
|
1
14
|
import { createHash } from "node:crypto";
|
|
2
15
|
import { createRequire } from "node:module";
|
|
3
16
|
import { readFileSync } from "node:fs";
|
|
4
17
|
import { dirname, join } from "node:path";
|
|
5
18
|
import { verifyPromptArtifact } from "@sema-agent/core";
|
|
6
|
-
const ID_RE = /^[a-z0-9][a-z0-9/._-]*$/;
|
|
19
|
+
const ID_RE = /^[a-z0-9][a-z0-9/._-]*$/; // core assemble 同形(≤128、非 core/ 前缀在下面单查)
|
|
7
20
|
const SLOTS = new Set(["identity", "scenario", "behavior"]);
|
|
8
21
|
const HASH_RE = /^sha256:[0-9a-f]{64}$/;
|
|
9
22
|
function declarationIssue(d, where) {
|
|
@@ -18,6 +31,10 @@ function declarationIssue(d, where) {
|
|
|
18
31
|
return `${where}: bad slot`;
|
|
19
32
|
if (typeof o.text !== "string" || o.text.length === 0)
|
|
20
33
|
return `${where}: text must be a non-empty string`;
|
|
34
|
+
// 发版复审(1.224 批)F1:contentHash **必备且重算比对**——core 的 epoch 声明轴用 (id,slot,chars,
|
|
35
|
+
// contentHash?),hash 缺席/被 core 丢弃(错值)后**同长度文本编辑不改 artifactDigest=不重 pin**,
|
|
36
|
+
// 恰是撤 restart 臂所依赖的审计不变量被击穿。center 链路恒逐 section 铸([1065]),正常路径零影响;
|
|
37
|
+
// 这里拒的是坏发布/被改载荷(整拒候选,LKG/内置继续服务)。
|
|
21
38
|
if (typeof o.contentHash !== "string" || !HASH_RE.test(o.contentHash))
|
|
22
39
|
return `${where}: contentHash is required (sha256:<64hex> — the epoch declaration axis needs it for byte-level change detection)`;
|
|
23
40
|
const expected = `sha256:${createHash("sha256").update(o.text).digest("hex")}`;
|
|
@@ -25,6 +42,11 @@ function declarationIssue(d, where) {
|
|
|
25
42
|
return `${where}: contentHash does not match sha256(text) — stale or tampered declaration`;
|
|
26
43
|
return undefined;
|
|
27
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* 结构判形(防炸底线,非语义复检)。`ok:false` 时调用方拒绝采用该候选的 prompts 面并 warn——绝不让
|
|
47
|
+
* 一个坏 pack 把每个任务的 prepare 炸掉。校验与 core assemble 的 THROW 条件同形(id 规范/长度/core/
|
|
48
|
+
* 保留、slot 闭集)+ 下发信封两键形;`contentHash` 只查形(值的校验归 core 1.315,错值 core 丢弃+warn)。
|
|
49
|
+
*/
|
|
28
50
|
export function validateCenterPrompts(raw) {
|
|
29
51
|
if (raw === null || typeof raw !== "object")
|
|
30
52
|
return { ok: false, error: "prompts is not an object" };
|
|
@@ -33,6 +55,11 @@ export function validateCenterPrompts(raw) {
|
|
|
33
55
|
return { ok: false, error: "bad packId form (center:<digest12>)" };
|
|
34
56
|
if (typeof p.contentDigest !== "string" || !HASH_RE.test(p.contentDigest))
|
|
35
57
|
return { ok: false, error: "bad contentDigest form" };
|
|
58
|
+
// 发版复审 F2/F4 两条硬化:
|
|
59
|
+
// - 数组内 id 必须唯一(core composer 对 duplicate section id 是 THROW——独立判形查不出对撞,必须
|
|
60
|
+
// 整数组查重;基线与各 override 互不查——override 整包替换,不同数组不共存于一次装配);
|
|
61
|
+
// - 空数组=坏形拒绝(F4:wire 契约是「整包替换终形」,空数组语义未定义——「显式清空场景」不是 v1
|
|
62
|
+
// 用例,静默把空重解释为「回落内置」会跑出与 center 发布物不同的提示词;语义决定权推回 center)。
|
|
36
63
|
const arrayIssue = (decls, where) => {
|
|
37
64
|
if (!Array.isArray(decls))
|
|
38
65
|
return `${where} is not an array`;
|
|
@@ -65,6 +92,10 @@ export function validateCenterPrompts(raw) {
|
|
|
65
92
|
}
|
|
66
93
|
return { ok: true, value: raw };
|
|
67
94
|
}
|
|
95
|
+
// ═══ 双轴门(a 实现班车,[985]a/[1242]/[1248] 过轮定稿;registry-core 0.10.20 同班车)═══
|
|
96
|
+
/** core 引擎版本(verifyPromptArtifact 的 compatibleCore range 输入)——经 exports map 解析包根读
|
|
97
|
+
* package.json(`require('@sema-agent/core/package.json')` 被 exports 封死,ERR_PACKAGE_PATH_NOT_EXPORTED
|
|
98
|
+
* 第一手教训)。解析失败回 "0.0.0" = range-gated artifact 被诚实拒(fail-closed 响,绝不静默采用)。 */
|
|
68
99
|
export const CORE_ENGINE_VERSION = (() => {
|
|
69
100
|
try {
|
|
70
101
|
const entry = createRequire(import.meta.url).resolve("@sema-agent/core");
|
|
@@ -74,6 +105,14 @@ export const CORE_ENGINE_VERSION = (() => {
|
|
|
74
105
|
return "0.0.0";
|
|
75
106
|
}
|
|
76
107
|
})();
|
|
108
|
+
/**
|
|
109
|
+
* prompts 域候选门 v2(validateCenterPrompts 的双轴升级;整拒语义不变=任一在场轴坏形 ⇒ 整个 prompts
|
|
110
|
+
* 面拒绝采用,LKG/内置继续服务)。两形都认:
|
|
111
|
+
* - legacy 平铺(无 schemaVersion 键)= declaration 轴单轴(存量 center 停发平铺前的兼容窗);
|
|
112
|
+
* - `{schemaVersion:1, declarations?, catalog?}`(registry-core `EffectivePromptsWire`)= 至少一轴。
|
|
113
|
+
* catalog 轴的语义权威=core `verifyPromptArtifact`(形/digest 逐位复算/ARTIFACT_LIMITS/compatibleCore
|
|
114
|
+
* range 全在 core 一处——[1242]③ a 解,上限单真源永不漂)。
|
|
115
|
+
*/
|
|
77
116
|
export function validatePromptsDomain(raw) {
|
|
78
117
|
if (raw === null || typeof raw !== "object")
|
|
79
118
|
return { ok: false, error: "prompts is not an object" };
|
|
@@ -100,6 +139,8 @@ export function validatePromptsDomain(raw) {
|
|
|
100
139
|
const c = verifyPromptArtifact(w.catalog, { engineVersion: CORE_ENGINE_VERSION });
|
|
101
140
|
if (!c.ok)
|
|
102
141
|
return { ok: false, error: `catalog axis: ${c.code}: ${c.reason}` };
|
|
142
|
+
// verify 返回的是重建后的 typed artifact;wire 上的 envelope 原样保留(sourceRevision 不进 digest,
|
|
143
|
+
// e/b 接线时 core artifact 仓吃 envelope 全形)。
|
|
103
144
|
value.catalog = w.catalog;
|
|
104
145
|
value.axes.push("catalog");
|
|
105
146
|
}
|
package/dist/question.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { type AskQuestionRequest, type QuestionAnswer, type AskQuestion } from "@sema-agent/core";
|
|
2
|
+
/** A live question frame delivered to whoever tails this run's stream. `type` IS the SSE event name (mirrors the
|
|
3
|
+
* named-event convention; the payload also carries `type` so a proxy that strips event names still works). The shell
|
|
4
|
+
* renders `question` as a dialog and dismisses on `question_complete`. */
|
|
2
5
|
export interface QuestionFrame {
|
|
3
6
|
type: "question" | "question_complete";
|
|
4
7
|
questionId: string;
|
|
8
|
+
/** "question" only: the model's structured questions, secret-redacted. UNTRUSTED-for-display (shell renders; never
|
|
9
|
+
* re-feeds a model). Absent on an over-cap payload (the ask then headless-defaults). */
|
|
5
10
|
questions?: AskQuestion[];
|
|
11
|
+
/** "question_complete" only: whether the human answered (`answered`) or the ask was released unanswered
|
|
12
|
+
* (`unanswered` — ttl/abort → the model got the headless default). Cosmetic dialog-dismiss. */
|
|
6
13
|
outcome?: "answered" | "unanswered";
|
|
7
14
|
}
|
|
15
|
+
/** The per-run context `onQuestion` recovers via ALS. `emit` delivers a frame to the run's live stream; `abortSignal`
|
|
16
|
+
* (the run's own cancel signal) releases a question parked awaiting a human when the run aborts. */
|
|
8
17
|
export interface QuestionRunContext {
|
|
9
18
|
taskId: string;
|
|
10
19
|
owner: string | null;
|
|
@@ -12,11 +21,17 @@ export interface QuestionRunContext {
|
|
|
12
21
|
abortSignal?: AbortSignal;
|
|
13
22
|
}
|
|
14
23
|
export interface QuestionThrottle {
|
|
24
|
+
/** Max concurrent in-flight questions per run leg (parallel tool calls can each ask). Breach ⇒ headless default. */
|
|
15
25
|
maxConcurrentPerRun: number;
|
|
26
|
+
/** Max total questions one run leg surfaces to the human. Breach ⇒ headless default (flood defense). */
|
|
16
27
|
maxTotalPerRun: number;
|
|
28
|
+
/** An unanswered question auto-releases (headless default) after this (ms) — the human walked away; don't hold core. */
|
|
17
29
|
ttlMs: number;
|
|
18
30
|
}
|
|
19
31
|
export declare const DEFAULT_QUESTION_THROTTLE: QuestionThrottle;
|
|
32
|
+
/** Validate the respond body = core's {@link QuestionAnswer}. `selected`/`note` are OPAQUE passthrough (core fences
|
|
33
|
+
* them: `selected ⊆ options`, `note` untrusted-fenced) — we validate only the outer SHAPE (answers[] of {header,
|
|
34
|
+
* selected:string[], note?}), never the option semantics. */
|
|
20
35
|
export declare function parseQuestionResponse(body: unknown): {
|
|
21
36
|
ok: true;
|
|
22
37
|
value: QuestionAnswer;
|
|
@@ -24,19 +39,37 @@ export declare function parseQuestionResponse(body: unknown): {
|
|
|
24
39
|
ok: false;
|
|
25
40
|
error: string;
|
|
26
41
|
};
|
|
42
|
+
/** @deprecated design/158 N22: renamed to {@link parseQuestionResponse} — unifies the HITL trio's parse-fn
|
|
43
|
+
* vocabulary (`parseQuestionResponse` / `parseElicitationResponse` / `parseToolApprovalResponse`, all "the
|
|
44
|
+
* human's reply body"). Kept as a compat alias. */
|
|
27
45
|
export declare const parseQuestionAnswer: typeof parseQuestionResponse;
|
|
46
|
+
/**
|
|
47
|
+
* Coordinates AskUserQuestion HITL for the singleton runner. Process-local + same-replica (the pending map is in memory,
|
|
48
|
+
* like ElicitationCoordinator / steerableRuns): a respond that lands on another replica finds nothing → 404. Present
|
|
49
|
+
* (passed into `RunnerDeps.onQuestion` + the respond route) ONLY when `ASK_QUESTION_ENABLED` — absent ⇒ core mounts the
|
|
50
|
+
* AskUserQuestion tool with the headless default (a run never hangs; the model just can't get a live answer).
|
|
51
|
+
*/
|
|
28
52
|
export declare class QuestionCoordinator {
|
|
29
53
|
private readonly als;
|
|
30
54
|
private readonly pending;
|
|
31
55
|
private readonly counters;
|
|
32
56
|
private readonly throttle;
|
|
33
57
|
constructor(throttle?: QuestionThrottle);
|
|
58
|
+
/** Run `fn` with the per-run question context ambient. On exit, release any still-pending question for this run (a
|
|
59
|
+
* live-only question cannot outlive its leg → headless default) and drop the run's counters (no leak). */
|
|
34
60
|
runWithContext<T>(ctx: QuestionRunContext, fn: () => Promise<T>): Promise<T>;
|
|
61
|
+
/** `RunnerDeps.onQuestion`. core calls this when the agent's AskUserQuestion tool fires; the resolved answer is what
|
|
62
|
+
* the model sees. Headless default (`NO_HUMAN`) in every case with no live human, so the run never hangs. Arrow
|
|
63
|
+
* property so it can be passed as `onQuestion: coordinator.question` with `this` bound. */
|
|
35
64
|
question: (req: AskQuestionRequest, signal?: AbortSignal) => Promise<QuestionAnswer>;
|
|
65
|
+
/** `POST /v1/questions/:id/respond` — resolve a parked question with the shell's answer. Owner-gated with a 404 (no
|
|
66
|
+
* existence oracle): a non-owner AND an unknown id (answered / expired / wrong replica) both get 404. Returns the
|
|
67
|
+
* HTTP {status, body}; the HTTP layer owns auth (gatedPrincipal + REQUIRE_PRINCIPAL) before calling. */
|
|
36
68
|
respond(id: string, principal: string | undefined, body: unknown): {
|
|
37
69
|
status: number;
|
|
38
70
|
body: unknown;
|
|
39
71
|
};
|
|
72
|
+
/** Test/observability hook: number of currently-parked questions. */
|
|
40
73
|
pendingCount(): number;
|
|
41
74
|
private countersFor;
|
|
42
75
|
}
|