@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/memory-export.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { MemoryBackend, MemoryEntry } from "@sema-agent/core";
|
|
2
|
+
/** All entries of one scope, deterministic id order (both backend read faces ORDER BY id). */
|
|
2
3
|
export declare function exportMemoryScope(backend: MemoryBackend, scope: string): Promise<MemoryEntry[]>;
|
|
3
4
|
//# sourceMappingURL=memory-export.d.ts.map
|
package/dist/memory-export.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
/** All entries of one scope, deterministic id order (both backend read faces ORDER BY id). */
|
|
1
2
|
export async function exportMemoryScope(backend, scope) {
|
|
2
3
|
const headers = await backend.listHeaders([scope]);
|
|
3
4
|
if (headers.length === 0)
|
|
4
5
|
return [];
|
|
5
6
|
const entries = await backend.getByIds(headers.map((h) => h.id));
|
|
7
|
+
// Defense-in-depth: getByIds is id-keyed (no scope filter). The ids came from THIS scope's own
|
|
8
|
+
// headers, but a header-read/entry-read race (concurrent cross-scope re-add) must never leak a
|
|
9
|
+
// foreign scope's entry into an owner-gated export — filter honestly.
|
|
6
10
|
return entries.filter((e) => e.scope === scope);
|
|
7
11
|
}
|
|
8
12
|
//# sourceMappingURL=memory-export.js.map
|
package/dist/memory-scope.d.ts
CHANGED
|
@@ -1,14 +1,63 @@
|
|
|
1
1
|
import { FileMemoryEngineBackend } from "@sema-agent/core";
|
|
2
2
|
import type { ServiceConfig } from "./config-types.js";
|
|
3
|
+
/** Resolve the memory scope for a request (design/138 S1 — the file-based memory engine is the only plane).
|
|
4
|
+
*
|
|
5
|
+
* SINGLE-USER (REQUIRE_PRINCIPAL !== "true"): ONE shared scope — `config.memoryScope` (default "local"),
|
|
6
|
+
* regardless of any principal label the caller self-reports (a single-user worker's `anon:*` / ad-hoc
|
|
7
|
+
* principals are surface labels, not isolation identities — keying memory by them would split the one
|
|
8
|
+
* user's memory across surfaces). Explicit `MEMORY_SCOPE` wins (it IS config.memoryScope).
|
|
9
|
+
*
|
|
10
|
+
* MULTI-TENANT (REQUIRE_PRINCIPAL=true): always `undefined` ⇒ no `spec.memory` ⇒ memory is DARK,
|
|
11
|
+
* fail-closed. The engine's file basement carries NO tenant isolation (one shared directory tree), so
|
|
12
|
+
* handing tenants per-principal scopes over it would be a cross-tenant bleed surface; until a
|
|
13
|
+
* tenant-isolated backend exists, multi-tenant memory is off by construction. */
|
|
3
14
|
export declare function memoryScopeFor(config: ServiceConfig, principal?: string, projectId?: string): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* N0 (通宵测试 2026-07-09,三重坐实 e2b+kata+代码): the file memory engine (core design/138) materializes and
|
|
17
|
+
* harvests via `node:fs` on the WORKER's local fs, while a remote exec lane routes the model's file tools to
|
|
18
|
+
* the SANDBOX fs — the planes never meet: materialized memory is invisible inside the sandbox (the injected
|
|
19
|
+
* instructions burn failing Write turns) and sandbox writes are never harvested (add=0). Until core defines
|
|
20
|
+
* the boundary (engine routed through the ExecutionEnv seam, or host-only by contract — relayed on the team
|
|
21
|
+
* channel), a remote lane forces memory DARK unless the operator explicitly vouches both lanes share one fs
|
|
22
|
+
* (`MEMORY_ENGINE_REMOTE_LANE=allow`, e.g. ssh to a host on the same NFS mount).
|
|
23
|
+
*
|
|
24
|
+
* Pure posture probe (memoryEngineBackendFor consumes it; main.ts logs it): `undefined` = no plane split
|
|
25
|
+
* (no remote lane, or the `host` lane), `dark` = split + fail-closed, `forced` = split + operator override.
|
|
26
|
+
*/
|
|
4
27
|
export declare function memoryEngineRemoteLanePosture(config: ServiceConfig): {
|
|
5
28
|
lane: string;
|
|
6
29
|
posture: "dark" | "forced";
|
|
7
30
|
} | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* design/138 S1 wiring gate (pure — unit-testable without booting main): build the file-based memory-engine
|
|
33
|
+
* backend for this deployment, or `undefined` when memory must stay dark.
|
|
34
|
+
*
|
|
35
|
+
* - SINGLE-USER TURNKEY ONLY (`requirePrincipal !== true`): the engine's file basement
|
|
36
|
+
* (`FileMemoryEngineBackend` over one directory tree) has NO tenant isolation, so a multi-tenant
|
|
37
|
+
* deployment gets `undefined` — memory dark, fail-closed (never a shared cross-tenant store).
|
|
38
|
+
* - `MEMORY_ENGINE=off` (`config.memoryEngineEnabled === false`) is the explicit operator kill-switch.
|
|
39
|
+
* - REMOTE EXEC LANE (N0): a plane-splitting lane (any non-`host` remoteExec) forces `undefined` — memory
|
|
40
|
+
* dark, fail-closed — unless `MEMORY_ENGINE_REMOTE_LANE=allow` (see memoryEngineRemoteLanePosture above).
|
|
41
|
+
* - Directory: `<root>/memory` where root = `resolveMemoryEngineRoot(config.memoryEngineDir ?? fallbackRoot)`
|
|
42
|
+
* (explicit `MEMORY_ENGINE_DIR` → caller's data root → `AGENT_DATA_DIR` env → `~/.ai-agent`). The
|
|
43
|
+
* FileBackend PINS this directory (core §2.7: `directoryRoot` wins over per-repo derivation), so the
|
|
44
|
+
* single user has ONE memory home across repos/tasks — the CC `~/.claude` posture.
|
|
45
|
+
*
|
|
46
|
+
* Returns the backend + the resolved config root (the root also rides on `RunnerDeps.memoryEngineDir` so
|
|
47
|
+
* core derives the B3 control plane beside it).
|
|
48
|
+
*/
|
|
8
49
|
export declare function memoryEngineBackendFor(config: ServiceConfig, fallbackRoot?: string): {
|
|
9
50
|
backend: FileMemoryEngineBackend;
|
|
10
51
|
root: string;
|
|
11
52
|
} | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* MF-30 memory PAUSE (option B, per-request — clay 2026-06-27): build the `TaskSpec.memory` spec for ONE run from
|
|
55
|
+
* the resolved memory `scope` + the request's `memoryWrite` toggle. `memoryWrite === false` ⇒ `writeScope: null`
|
|
56
|
+
* (design/138 engine read-only: normalizeMemorySpec's writeScope:null — materialize/read still works, harvest
|
|
57
|
+
* commits nothing). Absent/true ⇒ normal read+write. No scope (engine off / multi-tenant dark) ⇒ undefined
|
|
58
|
+
* (memory feature off for this run). Pure (testable in isolation) — main.ts's resolveSpec composes it with the
|
|
59
|
+
* engine-backend presence guard.
|
|
60
|
+
*/
|
|
12
61
|
export declare function memorySpecForRequest(scope: string | undefined, memoryWrite: boolean | undefined, defaultScopes?: string[]): {
|
|
13
62
|
scope: string;
|
|
14
63
|
scopes?: string[];
|
package/dist/memory-scope.js
CHANGED
|
@@ -1,38 +1,121 @@
|
|
|
1
|
+
// design/158 N17: the memory-plane resolvers moved VERBATIM out of security.ts (lens4 §4.1 — "budget.ts"'s
|
|
2
|
+
// sibling finding: security.ts's name says auth, but ~110 of its 765 lines were memory-scope config
|
|
3
|
+
// resolution with nothing to do with authentication). security.ts re-exports all four for compat (its own
|
|
4
|
+
// createAuthorizer still calls memoryScopeFor); index.ts's npm-facing re-export is unaffected (package.json
|
|
5
|
+
// "exports" only ever exposed "." and "./main" — dist/security.js was never a reachable deep-import path).
|
|
1
6
|
import { join } from "node:path";
|
|
2
7
|
import { FileMemoryEngineBackend, resolveMemoryEngineRoot, deriveControlPlaneDir, formatUserScope, formatProjScope } from "@sema-agent/core";
|
|
8
|
+
/** Resolve the memory scope for a request (design/138 S1 — the file-based memory engine is the only plane).
|
|
9
|
+
*
|
|
10
|
+
* SINGLE-USER (REQUIRE_PRINCIPAL !== "true"): ONE shared scope — `config.memoryScope` (default "local"),
|
|
11
|
+
* regardless of any principal label the caller self-reports (a single-user worker's `anon:*` / ad-hoc
|
|
12
|
+
* principals are surface labels, not isolation identities — keying memory by them would split the one
|
|
13
|
+
* user's memory across surfaces). Explicit `MEMORY_SCOPE` wins (it IS config.memoryScope).
|
|
14
|
+
*
|
|
15
|
+
* MULTI-TENANT (REQUIRE_PRINCIPAL=true): always `undefined` ⇒ no `spec.memory` ⇒ memory is DARK,
|
|
16
|
+
* fail-closed. The engine's file basement carries NO tenant isolation (one shared directory tree), so
|
|
17
|
+
* handing tenants per-principal scopes over it would be a cross-tenant bleed surface; until a
|
|
18
|
+
* tenant-isolated backend exists, multi-tenant memory is off by construction. */
|
|
3
19
|
export function memoryScopeFor(config, principal, projectId) {
|
|
4
20
|
if (config.requirePrincipal === true) {
|
|
21
|
+
// S3-TOB(设计 §1.3):multi-tenant lights up ONLY on a DB backend (scope column = tenant
|
|
22
|
+
// partition) — the scope is the VERIFIED principal, never MEMORY_SCOPE (a shared-env scope here would
|
|
23
|
+
// be a cross-tenant bleed, 复审 F6) and never absent-principal (anonymous run ⇒ no memory).
|
|
24
|
+
// NOTE (复审 F-07): the scope column is data PARTITIONING; tenant AUTHORIZATION is exactly this
|
|
25
|
+
// binding — verified principal in, one tenant's scope out. File backend stays dark (no isolation).
|
|
26
|
+
// 142-S1.5(core 1.268.0 到货即切,免费迁移窗=现网点亮前存量 0):bare principal → the v2 typed
|
|
27
|
+
// key `user:<tenant>` via core's formatUserScope (encodeScopeSegment inside — principal chars are
|
|
28
|
+
// segment-encoded, never truncated/collided). Paired with scopeContract:"v2" on the spec face below
|
|
29
|
+
// (opt-in is EXPLICIT per design/142 §1.2 — no prefix sniffing anywhere).
|
|
30
|
+
// 142-S4(派生 v1=项目盘):a SHAPE-VALIDATED projectId(authorizer 的 PROJECT_ID_REGEX 门)
|
|
31
|
+
// 在场 ⇒ 项目盘 v2 键 `proj:<tenant>/<projectId>`(core formatProjScope;tenant 段 = verified
|
|
32
|
+
// principal,身份永远不来自 body — projectId 只挑盘)。铁律:proj: 键经我方 DB 的场景=无仓
|
|
33
|
+
// project(有仓 project 权威=git,根本不到这条派生线)。userproj: 派生不在 v1(待拍板)。
|
|
5
34
|
if (config.memoryEngineBackend === "pg" || config.memoryEngineBackend === "tidb") {
|
|
6
35
|
if (!principal)
|
|
7
36
|
return undefined;
|
|
8
37
|
return projectId ? formatProjScope(principal, projectId) : formatUserScope(principal);
|
|
9
38
|
}
|
|
10
|
-
return undefined;
|
|
39
|
+
return undefined; // file backend: dark, fail-closed (no tenant isolation in the file engine)
|
|
11
40
|
}
|
|
12
|
-
return config.memoryScope;
|
|
41
|
+
return config.memoryScope; // single-user: one shared scope — principal labels never partition memory
|
|
13
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* N0 (通宵测试 2026-07-09,三重坐实 e2b+kata+代码): the file memory engine (core design/138) materializes and
|
|
45
|
+
* harvests via `node:fs` on the WORKER's local fs, while a remote exec lane routes the model's file tools to
|
|
46
|
+
* the SANDBOX fs — the planes never meet: materialized memory is invisible inside the sandbox (the injected
|
|
47
|
+
* instructions burn failing Write turns) and sandbox writes are never harvested (add=0). Until core defines
|
|
48
|
+
* the boundary (engine routed through the ExecutionEnv seam, or host-only by contract — relayed on the team
|
|
49
|
+
* channel), a remote lane forces memory DARK unless the operator explicitly vouches both lanes share one fs
|
|
50
|
+
* (`MEMORY_ENGINE_REMOTE_LANE=allow`, e.g. ssh to a host on the same NFS mount).
|
|
51
|
+
*
|
|
52
|
+
* Pure posture probe (memoryEngineBackendFor consumes it; main.ts logs it): `undefined` = no plane split
|
|
53
|
+
* (no remote lane, or the `host` lane), `dark` = split + fail-closed, `forced` = split + operator override.
|
|
54
|
+
*/
|
|
14
55
|
export function memoryEngineRemoteLanePosture(config) {
|
|
15
56
|
const lane = config.remoteExec?.provider;
|
|
16
57
|
if (lane === undefined || lane === "host")
|
|
17
|
-
return undefined;
|
|
58
|
+
return undefined; // hands work THIS machine's fs — same plane
|
|
18
59
|
return { lane, posture: config.memoryEngineRemoteLaneAllowed === true ? "forced" : "dark" };
|
|
19
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* design/138 S1 wiring gate (pure — unit-testable without booting main): build the file-based memory-engine
|
|
63
|
+
* backend for this deployment, or `undefined` when memory must stay dark.
|
|
64
|
+
*
|
|
65
|
+
* - SINGLE-USER TURNKEY ONLY (`requirePrincipal !== true`): the engine's file basement
|
|
66
|
+
* (`FileMemoryEngineBackend` over one directory tree) has NO tenant isolation, so a multi-tenant
|
|
67
|
+
* deployment gets `undefined` — memory dark, fail-closed (never a shared cross-tenant store).
|
|
68
|
+
* - `MEMORY_ENGINE=off` (`config.memoryEngineEnabled === false`) is the explicit operator kill-switch.
|
|
69
|
+
* - REMOTE EXEC LANE (N0): a plane-splitting lane (any non-`host` remoteExec) forces `undefined` — memory
|
|
70
|
+
* dark, fail-closed — unless `MEMORY_ENGINE_REMOTE_LANE=allow` (see memoryEngineRemoteLanePosture above).
|
|
71
|
+
* - Directory: `<root>/memory` where root = `resolveMemoryEngineRoot(config.memoryEngineDir ?? fallbackRoot)`
|
|
72
|
+
* (explicit `MEMORY_ENGINE_DIR` → caller's data root → `AGENT_DATA_DIR` env → `~/.ai-agent`). The
|
|
73
|
+
* FileBackend PINS this directory (core §2.7: `directoryRoot` wins over per-repo derivation), so the
|
|
74
|
+
* single user has ONE memory home across repos/tasks — the CC `~/.claude` posture.
|
|
75
|
+
*
|
|
76
|
+
* Returns the backend + the resolved config root (the root also rides on `RunnerDeps.memoryEngineDir` so
|
|
77
|
+
* core derives the B3 control plane beside it).
|
|
78
|
+
*/
|
|
20
79
|
export function memoryEngineBackendFor(config, fallbackRoot) {
|
|
21
80
|
if (config.requirePrincipal === true || !config.memoryEngineEnabled)
|
|
22
81
|
return undefined;
|
|
23
82
|
if (memoryEngineRemoteLanePosture(config)?.posture === "dark")
|
|
24
|
-
return undefined;
|
|
83
|
+
return undefined; // N0: worker/sandbox file planes split
|
|
25
84
|
const root = resolveMemoryEngineRoot(config.memoryEngineDir ?? fallbackRoot);
|
|
26
85
|
const dir = join(root, "memory");
|
|
86
|
+
// 🔴 controlDir EXPLICIT: the backend's DEFAULT control plane derives from the ARGLESS
|
|
87
|
+
// resolveMemoryEngineRoot() — i.e. AGENT_DATA_DIR/~/.ai-agent, IGNORING an explicit MEMORY_ENGINE_DIR. With a
|
|
88
|
+
// custom dir the sidecars (ledger/shadow/quarantine) would land under the DEFAULT root while
|
|
89
|
+
// RunnerDeps.memoryEngineDir points core's engine at the custom root — a split control plane. Pin it beside
|
|
90
|
+
// OUR root using core's own derivation (key = the memory dir, the same shape as the backend's default).
|
|
27
91
|
return { backend: new FileMemoryEngineBackend(dir, { controlDir: deriveControlPlaneDir(root, dir) }), root };
|
|
28
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* MF-30 memory PAUSE (option B, per-request — clay 2026-06-27): build the `TaskSpec.memory` spec for ONE run from
|
|
95
|
+
* the resolved memory `scope` + the request's `memoryWrite` toggle. `memoryWrite === false` ⇒ `writeScope: null`
|
|
96
|
+
* (design/138 engine read-only: normalizeMemorySpec's writeScope:null — materialize/read still works, harvest
|
|
97
|
+
* commits nothing). Absent/true ⇒ normal read+write. No scope (engine off / multi-tenant dark) ⇒ undefined
|
|
98
|
+
* (memory feature off for this run). Pure (testable in isolation) — main.ts's resolveSpec composes it with the
|
|
99
|
+
* engine-backend presence guard.
|
|
100
|
+
*/
|
|
29
101
|
export function memorySpecForRequest(scope, memoryWrite, defaultScopes) {
|
|
30
102
|
if (!scope)
|
|
31
103
|
return undefined;
|
|
104
|
+
// 142-S1.5: a scope carrying a v2 typed prefix rides WITH the explicit contract marker — core validates
|
|
105
|
+
// the key fail-loud under "v2" (design/142 §1.2). Detection here is NOT sniffing: `user:`/`proj:` keys are
|
|
106
|
+
// OUR memoryScopeFor's own mint (formatUserScope/formatProjScope) and `defaultScopes` entries are the
|
|
107
|
+
// OPERATOR's center-registry declaration (config.projects — 登记簿说明其形态=v2 scope 键串),so the
|
|
108
|
+
// prefix is a self/operator-produced marker, never a guess about caller data; a legacy opaque scope
|
|
109
|
+
// (single-user config.memoryScope) with no defaultScopes stays contract-less byte-identical.
|
|
32
110
|
const isV2 = (k) => k.startsWith("user:") || k.startsWith("org:") || k.startsWith("proj:") || k.startsWith("userproj:");
|
|
111
|
+
// 142-S4 defaultScopes 种子(config.projects[projectId].defaultScopes):额外的 READ 层(去重、去 scope
|
|
112
|
+
// 自身、去空串;保 center 声明顺序)。写路由不变:core normalizeMemorySpec 的 writeScope 缺省=scopes 的
|
|
113
|
+
// 最后一层,所以带种子时必须 EXPLICIT 钉 writeScope=派生 scope(否则 harvest 会写进登记簿的最后一个默认
|
|
114
|
+
// scope — 一个共享层,错)。无种子 = 形状逐字节等价旧版(additive 锁)。
|
|
33
115
|
const extras = (defaultScopes ?? []).filter((s, i, arr) => typeof s === "string" && s.length > 0 && s !== scope && arr.indexOf(s) === i);
|
|
34
116
|
const layered = extras.length > 0 ? { scopes: [scope, ...extras], writeScope: scope } : {};
|
|
35
117
|
const v2 = isV2(scope) || extras.some(isV2) ? { scopeContract: "v2" } : {};
|
|
118
|
+
// memoryWrite === false(MF-30 pause)wins over the layered writeScope pin — 只读语义在有种子时同样成立。
|
|
36
119
|
return memoryWrite === false ? { scope, ...layered, writeScope: null, ...v2 } : { scope, ...layered, ...v2 };
|
|
37
120
|
}
|
|
38
121
|
//# sourceMappingURL=memory-scope.js.map
|
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
import { type MemoryBackend, type MemorySyncClientResult, type MemorySyncTransport } from "@sema-agent/core";
|
|
2
|
+
/** 结构化日志面(src/observability/logger.ts Logger 的结构子集——测试可注入捕获器)。 */
|
|
2
3
|
export interface MemorySyncLog {
|
|
3
4
|
info(msg: string, fields?: Record<string, unknown>): void;
|
|
4
5
|
warn(msg: string, fields?: Record<string, unknown>): void;
|
|
5
6
|
}
|
|
7
|
+
/** 缺省对端名(core `syncMemoryScope` 同款缺省;cursor 按 (scope,peer) 分区)。 */
|
|
6
8
|
export declare const DEFAULT_MEMORY_SYNC_PEER = "central";
|
|
9
|
+
/**
|
|
10
|
+
* fetch transport(core `MemorySyncTransport` 的部署实现)。`url` = 中心 server 基址(尾斜杠剥除,
|
|
11
|
+
* core 传来的 path 以 `/` 开头);`token` 走 Authorization: Bearer(与中心侧 gatedPrincipal 的
|
|
12
|
+
* verified-principal 门对齐)。非 2xx throw(status + body 前 200 字节——中心 4xx/5xx 的 typed error
|
|
13
|
+
* body 就是最好的诊断线索);2xx 返回解码后的 JSON(形状校验在 core parseMemorySyncResponse,职责
|
|
14
|
+
* 不重复)。`timeoutMs`(缺省 60s,AbortSignal.timeout)是活性保护:fire-and-forget 轮挂死会把
|
|
15
|
+
* inflight 节流永久卡住(undici 默认 headers 超时 300s 太钝)。
|
|
16
|
+
*/
|
|
7
17
|
export declare function createMemorySyncTransport(opts: {
|
|
8
18
|
url: string;
|
|
9
19
|
token: string;
|
|
10
20
|
timeoutMs?: number;
|
|
11
21
|
fetchImpl?: typeof fetch;
|
|
12
22
|
}): MemorySyncTransport;
|
|
23
|
+
/** cursor 文件路径:`memoryRoot`(= RunnerDeps.memoryEngineDir 的 resolved config root,memory/ 目录
|
|
24
|
+
* 旁)下的 per-peer sidecar。peer 段走 core encodeScopeSegment(文件名安全字符纪律与 scope 目录同)。 */
|
|
13
25
|
export declare function memorySyncCursorPath(memoryRoot: string, peer: string): string;
|
|
14
26
|
export interface MemorySyncRunner {
|
|
27
|
+
/** 一轮同步(串行:排在上一轮之后)。返回 core 结构化结果供调用方记 metrics/日志;transport/
|
|
28
|
+
* 协议错误向上 throw(本地零副作用,core 契约)。cursor 读写、conflicts warn 都在轮内完成。 */
|
|
15
29
|
syncOnce(reason: string): Promise<MemorySyncClientResult>;
|
|
30
|
+
/** fire-and-forget 一轮:上一轮在飞(排队/执行中)则跳过(inflight 节流);失败 warn 不上抛。 */
|
|
16
31
|
trigger(reason: string): void;
|
|
32
|
+
/** cursor sidecar 的落盘路径(boot 日志/测试可见性)。 */
|
|
17
33
|
readonly cursorPath: string;
|
|
34
|
+
/** 排队+在飞的轮数(测试的确定性等待面;0 = 完全空闲)。 */
|
|
18
35
|
pending(): number;
|
|
19
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* 组装一个 per-(scope,peer) 的同步执行器:cursor 持久化 + core `syncMemoryScope` + conflicts 上报 +
|
|
39
|
+
* 串行化/节流。`backend` = 本地 File authority plane(memoryEngineBackendFor 的产物);`memoryRoot` =
|
|
40
|
+
* resolved config root(cursor sidecar 落在 memory/ 目录旁)。
|
|
41
|
+
*/
|
|
42
|
+
/** S2.5 分批 loop 的轮数上限(fail-loud 警戒,防协议异常时死循环;正常收敛远低于此)。 */
|
|
20
43
|
export declare const MAX_SYNC_ROUNDS = 32;
|
|
21
44
|
export declare function createMemorySyncRunner(opts: {
|
|
22
45
|
backend: MemoryBackend;
|
|
@@ -26,6 +49,7 @@ export declare function createMemorySyncRunner(opts: {
|
|
|
26
49
|
log: MemorySyncLog;
|
|
27
50
|
peer?: string;
|
|
28
51
|
now?: () => number;
|
|
52
|
+
/** S2.5 分批(core 1.284 两 seam):push 集/pull 集单轮上限。未设=不分批(wire 字节不变)。 */
|
|
29
53
|
maxPushEntries?: number;
|
|
30
54
|
maxPullEntries?: number;
|
|
31
55
|
}): MemorySyncRunner;
|
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
// 142-S2.5-W1 —— TOC 同步 client 腿:包 core `syncMemoryScope`(1.275.1 导出,一轮 =
|
|
2
|
+
// 一 RTT 双向,cursor 保留纪律见 core sync-client.js 头注)。本模块只补 core 刻意留白的部署半场:
|
|
3
|
+
// ① transport:fetch POST `{MEMORY_SYNC_URL 去尾斜杠}{path}`(path 由 core 铸,scope 已
|
|
4
|
+
// encodeURIComponent),headers = Bearer + JSON;非 2xx throw(带 status + body 前 200 字节)。
|
|
5
|
+
// core 契约:transport 在任何本地写之前跑,throw = 本轮零本地副作用。
|
|
6
|
+
// ② cursor 持久化:`join(memoryRoot, "sync-cursor-" + encodeScopeSegment(peer) + ".json")`——
|
|
7
|
+
// 读:不存在 ⇒ undefined(首轮);坏 JSON/形状不符/scope-peer 不匹配 ⇒ warn + 当首轮(core 对
|
|
8
|
+
// 错配 cursor 是 fail-loud throw,这里预检降为首轮:空基线重收敛是协议的幂等安全面)。
|
|
9
|
+
// 写:仅 cursorAdvanced 才写(core 保留纪律的落盘半场),tmp+rename 原子。
|
|
10
|
+
// ③ 串行化 + 节流:syncOnce 按 promise 链串行(两轮并发会在同一文件面上交错写);trigger =
|
|
11
|
+
// fire-and-forget,上一轮在飞(排队中/执行中)则跳过(设计:简单 inflight 布尔)。
|
|
12
|
+
// conflicts = logger.warn 逐条上报(不自动 ladder——败者铸 sibling 的解决动作留给 operator/后续单)。
|
|
1
13
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
14
|
import { dirname, join } from "node:path";
|
|
3
15
|
import { encodeScopeSegment, syncMemoryScope, } from "@sema-agent/core";
|
|
16
|
+
/** 缺省对端名(core `syncMemoryScope` 同款缺省;cursor 按 (scope,peer) 分区)。 */
|
|
4
17
|
export const DEFAULT_MEMORY_SYNC_PEER = "central";
|
|
18
|
+
/**
|
|
19
|
+
* fetch transport(core `MemorySyncTransport` 的部署实现)。`url` = 中心 server 基址(尾斜杠剥除,
|
|
20
|
+
* core 传来的 path 以 `/` 开头);`token` 走 Authorization: Bearer(与中心侧 gatedPrincipal 的
|
|
21
|
+
* verified-principal 门对齐)。非 2xx throw(status + body 前 200 字节——中心 4xx/5xx 的 typed error
|
|
22
|
+
* body 就是最好的诊断线索);2xx 返回解码后的 JSON(形状校验在 core parseMemorySyncResponse,职责
|
|
23
|
+
* 不重复)。`timeoutMs`(缺省 60s,AbortSignal.timeout)是活性保护:fire-and-forget 轮挂死会把
|
|
24
|
+
* inflight 节流永久卡住(undici 默认 headers 超时 300s 太钝)。
|
|
25
|
+
*/
|
|
5
26
|
export function createMemorySyncTransport(opts) {
|
|
6
27
|
const base = opts.url.replace(/\/+$/, "");
|
|
7
28
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -19,9 +40,13 @@ export function createMemorySyncTransport(opts) {
|
|
|
19
40
|
return JSON.parse(text);
|
|
20
41
|
};
|
|
21
42
|
}
|
|
43
|
+
/** cursor 文件路径:`memoryRoot`(= RunnerDeps.memoryEngineDir 的 resolved config root,memory/ 目录
|
|
44
|
+
* 旁)下的 per-peer sidecar。peer 段走 core encodeScopeSegment(文件名安全字符纪律与 scope 目录同)。 */
|
|
22
45
|
export function memorySyncCursorPath(memoryRoot, peer) {
|
|
23
46
|
return join(memoryRoot, `sync-cursor-${encodeScopeSegment(peer)}.json`);
|
|
24
47
|
}
|
|
48
|
+
/** 读 cursor:不存在 ⇒ undefined(首轮);坏 JSON / 形状不符 / (scope,peer) 错配 ⇒ warn + undefined
|
|
49
|
+
* (core 对错配 cursor fail-loud throw——这里预检降为首轮,空基线重收敛幂等安全)。 */
|
|
25
50
|
async function loadCursor(path, scope, peer, log) {
|
|
26
51
|
let raw;
|
|
27
52
|
try {
|
|
@@ -57,12 +82,19 @@ async function loadCursor(path, scope, peer, log) {
|
|
|
57
82
|
log.warn("memory_sync_cursor_invalid", { path, scope, peer, note: "shape/identity mismatch — treating as first round" });
|
|
58
83
|
return undefined;
|
|
59
84
|
}
|
|
85
|
+
/** 写 cursor:tmp + rename 原子(半写的 cursor = 下轮坏 JSON 当首轮,重收敛而非错基线)。 */
|
|
60
86
|
async function saveCursor(path, cursor) {
|
|
61
87
|
await mkdir(dirname(path), { recursive: true });
|
|
62
88
|
const tmp = `${path}.tmp`;
|
|
63
89
|
await writeFile(tmp, JSON.stringify(cursor), "utf8");
|
|
64
90
|
await rename(tmp, path);
|
|
65
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* 组装一个 per-(scope,peer) 的同步执行器:cursor 持久化 + core `syncMemoryScope` + conflicts 上报 +
|
|
94
|
+
* 串行化/节流。`backend` = 本地 File authority plane(memoryEngineBackendFor 的产物);`memoryRoot` =
|
|
95
|
+
* resolved config root(cursor sidecar 落在 memory/ 目录旁)。
|
|
96
|
+
*/
|
|
97
|
+
/** S2.5 分批 loop 的轮数上限(fail-loud 警戒,防协议异常时死循环;正常收敛远低于此)。 */
|
|
66
98
|
export const MAX_SYNC_ROUNDS = 32;
|
|
67
99
|
export function createMemorySyncRunner(opts) {
|
|
68
100
|
const peer = opts.peer ?? DEFAULT_MEMORY_SYNC_PEER;
|
|
@@ -71,6 +103,8 @@ export function createMemorySyncRunner(opts) {
|
|
|
71
103
|
let cursor = await loadCursor(cursorPath, opts.scope, peer, opts.log);
|
|
72
104
|
let result;
|
|
73
105
|
let subRound = 0;
|
|
106
|
+
// S2.5 分批续轮:任一半场截断 ⇒ 立即续跑下一子轮(用上一轮返回的 cursor 作基线,协议幂等收敛);
|
|
107
|
+
// MAX_SYNC_ROUNDS 警戒 fail-loud(截断标志异常粘死时不无限烧请求,余量下轮 trigger 自然补)。
|
|
74
108
|
for (;;) {
|
|
75
109
|
subRound += 1;
|
|
76
110
|
result = await syncMemoryScope({
|
|
@@ -93,7 +127,7 @@ export function createMemorySyncRunner(opts) {
|
|
|
93
127
|
}
|
|
94
128
|
if (result.cursorAdvanced && result.cursor !== undefined) {
|
|
95
129
|
try {
|
|
96
|
-
await saveCursor(cursorPath, result.cursor);
|
|
130
|
+
await saveCursor(cursorPath, result.cursor); // 子轮间也持久化(崩溃不回退基线)
|
|
97
131
|
}
|
|
98
132
|
catch (err) {
|
|
99
133
|
opts.log.warn("memory_sync_cursor_write_failed", { path: cursorPath, err: String(err) });
|
|
@@ -102,6 +136,7 @@ export function createMemorySyncRunner(opts) {
|
|
|
102
136
|
cursor = result.cursor ?? cursor;
|
|
103
137
|
opts.log.info("memory_sync_continuation", { reason, scope: opts.scope, peer, subRound, pushTruncated: result.pushTruncated === true, pullTruncated: result.pullTruncated === true });
|
|
104
138
|
}
|
|
139
|
+
// conflicts 逐条 warn(server 半场 + 本地半场聚合,core 绝不隐藏;解决 ladder 不自动跑)。
|
|
105
140
|
for (const c of result.conflicts) {
|
|
106
141
|
opts.log.warn("memory_sync_conflict", {
|
|
107
142
|
scope: opts.scope,
|
|
@@ -113,6 +148,8 @@ export function createMemorySyncRunner(opts) {
|
|
|
113
148
|
...(c.currentRev !== undefined ? { currentRev: c.currentRev } : {}),
|
|
114
149
|
});
|
|
115
150
|
}
|
|
151
|
+
// 保留纪律的落盘半场:仅 cursorAdvanced 才写。写失败只 warn(数据已按 CAS 落定,丢的是基线推进——
|
|
152
|
+
// 下轮按旧基线重放即幂等自愈,与中心侧 putCursor 失败的收敛论证同款),绝不把成功轮报成失败。
|
|
116
153
|
if (result.cursorAdvanced && result.cursor !== undefined) {
|
|
117
154
|
try {
|
|
118
155
|
await saveCursor(cursorPath, result.cursor);
|
|
@@ -135,6 +172,8 @@ export function createMemorySyncRunner(opts) {
|
|
|
135
172
|
});
|
|
136
173
|
return result;
|
|
137
174
|
};
|
|
175
|
+
// 串行链:两轮并发会在同一 File plane / cursor 文件上交错(push 半场读集与 pull 半场落盘互踩)。
|
|
176
|
+
// `pending` = 排队+在飞的轮数(设计的“简单 inflight 布尔”推广到可排队形态:syncOnce 排队,trigger 跳过)。
|
|
138
177
|
let chain = Promise.resolve();
|
|
139
178
|
let pending = 0;
|
|
140
179
|
const syncOnce = (reason) => {
|
|
@@ -149,7 +188,7 @@ export function createMemorySyncRunner(opts) {
|
|
|
149
188
|
};
|
|
150
189
|
const trigger = (reason) => {
|
|
151
190
|
if (pending > 0)
|
|
152
|
-
return;
|
|
191
|
+
return; // 上一轮在飞 ⇒ 跳过(harvest 高频时的节流;漏掉的变更下一轮全量补上)
|
|
153
192
|
void syncOnce(reason).catch((err) => {
|
|
154
193
|
opts.log.warn("memory_sync_failed", { reason, scope: opts.scope, peer, err: String(err) });
|
|
155
194
|
});
|
package/dist/memory-sync.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import { type MemoryBackend, type MemoryEntry, type PatchReport } from "@sema-agent/core";
|
|
2
2
|
import type { MemorySyncStore } from "./plugins/memory-sync-store-pg.js";
|
|
3
|
+
/** 一轮同步请求(验型后的干净形状——`parseMemorySyncRequest` 是唯一铸造点)。 */
|
|
3
4
|
export interface MemorySyncRequest {
|
|
5
|
+
/** 对端标识(MemorySyncCursor.peer,per-(scope,peer) 游标分区键)。 */
|
|
4
6
|
peer: string;
|
|
7
|
+
/** 客户端游标的共同基线:id → rev at last completed sync round(空 map = 首轮)。 */
|
|
5
8
|
baseRevs: Record<string, string>;
|
|
9
|
+
/** push 半场:自基线以来客户端新增/变更的条目全量(scope 已验 = 路径 scope)。 */
|
|
6
10
|
entries: MemoryEntry[];
|
|
11
|
+
/** 客户端删除的 id(每个都在 baseRevs 里——CAS 基线;验型层保证)。 */
|
|
7
12
|
deletes: string[];
|
|
13
|
+
/** S2.5 分批腿(契约 settled 2026-07-14,全 additive):pull 半场条目数上限。缺席=不限(旧行为
|
|
14
|
+
* 字节不变)。截断规则见 performMemorySync ⑥。 */
|
|
8
15
|
pull?: {
|
|
9
16
|
limit: number;
|
|
10
17
|
};
|
|
11
18
|
}
|
|
19
|
+
/** 一条冲突上报(applyPatches conflicts 同形 + 入站门/发散两类 reason)。`currentRev` = 中心侧
|
|
20
|
+
* 当前 rev(中心已删则缺席)——客户端按 core §3 ladder 解决(败者铸 sibling,绝不静默丢)。 */
|
|
12
21
|
export interface MemorySyncConflictReport {
|
|
13
22
|
id: string;
|
|
14
23
|
reason: string;
|
|
@@ -16,20 +25,27 @@ export interface MemorySyncConflictReport {
|
|
|
16
25
|
currentRev?: string;
|
|
17
26
|
}
|
|
18
27
|
export interface MemorySyncResponse {
|
|
28
|
+
/** 中心侧本轮真正落库的 op(backend PatchReport.applied 原样——幂等重放时为空)。 */
|
|
19
29
|
applied: PatchReport["applied"];
|
|
20
30
|
conflicts: MemorySyncConflictReport[];
|
|
31
|
+
/** pull 半场:中心侧自 baseRevs 以来新增/变更的条目全量(客户端按自己的 baseRevs CAS 应用)。 */
|
|
21
32
|
serverEntries: MemoryEntry[];
|
|
33
|
+
/** pull 半场的删除腿(core plan.deleteRemote;草案偏离①——没它中心删除永不传播 = livelock)。 */
|
|
22
34
|
serverDeletes: Array<{
|
|
23
35
|
id: string;
|
|
24
36
|
baseRev: string;
|
|
25
37
|
}>;
|
|
38
|
+
/** 本轮落库的新基线(草案偏离②)——客户端应用完 pull 半场后把它持久化为自己的游标。 */
|
|
26
39
|
cursor: {
|
|
27
40
|
peer: string;
|
|
28
41
|
baseRevs: Record<string, string>;
|
|
29
42
|
updatedAtMs: number;
|
|
30
43
|
};
|
|
44
|
+
/** S2.5 分批腿:serverEntries 被 pull.limit 截断时为 true(缺席=未截断)。客户端续轮直到缺席。 */
|
|
31
45
|
pullTruncated?: true;
|
|
32
46
|
}
|
|
47
|
+
/** 一轮 push 的条目数上限 = core REMOTE_HARVEST_MAX_FILES 同款口径(一个 scope 的文件面上限 500;
|
|
48
|
+
* 同步一轮打满全集也在此内)。deletes 上限同基数放宽(全集删除也要能一轮表达)。 */
|
|
33
49
|
export declare const MEMORY_SYNC_MAX_ENTRIES = 500;
|
|
34
50
|
export declare const MEMORY_SYNC_MAX_DELETES = 2000;
|
|
35
51
|
type ParseResult = {
|
|
@@ -39,7 +55,14 @@ type ParseResult = {
|
|
|
39
55
|
ok: false;
|
|
40
56
|
error: string;
|
|
41
57
|
};
|
|
58
|
+
/** Shape-validate + NORMALIZE the request body (picked-not-spread:只挑认识的字段重建,body 上的
|
|
59
|
+
* 多余键绝不透传进数据面)。`scope` = 路径上已过 owner 门的 scope——每个条目的 scope 必须逐字
|
|
60
|
+
* 等于它(否则一个 owner-gated 路由就成了跨租户写门)。 */
|
|
42
61
|
export declare function parseMemorySyncRequest(body: unknown, scope: string): ParseResult;
|
|
62
|
+
/**
|
|
63
|
+
* One full sync round for one (scope, peer). `backend` = 中心侧 entry plane(DB 权威),`cursors` =
|
|
64
|
+
* per-(scope,peer) 游标面(sync_cursors)。纯数据参数进(路由已完成鉴权/owner 门/验型),响应形状出。
|
|
65
|
+
*/
|
|
43
66
|
export declare function performMemorySync(backend: MemoryBackend, cursors: Pick<MemorySyncStore, "putCursor">, scope: string, req: MemorySyncRequest, now?: () => number): Promise<MemorySyncResponse>;
|
|
44
67
|
export {};
|
|
45
68
|
//# sourceMappingURL=memory-sync.d.ts.map
|
package/dist/memory-sync.js
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
|
+
// 142-S2.5 中心侧同步 API 的执行内核(设计 docs/design/142-S4-DATAPLANE.md §2.5;裁定:
|
|
2
|
+
// **plan 随数据走,core 零运行时半场**——core 的 `reconcileMemoryEntries`/`nextSyncBaseline`/
|
|
3
|
+
// `screenInboundEntries` 是纯函数导出,持数据的一侧(本 server=DB 权威+per-(scope,peer) 游标)直接
|
|
4
|
+
// import 调用算 plan 并执行 CAS;API 面全在 server,core 的承诺=纯函数语义稳定。
|
|
5
|
+
//
|
|
6
|
+
// 协议(POST /v1/memory/sync/:scope,http/server.ts 持路由/鉴权/验型;本模块只吃已验型请求):
|
|
7
|
+
// 请求 = { peer, baseRevs, entries[], deletes[] } —— TOC 本地引擎按**自己的**游标把 push 半场打过来:
|
|
8
|
+
// entries = 自 baseRevs 以来本地新增/变更的条目全量;deletes = 本地删除(tombstone)的 id
|
|
9
|
+
// (CAS 基线 = baseRevs[id],所以 deletes ⊆ baseRevs 键——验型层已保证)。
|
|
10
|
+
// 响应 = { applied[], conflicts[], serverEntries[], serverDeletes[], cursor } —— 一个 RTT 双向:
|
|
11
|
+
// serverEntries/serverDeletes = 中心侧自 baseRevs 以来变过/删过的条目 = 本地的 pull 半场。
|
|
12
|
+
//
|
|
13
|
+
// 与 §2.5 草案的两处**诚实偏离**(按 core JSDoc 实况,不硬凑草案):
|
|
14
|
+
// ① 响应加 `serverDeletes[]`:core MemorySyncPlan.deleteRemote—— 没有删除传播腿,
|
|
15
|
+
// 中心侧删除永远过不去、每轮重摆同一状态 = livelock;草案响应形状缺这条腿。
|
|
16
|
+
// ② 响应加 `cursor`(本轮落库的 per-(scope,peer) 新基线):客户端应用完 pull 半场后持久化为
|
|
17
|
+
// 自己的游标——它自己算不出(不持有中心全集)。
|
|
18
|
+
//
|
|
19
|
+
// 游标推进纪律(nextSyncBaseline 的 JSDoc 假设「POST-round 双方都已应用」,但响应发出时客户端还
|
|
20
|
+
// **没有**应用 pull 半场——直接乐观推进会在客户端应用失败时把它的旧条目误判为「客户端改过」而回灌
|
|
21
|
+
// 中心 = 数据回退):对 pull 半场(plan.push/plan.deleteRemote)的 id **保留旧基线**。两种客户端结局
|
|
22
|
+
// 都收敛且零回退:客户端应用了 ⇒ 下轮 identical revs → no-op+基线推进;没应用 ⇒ 下轮干净重推。
|
|
23
|
+
//
|
|
24
|
+
// 执行序(任务书①-⑤):
|
|
25
|
+
// ① screenInboundEntries 入站门(拒 = 该条入 conflicts 上报,不落库不入队——门拒是终态)+
|
|
26
|
+
// rev 诚实校验(rev = core computeEntryRev 的内容哈希契约;谎报的 rev 会破坏 identical-revs
|
|
27
|
+
// 收敛判定,按条拒入 conflicts,批内其余照常——applyPatches 的 per-patch 非致命姿势);
|
|
28
|
+
// ② 过门条目按 baseRevs[id] CAS applyPatches(基线有 ⇒ update+baseRev;基线无 ⇒ add——core
|
|
29
|
+
// MemorySyncPlan JSDoc 的 CAS 纪律原文:absent from the baseline ⇒ plain add);
|
|
30
|
+
// ③ deletes 同 CAS(plan.deleteLocal 的 {id, baseRev} → delete patch);
|
|
31
|
+
// ④ reconcileMemoryEntries(baseRevs, 中心集, 对端视图) 算双向 plan(对端视图 = push 条目 +
|
|
32
|
+
// 「基线未提及 id 钉在基线 rev」的合成 stub——stub 永远不会被 pull/delete 判定选中,只参与
|
|
33
|
+
// rev 对比);⑤ nextSyncBaseline + 保留纪律 → putCursor。
|
|
34
|
+
//
|
|
35
|
+
// putCursor 失败于 applyPatches 之后 = 补丁已落、游标陈旧:向上抛(路由 500),客户端按同一
|
|
36
|
+
// baseRevs 重放即幂等自愈(identical revs 全程 no-op)——游标写不是本轮正确性的一部分。
|
|
1
37
|
import { computeEntryRev, nextSyncBaseline, reconcileMemoryEntries, screenInboundEntries, } from "@sema-agent/core";
|
|
2
38
|
import { exportMemoryScope } from "./memory-export.js";
|
|
39
|
+
// ── 验型(HTTP 面的 422 判据;返回 error 字符串而非 throw——validateUserSkills 姿势) ──────────
|
|
40
|
+
/** 一轮 push 的条目数上限 = core REMOTE_HARVEST_MAX_FILES 同款口径(一个 scope 的文件面上限 500;
|
|
41
|
+
* 同步一轮打满全集也在此内)。deletes 上限同基数放宽(全集删除也要能一轮表达)。 */
|
|
3
42
|
export const MEMORY_SYNC_MAX_ENTRIES = 500;
|
|
4
43
|
export const MEMORY_SYNC_MAX_DELETES = 2000;
|
|
44
|
+
/** Shape-validate + NORMALIZE the request body (picked-not-spread:只挑认识的字段重建,body 上的
|
|
45
|
+
* 多余键绝不透传进数据面)。`scope` = 路径上已过 owner 门的 scope——每个条目的 scope 必须逐字
|
|
46
|
+
* 等于它(否则一个 owner-gated 路由就成了跨租户写门)。 */
|
|
5
47
|
export function parseMemorySyncRequest(body, scope) {
|
|
6
48
|
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
7
49
|
return { ok: false, error: "body must be a JSON object { peer, baseRevs, entries, deletes }" };
|
|
@@ -104,12 +146,21 @@ export function parseMemorySyncRequest(body, scope) {
|
|
|
104
146
|
}
|
|
105
147
|
return { ok: true, value: { peer, baseRevs, entries, deletes, ...(pull !== undefined ? { pull } : {}) } };
|
|
106
148
|
}
|
|
149
|
+
// ── 执行内核 ─────────────────────────────────────────────────────────────────────────────────
|
|
150
|
+
/** 基线 stub:对端在基线上、本轮未提及(或被门拒钉回基线)的 id 的合成占位。只有 id/rev 参与
|
|
151
|
+
* reconcile 判定;rev === baseRevs[id] ⇒ remoteChanged 恒 false ⇒ 永不被 pull/deleteLocal 选中,
|
|
152
|
+
* 身体永不落任何盘。 */
|
|
107
153
|
function baselineStub(id, rev, scope, slug) {
|
|
108
154
|
return { id, rev, scope, slug: slug ?? `sync-baseline-stub/${id}`, frontmatter: {}, body: "" };
|
|
109
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* One full sync round for one (scope, peer). `backend` = 中心侧 entry plane(DB 权威),`cursors` =
|
|
158
|
+
* per-(scope,peer) 游标面(sync_cursors)。纯数据参数进(路由已完成鉴权/owner 门/验型),响应形状出。
|
|
159
|
+
*/
|
|
110
160
|
export async function performMemorySync(backend, cursors, scope, req, now = Date.now) {
|
|
111
161
|
const conflicts = [];
|
|
112
|
-
|
|
162
|
+
// ① 入站门 + rev 诚实校验(拒 = 终态:上报 conflicts,不落库不入队;per-entry 非致命,批内其余照常)。
|
|
163
|
+
const rejected = new Map(); // id → reason
|
|
113
164
|
for (const e of req.entries) {
|
|
114
165
|
const computed = computeEntryRev(e);
|
|
115
166
|
if (computed !== e.rev)
|
|
@@ -125,16 +176,23 @@ export async function performMemorySync(backend, cursors, scope, req, now = Date
|
|
|
125
176
|
conflicts.push({ id, reason, ...(base !== undefined ? { baseRev: base } : {}) });
|
|
126
177
|
}
|
|
127
178
|
const clean = req.entries.filter((e) => !rejected.has(e.id));
|
|
179
|
+
// 中心侧全集(export 面同款读姿势:listHeaders → getByIds → scope 过滤纵深)。
|
|
128
180
|
const central = await exportMemoryScope(backend, scope);
|
|
129
181
|
const centralById = new Map(central.map((e) => [e.id, e]));
|
|
182
|
+
// 对端视图:push 条目 + 基线 stub。门拒的 id 钉回基线(有基线时)——绝不能让「拒收」被误判成
|
|
183
|
+
// 「对端删除」而触发 deleteLocal(中心副本会被误删);新条目被拒 = 视图里干脆没有它。
|
|
130
184
|
const peerView = [...clean];
|
|
131
185
|
const pushedOrDeleted = new Set([...clean.map((e) => e.id), ...req.deletes]);
|
|
132
186
|
for (const [id, rev] of Object.entries(req.baseRevs)) {
|
|
133
187
|
if (pushedOrDeleted.has(id))
|
|
134
188
|
continue;
|
|
189
|
+
// 未提及 = 对端仍在基线(含被门拒钉回的);stub 只有 rev 参与判定。
|
|
135
190
|
peerView.push(baselineStub(id, rev, scope, centralById.get(id)?.slug));
|
|
136
191
|
}
|
|
192
|
+
// ④(判定先行)三方 reconcile:local = 中心,remote = 对端视图。
|
|
137
193
|
const plan = reconcileMemoryEntries(req.baseRevs, central, peerView);
|
|
194
|
+
// ②③ 中心半场执行:pull(采纳对端 push)按 baseRevs CAS;deleteLocal 同 CAS。backend.applyPatches
|
|
195
|
+
// 的 per-id CAS 是并发纵深——本函数读集与落库之间挤进来的写者会让 baseRev 失配 = 冲突上报,绝不盲写。
|
|
138
196
|
const patches = [
|
|
139
197
|
...plan.pull.map((e) => {
|
|
140
198
|
const base = req.baseRevs[e.id];
|
|
@@ -146,6 +204,8 @@ export async function performMemorySync(backend, cursors, scope, req, now = Date
|
|
|
146
204
|
for (const c of report.conflicts) {
|
|
147
205
|
conflicts.push({ id: c.id, reason: c.reason, ...(c.baseRev !== undefined ? { baseRev: c.baseRev } : {}), ...(c.currentRev !== undefined ? { currentRev: c.currentRev } : {}) });
|
|
148
206
|
}
|
|
207
|
+
// plan 冲突(双边自基线各自变过 / 删改相撞):currentRev = 中心当前 rev(中心已删则缺席),
|
|
208
|
+
// 客户端拿它走 §3 ladder(败者铸 sibling)。
|
|
149
209
|
for (const c of plan.conflicts) {
|
|
150
210
|
conflicts.push({
|
|
151
211
|
id: c.id,
|
|
@@ -158,6 +218,7 @@ export async function performMemorySync(backend, cursors, scope, req, now = Date
|
|
|
158
218
|
...(c.local !== undefined ? { currentRev: c.local.rev } : {}),
|
|
159
219
|
});
|
|
160
220
|
}
|
|
221
|
+
// ⑤ 游标:POST-round 中心集(内存推演,只按 applied 口径——CAS 输掉的补丁不算)× 对端视图。
|
|
161
222
|
const appliedByKey = new Set(report.applied.map((a) => `${a.op}\x1f${a.id}`));
|
|
162
223
|
const appliedPatch = new Map();
|
|
163
224
|
for (const p of patches)
|
|
@@ -174,6 +235,9 @@ export async function performMemorySync(backend, cursors, scope, req, now = Date
|
|
|
174
235
|
centralPost.push(p.entry);
|
|
175
236
|
}
|
|
176
237
|
const nextBase = nextSyncBaseline(centralPost, peerView);
|
|
238
|
+
// 保留纪律(头注):pull 半场的 id 保留旧基线——客户端此刻还没应用 serverEntries/serverDeletes,
|
|
239
|
+
// 乐观推进会在「客户端没应用」的下一轮把它的旧条目误判成新改动回灌中心(数据回退)。保留旧基线
|
|
240
|
+
// 两种结局都收敛:应用了 ⇒ identical revs no-op+推进;没应用 ⇒ 干净重推/重删。
|
|
177
241
|
for (const e of plan.push) {
|
|
178
242
|
const base = req.baseRevs[e.id];
|
|
179
243
|
if (base !== undefined)
|
|
@@ -181,6 +245,11 @@ export async function performMemorySync(backend, cursors, scope, req, now = Date
|
|
|
181
245
|
}
|
|
182
246
|
for (const d of plan.deleteRemote)
|
|
183
247
|
nextBase[d.id] = d.baseRev;
|
|
248
|
+
// ⑥ S2.5 pull 分批(契约 settled 2026-07-14):serverEntries 稳定序(id 升序)截 limit;deletes 轻不截。
|
|
249
|
+
// cursor 精确化约束(core 回执):**不得预填未交付条目的 rev**——有基线的 pull id 上面的保留纪律已经
|
|
250
|
+
// 钉回旧值;无基线的新条目若未交付,必须从 nextBase 整个剔除(预填=客户端应用交付子集后持久化整张
|
|
251
|
+
// cursor,下轮把未交付 id 误判「baseline 已知」⇒ 该条目永久漏拉)。已交付的新条目保持 nextSyncBaseline
|
|
252
|
+
// 值(客户端按纪律应用完交付集才持久化 cursor,安全)。
|
|
184
253
|
let serverEntries = plan.push;
|
|
185
254
|
let pullTruncated = false;
|
|
186
255
|
if (req.pull !== undefined && plan.push.length > req.pull.limit) {
|
package/dist/model-select.d.ts
CHANGED
|
@@ -1,9 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the model ref for a task spec from the request (CLI `/model` picker + `run --model`).
|
|
3
|
+
*
|
|
4
|
+
* Priority (a deliberate selection beats incidental free text):
|
|
5
|
+
* 1) an explicit, allow-listed `body.model` (the picker / `--model <ref>` flag),
|
|
6
|
+
* 2) an inline `@name` mention in the objective (core's `parseModelMention`),
|
|
7
|
+
* 3) the `default` role.
|
|
8
|
+
*
|
|
9
|
+
* Security: BOTH the explicit field and the @mention are gated by the SAME catalog (`config.models` keys), so
|
|
10
|
+
* untrusted body/text can pick WHICH configured model but can never inject a baseUrl/apiKey (parseModelMention
|
|
11
|
+
* only ever returns an allow-listed catalog name).
|
|
12
|
+
*
|
|
13
|
+
* [865]②(clay 生产实锤:onboard 选 kimi 实跑 Qwen):
|
|
14
|
+
* - explicit ref 走 name+id 双键索引({@link matchCatalogModel})——壳 boot 回读的 mainLoopModel 是 **id 形**,
|
|
15
|
+
* 目录键是 **name 形**,单键索引把 id 形请求当「未知」静默落 default = session 中途静默换模型(最恶性的
|
|
16
|
+
* 上下文污染路径)。
|
|
17
|
+
* - 真未知不再无声:FRESH submit 在 HTTP 门 400 fail-loud(带 available 列表,http/server.ts);本函数保持
|
|
18
|
+
* 不 throw(RESUME 重放持久化 body 不过 400 门——模型可能事后被移出目录,砖死 resume 比降级更糟),但把
|
|
19
|
+
* 未知 ref 透出给调用方(`unknownExplicit`),resolveSpec 记 warn——降级永远可见,绝不静默。
|
|
20
|
+
*
|
|
21
|
+
* Returns the chosen model ref AND the objective with any `@mention` stripped (parseModelMention's cleanedText).
|
|
22
|
+
*
|
|
23
|
+
* 🔴 Was a real defect: resolveSpec previously read ONLY the inline @mention, so `body.model` (the picker + the
|
|
24
|
+
* `--model` flag) was SILENTLY DROPPED — the picker UX was a no-op server-side. This restores it.
|
|
25
|
+
*/
|
|
1
26
|
export declare function resolveTaskModel(bodyModel: unknown, objective: string, catalog: Record<string, unknown>): {
|
|
2
27
|
model: string;
|
|
3
28
|
cleanedObjective: string;
|
|
4
29
|
unknownExplicit?: string;
|
|
5
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* [865]② name+id 双键目录索引:返回 ref 命中的目录 **name 键**(spec.model 的规范形),未知 → undefined。
|
|
33
|
+
* - name 命中用 Object.hasOwn(🔴 不用真值索引:Object.prototype 继承键 "constructor"/"__proto__" 等在裸
|
|
34
|
+
* 索引下是真值,会绕过 allow-list——沿袭原实现的纪律)。
|
|
35
|
+
* - id 命中扫目录值(`Model.id`),跳过 "default" 别名键(它与其指向的真身共享 id,解析到别名会让 /model
|
|
36
|
+
* 面板与实际路由再度撕裂);同 id 多 name 时取目录序第一个(与 /v1/models 列表序一致,确定性)。
|
|
37
|
+
*/
|
|
6
38
|
export declare function matchCatalogModel(ref: string, catalog: Record<string, unknown>): string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* vision precheck: a catalog model can read images iff its `input` modality list
|
|
41
|
+
* includes `"image"` (the SAME test as the vision capability on GET /v1/models — `server.ts`). FALSE-SAFE on
|
|
42
|
+
* missing/unknown modality info: returns `true` (do NOT block) — only an EXPLICIT text-only `input` triggers the
|
|
43
|
+
* precheck, so a model that never declared its modalities is never wrongly 422'd. Lets a request with images 422
|
|
44
|
+
* up-front instead of hitting the downstream gateway as an opaque deserialize 400 on a text-only model.
|
|
45
|
+
*/
|
|
7
46
|
export declare function modelSupportsImages(model: {
|
|
8
47
|
input?: unknown;
|
|
9
48
|
} | undefined): boolean;
|