@sema-agent/server 7.132.0 → 7.133.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +266 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +174 -55
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +79 -19
- package/dist/approval-card.js +44 -13
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +6 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -0
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +5 -6
- package/dist/boot/stores.js +2 -2
- package/dist/boot/web-admin.d.ts +4 -0
- package/dist/boot/web-admin.js +151 -63
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/caller-text-echo.d.ts +9 -6
- package/dist/caller-text-echo.js +8 -11
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +27 -4
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +103 -60
- package/dist/http/approval-sweeps.js +55 -18
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +16 -16
- package/dist/http/checkpoint-ctx.js +13 -10
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +10 -4
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +34 -10
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +48 -23
- package/dist/http/principal-gate.js +39 -12
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/request-guards.d.ts +16 -23
- package/dist/http/request-guards.js +30 -15
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +3 -4
- package/dist/http/resume-legs.js +126 -69
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +5 -1
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +33 -106
- package/dist/http/routes/session-sync.js +15 -28
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +50 -14
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +17 -18
- package/dist/http/server.js +15 -13
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.js +4 -3
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +10 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/mcp-tool-faces.js +1 -3
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +3 -17
- package/dist/observability/prompt-manifest.js +45 -42
- package/dist/observability/tool-trace.js +9 -9
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
- package/dist/plugins/checkpoint-store-sql.js +20 -2
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +6 -1
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +110 -5
- package/dist/plugins/one-time-migrations.js +320 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +29 -6
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +28 -4
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +36 -6
- package/dist/runs.d.ts +10 -9
- package/dist/runs.js +21 -3
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +7 -66
- package/dist/task-settings.d.ts +89 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +303 -87
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +104 -22
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +3 -2
- package/dist/trace/project.d.ts +80 -12
- package/dist/trace/project.js +41 -28
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +298 -2
- package/dist/trace/wire-projection-faces.js +154 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +4 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +7 -3
|
@@ -20,29 +20,43 @@ export declare function createMemorySyncTransport(opts: {
|
|
|
20
20
|
timeoutMs?: number;
|
|
21
21
|
fetchImpl?: typeof fetch;
|
|
22
22
|
}): MemorySyncTransport;
|
|
23
|
-
/** cursor 文件路径:`memoryRoot`(= RunnerDeps.memoryEngineDir 的 resolved config root,memory/
|
|
24
|
-
*
|
|
25
|
-
|
|
23
|
+
/** cursor 文件路径:`memoryRoot`(= RunnerDeps.memoryEngineDir 的 resolved config root,memory/ 目录旁)下的
|
|
24
|
+
* per-(peer, scope) sidecar(`sync-cursors/<peer>/<scope 摘要>.json`)。peer 段走 core encodeScopeSegment(文件名安全字符纪律与 scope 目录同);scope 段取 sha256 前 32 hex
|
|
25
|
+
* (scope 键带 `:` `/` 且可长过段编码的 64 字符帽 —— 名字只需区分,内容里仍记原 scope,读时比对)。 */
|
|
26
|
+
export declare function memorySyncCursorPath(memoryRoot: string, peer: string, scope: string): string;
|
|
27
|
+
/** 一轮里一层的结果。 */
|
|
28
|
+
export interface MemorySyncLayerResult {
|
|
29
|
+
readonly scope: string;
|
|
30
|
+
readonly result: MemorySyncClientResult;
|
|
31
|
+
}
|
|
32
|
+
/** 一轮(按层)的结果:成功的各层,按同步序(同步层在前,项目层按键序)。 */
|
|
33
|
+
export interface MemorySyncRound {
|
|
34
|
+
readonly layers: readonly MemorySyncLayerResult[];
|
|
35
|
+
}
|
|
26
36
|
export interface MemorySyncRunner {
|
|
27
|
-
/** 一轮同步(串行:排在上一轮之后)
|
|
28
|
-
*
|
|
29
|
-
syncOnce(reason: string): Promise<
|
|
37
|
+
/** 一轮同步(串行:排在上一轮之后),逐层一轮。任一层 transport/协议错误 ⇒ 其余层照跑,轮末汇总 reject(失败层本地零副作用,
|
|
38
|
+
* core 契约);cursor 读写、conflicts warn 都在层内完成。 */
|
|
39
|
+
syncOnce(reason: string): Promise<MemorySyncRound>;
|
|
30
40
|
/** fire-and-forget 一轮:上一轮在飞(排队/执行中)则跳过(inflight 节流);失败 warn 不上抛。 */
|
|
31
41
|
trigger(reason: string): void;
|
|
32
|
-
/**
|
|
33
|
-
|
|
42
|
+
/** 跟踪一只本层属主的项目层(本地还没有条目也每轮拉它);首次跟踪即排一轮。不是本同步腿覆盖的项目层 ⇒ 抛(调用方的错)。 */
|
|
43
|
+
track(scope: string): void;
|
|
44
|
+
/** 把一段动本地记忆面的工作排进同步的串行链(等在飞的轮落定、执行时没有轮在飞)—— 项目层折叠用(`memory-project-layer.ts`)。 */
|
|
45
|
+
exclusive<T>(work: () => Promise<T>): Promise<T>;
|
|
46
|
+
/** 某一层的 cursor sidecar 路径(boot 日志/测试可见性)。 */
|
|
47
|
+
cursorPathFor(scope: string): string;
|
|
34
48
|
/** 排队+在飞的轮数(测试的确定性等待面;0 = 完全空闲)。 */
|
|
35
49
|
pending(): number;
|
|
36
50
|
}
|
|
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
51
|
/** S2.5 分批 loop 的轮数上限(fail-loud 警戒,防协议异常时死循环;正常收敛远低于此)。 */
|
|
43
52
|
export declare const MAX_SYNC_ROUNDS = 32;
|
|
53
|
+
/**
|
|
54
|
+
* 组装同步执行器:同步层 `scope` + 同属主的项目层,逐层一轮(cursor 持久化 + core `syncMemoryScope` + conflicts 上报),串行化/节流。
|
|
55
|
+
* `backend` = 本地 File authority plane(memoryEngineBackendFor 的产物);`memoryRoot` = resolved config root(cursor sidecar 落在 memory/ 目录旁)。
|
|
56
|
+
*/
|
|
44
57
|
export declare function createMemorySyncRunner(opts: {
|
|
45
58
|
backend: MemoryBackend;
|
|
59
|
+
/** 同步层(`config.memorySync.scope`);它同属主的项目层随它一起同步。 */
|
|
46
60
|
scope: string;
|
|
47
61
|
memoryRoot: string;
|
|
48
62
|
transport: MemorySyncTransport;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { encodeScopeSegment, syncMemoryScope, } from "@sema-agent/core";
|
|
5
|
+
import { replicationCovers } from "./memory-scope.js";
|
|
6
|
+
import { parseProjectLayerKey } from "./project-layer-key.js";
|
|
5
7
|
export const DEFAULT_MEMORY_SYNC_PEER = "central";
|
|
6
8
|
export function createMemorySyncTransport(opts) {
|
|
7
9
|
const base = opts.url.replace(/\/+$/, "");
|
|
@@ -20,7 +22,10 @@ export function createMemorySyncTransport(opts) {
|
|
|
20
22
|
return JSON.parse(text);
|
|
21
23
|
};
|
|
22
24
|
}
|
|
23
|
-
export function memorySyncCursorPath(memoryRoot, peer) {
|
|
25
|
+
export function memorySyncCursorPath(memoryRoot, peer, scope) {
|
|
26
|
+
return join(memoryRoot, "sync-cursors", encodeScopeSegment(peer), `${createHash("sha256").update(scope, "utf8").digest("hex").slice(0, 32)}.json`);
|
|
27
|
+
}
|
|
28
|
+
function legacyMemorySyncCursorPath(memoryRoot, peer) {
|
|
24
29
|
return join(memoryRoot, `sync-cursor-${encodeScopeSegment(peer)}.json`);
|
|
25
30
|
}
|
|
26
31
|
async function loadCursor(path, scope, peer, log) {
|
|
@@ -41,6 +46,13 @@ async function loadCursor(path, scope, peer, log) {
|
|
|
41
46
|
log.warn("memory_sync_cursor_corrupt", { path, err: String(err), note: "treating as first round" });
|
|
42
47
|
return undefined;
|
|
43
48
|
}
|
|
49
|
+
const cursor = cursorOf(parsed, scope, peer);
|
|
50
|
+
if (cursor !== undefined)
|
|
51
|
+
return cursor;
|
|
52
|
+
log.warn("memory_sync_cursor_invalid", { path, scope, peer, note: "shape/identity mismatch — treating as first round" });
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
function cursorOf(parsed, scope, peer) {
|
|
44
56
|
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
45
57
|
const c = parsed;
|
|
46
58
|
const baseRevsRaw = c["baseRevs"];
|
|
@@ -55,9 +67,34 @@ async function loadCursor(path, scope, peer, log) {
|
|
|
55
67
|
return { scope, peer, baseRevs: { ...baseRevsRaw }, updatedAtMs: c["updatedAtMs"] };
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
|
-
log.warn("memory_sync_cursor_invalid", { path, scope, peer, note: "shape/identity mismatch — treating as first round" });
|
|
59
70
|
return undefined;
|
|
60
71
|
}
|
|
72
|
+
async function adoptLegacyCursor(memoryRoot, scope, peer, log) {
|
|
73
|
+
const target = memorySyncCursorPath(memoryRoot, peer, scope);
|
|
74
|
+
const legacy = legacyMemorySyncCursorPath(memoryRoot, peer);
|
|
75
|
+
const facts = await Promise.all([readFile(target, "utf8").then(() => "present", (err) => (err.code === "ENOENT" ? "absent" : "present")), readFile(legacy, "utf8").then((text) => ({ text }), (err) => ({ err }))]);
|
|
76
|
+
const [targetFact, legacyRead] = facts;
|
|
77
|
+
if (targetFact === "present")
|
|
78
|
+
return;
|
|
79
|
+
if ("err" in legacyRead) {
|
|
80
|
+
if (legacyRead.err.code !== "ENOENT")
|
|
81
|
+
log.warn("memory_sync_cursor_read_failed", { path: legacy, err: String(legacyRead.err), note: "legacy cursor not adopted — this layer starts from its own cursor" });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = JSON.parse(legacyRead.text);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
log.warn("memory_sync_cursor_corrupt", { path: legacy, err: String(err), note: "legacy cursor not adopted" });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (cursorOf(parsed, scope, peer) === undefined)
|
|
93
|
+
return;
|
|
94
|
+
await mkdir(dirname(target), { recursive: true });
|
|
95
|
+
await rename(legacy, target);
|
|
96
|
+
log.info("memory_sync_cursor_adopted", { from: legacy, to: target, scope, peer });
|
|
97
|
+
}
|
|
61
98
|
async function saveCursor(path, cursor) {
|
|
62
99
|
await mkdir(dirname(path), { recursive: true });
|
|
63
100
|
const tmp = `${path}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
@@ -65,18 +102,36 @@ async function saveCursor(path, cursor) {
|
|
|
65
102
|
await rename(tmp, path);
|
|
66
103
|
}
|
|
67
104
|
export const MAX_SYNC_ROUNDS = 32;
|
|
105
|
+
function enumerateScopes(backend) {
|
|
106
|
+
const face = backend.listScopes;
|
|
107
|
+
return typeof face === "function" ? face.call(backend) : { supported: false, reason: "the memory backend has no listScopes face" };
|
|
108
|
+
}
|
|
68
109
|
export function createMemorySyncRunner(opts) {
|
|
69
110
|
const peer = opts.peer ?? DEFAULT_MEMORY_SYNC_PEER;
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
111
|
+
const coverage = { kind: "layers", layers: [opts.scope] };
|
|
112
|
+
const tracked = new Set();
|
|
113
|
+
let legacyCursorChecked = false;
|
|
114
|
+
let enumerationWarned = false;
|
|
115
|
+
const isCoveredProjectLayer = (scope) => scope !== opts.scope && parseProjectLayerKey(scope) !== undefined && replicationCovers(coverage, scope);
|
|
116
|
+
const layersOfRound = () => {
|
|
117
|
+
const local = enumerateScopes(opts.backend);
|
|
118
|
+
if (!local.supported && !enumerationWarned) {
|
|
119
|
+
enumerationWarned = true;
|
|
120
|
+
opts.log.warn("memory_sync_layer_enumeration_unsupported", { scope: opts.scope, peer, reason: local.reason, note: "only the sync layer and tracked project layers are synced" });
|
|
121
|
+
}
|
|
122
|
+
const projectLayers = new Set([...(local.supported ? local.scopes : []), ...tracked].filter(isCoveredProjectLayer));
|
|
123
|
+
return [opts.scope, ...[...projectLayers].sort()];
|
|
124
|
+
};
|
|
125
|
+
const syncLayer = async (scope, reason) => {
|
|
126
|
+
const cursorPath = memorySyncCursorPath(opts.memoryRoot, peer, scope);
|
|
127
|
+
let cursor = await loadCursor(cursorPath, scope, peer, opts.log);
|
|
73
128
|
let result;
|
|
74
129
|
let subRound = 0;
|
|
75
130
|
for (;;) {
|
|
76
131
|
subRound += 1;
|
|
77
132
|
result = await syncMemoryScope({
|
|
78
133
|
backend: opts.backend,
|
|
79
|
-
scope
|
|
134
|
+
scope,
|
|
80
135
|
transport: opts.transport,
|
|
81
136
|
peer,
|
|
82
137
|
...(cursor !== undefined ? { cursor } : {}),
|
|
@@ -85,11 +140,11 @@ export function createMemorySyncRunner(opts) {
|
|
|
85
140
|
...(opts.maxPullEntries !== undefined ? { maxPullEntries: opts.maxPullEntries } : {}),
|
|
86
141
|
});
|
|
87
142
|
for (const w of result.warnings ?? [])
|
|
88
|
-
opts.log.warn("memory_sync_warning", { scope
|
|
143
|
+
opts.log.warn("memory_sync_warning", { scope, peer, subRound, warning: w });
|
|
89
144
|
if (!(result.pushTruncated === true || result.pullTruncated === true))
|
|
90
145
|
break;
|
|
91
146
|
if (subRound >= MAX_SYNC_ROUNDS) {
|
|
92
|
-
opts.log.warn("memory_sync_rounds_exhausted", { scope
|
|
147
|
+
opts.log.warn("memory_sync_rounds_exhausted", { scope, peer, rounds: subRound, note: "truncation flag still set at the round cap — remaining items ride the next trigger" });
|
|
93
148
|
break;
|
|
94
149
|
}
|
|
95
150
|
if (result.cursorAdvanced && result.cursor !== undefined) {
|
|
@@ -101,11 +156,11 @@ export function createMemorySyncRunner(opts) {
|
|
|
101
156
|
}
|
|
102
157
|
}
|
|
103
158
|
cursor = result.cursor ?? cursor;
|
|
104
|
-
opts.log.info("memory_sync_continuation", { reason, scope
|
|
159
|
+
opts.log.info("memory_sync_continuation", { reason, scope, peer, subRound, pushTruncated: result.pushTruncated === true, pullTruncated: result.pullTruncated === true });
|
|
105
160
|
}
|
|
106
161
|
for (const c of result.conflicts) {
|
|
107
162
|
opts.log.warn("memory_sync_conflict", {
|
|
108
|
-
scope
|
|
163
|
+
scope,
|
|
109
164
|
peer,
|
|
110
165
|
side: c.side,
|
|
111
166
|
id: c.id,
|
|
@@ -124,7 +179,7 @@ export function createMemorySyncRunner(opts) {
|
|
|
124
179
|
}
|
|
125
180
|
opts.log.info("memory_sync_round", {
|
|
126
181
|
reason,
|
|
127
|
-
scope
|
|
182
|
+
scope,
|
|
128
183
|
peer,
|
|
129
184
|
ok: result.ok,
|
|
130
185
|
cursorAdvanced: result.cursorAdvanced,
|
|
@@ -136,11 +191,32 @@ export function createMemorySyncRunner(opts) {
|
|
|
136
191
|
});
|
|
137
192
|
return result;
|
|
138
193
|
};
|
|
194
|
+
const round = async (reason) => {
|
|
195
|
+
if (!legacyCursorChecked) {
|
|
196
|
+
legacyCursorChecked = true;
|
|
197
|
+
await adoptLegacyCursor(opts.memoryRoot, opts.scope, peer, opts.log);
|
|
198
|
+
}
|
|
199
|
+
const layers = [];
|
|
200
|
+
const failures = [];
|
|
201
|
+
for (const scope of layersOfRound()) {
|
|
202
|
+
try {
|
|
203
|
+
layers.push({ scope, result: await syncLayer(scope, reason) });
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
failures.push({ scope, err });
|
|
207
|
+
opts.log.warn("memory_sync_layer_failed", { reason, scope, peer, err: String(err) });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (failures.length > 0) {
|
|
211
|
+
throw new Error(`memory sync round failed for ${failures.length} layer(s): ${failures.map((f) => `${f.scope}: ${f.err instanceof Error ? f.err.message : String(f.err)}`).join("; ")}`);
|
|
212
|
+
}
|
|
213
|
+
return { layers };
|
|
214
|
+
};
|
|
139
215
|
let chain = Promise.resolve();
|
|
140
216
|
let pending = 0;
|
|
141
|
-
const
|
|
217
|
+
const exclusive = (work) => {
|
|
142
218
|
pending += 1;
|
|
143
|
-
const run = chain.then(
|
|
219
|
+
const run = chain.then(work);
|
|
144
220
|
chain = run.then(() => {
|
|
145
221
|
pending -= 1;
|
|
146
222
|
}, () => {
|
|
@@ -148,13 +224,26 @@ export function createMemorySyncRunner(opts) {
|
|
|
148
224
|
});
|
|
149
225
|
return run;
|
|
150
226
|
};
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
return;
|
|
227
|
+
const syncOnce = (reason) => exclusive(() => round(reason));
|
|
228
|
+
const queueRound = (reason) => {
|
|
154
229
|
void syncOnce(reason).catch((err) => {
|
|
155
230
|
opts.log.warn("memory_sync_failed", { reason, scope: opts.scope, peer, err: String(err) });
|
|
156
231
|
});
|
|
157
232
|
};
|
|
158
|
-
|
|
233
|
+
const trigger = (reason) => {
|
|
234
|
+
if (pending > 0)
|
|
235
|
+
return;
|
|
236
|
+
queueRound(reason);
|
|
237
|
+
};
|
|
238
|
+
const track = (scope) => {
|
|
239
|
+
if (!isCoveredProjectLayer(scope)) {
|
|
240
|
+
throw new Error(`memory sync track(): ${JSON.stringify(scope)} is not a project layer of this sync leg (layer ${JSON.stringify(opts.scope)} replicates its own project layers only)`);
|
|
241
|
+
}
|
|
242
|
+
if (tracked.has(scope))
|
|
243
|
+
return;
|
|
244
|
+
tracked.add(scope);
|
|
245
|
+
queueRound("track");
|
|
246
|
+
};
|
|
247
|
+
return { syncOnce, trigger, track, exclusive, cursorPathFor: (scope) => memorySyncCursorPath(opts.memoryRoot, peer, scope), pending: () => pending };
|
|
159
248
|
}
|
|
160
249
|
//# sourceMappingURL=memory-sync-client.js.map
|
|
@@ -116,10 +116,18 @@ export declare function refusedNamesLogFields(key: string, names: readonly strin
|
|
|
116
116
|
export declare function refusalEventOf(reason: ModelEntryRefusalReason): "web_admin_model_no_brain" | "web_admin_model_entry_invalid";
|
|
117
117
|
/** warn 字段(不含值):`field` = 第一处坏字段(告警规则最常按它分组),`fields` = 全部。S-805:`model` 只在名可披露时写。 */
|
|
118
118
|
export declare function refusalWarnFields(name: string, r: ModelEntryRefusal): Record<string, unknown>;
|
|
119
|
+
/** 调用方写的模型 ref(`model` / `compactionModel` / `agents[i].model` / `@name`)回到人面前 —— 拒句与留声日志 —— 的字符上限。 */
|
|
120
|
+
export declare const MODEL_REF_ECHO_CHARS = 120;
|
|
121
|
+
/**
|
|
122
|
+
* 调用方写的模型 ref 的回显形:过回显的一只口径 {@link echoCallerText}(剥控制与双向字符,截到 {@link MODEL_REF_ECHO_CHARS} 字,超出加 `…`)。
|
|
123
|
+
* 目录门、`resolveSpec`、side-query 的拒句,以及它们写进运维日志的 `requested` 字段,**都**调这一只 —— 不在站点手写 `slice`。
|
|
124
|
+
*/
|
|
125
|
+
export declare function echoModelRef(ref: string): string;
|
|
119
126
|
/**
|
|
120
127
|
* 一次**显式选择**命中了不可用条目时的拒因句(HTTP `request.model_unavailable` 的 `error`、run-local 的 stderr、
|
|
121
128
|
* hook 选模型的失败文案 —— 各处同一句)。`field` = 调用方的通道名(`model` / `compactionModel` / `agents[0].model` /
|
|
122
|
-
* `@-mention`),`requested` =
|
|
129
|
+
* `@-mention`),`requested` = 调用方发来的**原形**(name 或 id;本函数回显它时过 {@link echoModelRef},调用方不预先截)。
|
|
130
|
+
* 别名段(`(catalog entry …)`)的判断读原形:ref 与条目名逐字相同 ⇒ 不带,不因回显截短而误判成「另有条目」。
|
|
123
131
|
*/
|
|
124
132
|
export declare function modelUnavailableMessage(field: string, requested: string, name: string, r: ModelEntryRefusal): string;
|
|
125
133
|
/** 缺省模型不变量读的切面(`ServiceConfig` 与 `CrossInvariantView` 都结构满足)。 */
|
|
@@ -3,6 +3,7 @@ import { ModelEntry, formatConfigPath, isReportableRefusalName } from "@sema-age
|
|
|
3
3
|
import { catalogBrainLane } from "./model-provider.js";
|
|
4
4
|
import { readCatalogEntryHeaders } from "./model-entry-headers.js";
|
|
5
5
|
import { DroppedCatalogEntryRow, describeSchemaIssueFields, describeSchemaIssues } from "./web-admin-client/read-warnings.js";
|
|
6
|
+
import { echoCallerText } from "./caller-text-echo.js";
|
|
6
7
|
import { DEFAULT_MODEL_REF } from "./model-select.js";
|
|
7
8
|
export const ENTRY_REFUSAL_REASON_OF = {
|
|
8
9
|
"config.model_no_brain": "no_brain",
|
|
@@ -132,9 +133,13 @@ export function refusalWarnFields(name, r) {
|
|
|
132
133
|
hint: r.detail,
|
|
133
134
|
};
|
|
134
135
|
}
|
|
136
|
+
export const MODEL_REF_ECHO_CHARS = 120;
|
|
137
|
+
export function echoModelRef(ref) {
|
|
138
|
+
return echoCallerText(ref, { maxChars: MODEL_REF_ECHO_CHARS });
|
|
139
|
+
}
|
|
135
140
|
export function modelUnavailableMessage(field, requested, name, r) {
|
|
136
141
|
const alias = requested === name ? "" : ` (catalog entry "${name}")`;
|
|
137
|
-
return `${field} "${requested}"${alias} is published in the catalog but unavailable on this deployment [${r.code}] — ${r.detail}`;
|
|
142
|
+
return `${field} "${echoModelRef(requested)}"${alias} is published in the catalog but unavailable on this deployment [${r.code}] — ${r.detail}`;
|
|
138
143
|
}
|
|
139
144
|
export function defaultModelRefusal(view, leg) {
|
|
140
145
|
if (Object.hasOwn(view.models, DEFAULT_MODEL_REF) && view.models[DEFAULT_MODEL_REF] !== undefined)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /v1/models` 顶层 `modelPlane` 的**唯一铸点** —— 壳问「这台引擎服务的是哪张模型表 / 目录采纳了没有 / 起服路由判官怎么说」读这一格,不自己预测。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么在 server 里答
|
|
5
|
+
* 判官的输入是服务进程的事实:采纳之后 `config.model` 是不是还是那只 env 模型(对象同一性)、anthropic 路由装没装(凭据在场性)、名册布防(env 表是占位)。
|
|
6
|
+
* 壳拼不出这些,只能镜像两道判(目录条目逐条合形、车道 / 端点可解析)—— 镜像会随时间与真判官漂开(同一问两份读法)。所以结论只有 server 说,壳读它。
|
|
7
|
+
*
|
|
8
|
+
* ## 四个字段,两根轴
|
|
9
|
+
* · `servedTable` —— **谁在服**:{@link servedModelTableLeg}(此刻服务 env 表还是目录表;同一只读法,不另记旗子)。
|
|
10
|
+
* · `catalog` —— **最近一份目录候选的结局**({@link CATALOG_STANCES}):
|
|
11
|
+
* `refused` —— 候选被整拒:候选判官整拒(`candidateRejectionState` 座),或模型面组拒(`modelRefusalsState().plane` 在场;各码见
|
|
12
|
+
* settings-schema `MODEL_PLANE_REFUSAL_CODES`)。没有 LKG 时服务的是 env 表,有 LKG(或上一代已采纳)时仍服目录表 —— 谁在服归 `servedTable` 答,
|
|
13
|
+
* 不在这一格里合并(合并 = 一个字段两个意思);逐条被拒(条目不可用,`entries`)不是整拒,那些条目之外的目录照服;
|
|
14
|
+
* `adopted` —— 没有整拒、且服务的是目录表;
|
|
15
|
+
* `absent` —— 没有整拒、且服务的是 env 表:没配目录源 / 配了但没有启用条目(候选不管模型面,不是拒)/ 纯 env 部署。
|
|
16
|
+
* 两个座(候选判官的结论座与模型面组拒的信号座)是候选在两道判官各自留下的事实,本格只读它们,不另算第二份。
|
|
17
|
+
* **不在内**:候选过了两道判官、却在装配期被引擎整份拒收(`applyEffective` 里引擎拒收 `apiKeyEnv` 声明 / Runner 拒收换装;活配置零触碰,只有日志与 `/health` 世代账的 target≠applied)——
|
|
18
|
+
* 这一形今天没有座,`catalog` 仍按上一代读;`adopted` 说的是「没有被判官整拒」,不是「最新候选已落地」(那一问归世代账)。要覆盖它得先给装配期拒收立一个座(另案设计)。
|
|
19
|
+
* · `refusalCode` / `gap` —— **起服路由判官对当前 config 的判决**:`judgeServedModelRoute` 同一只函数(装配第 2 段与 `run-local` 调的就是它),通过 ⇒ 两键缺席。
|
|
20
|
+
* 进程既然起来了,正常是缺席;测试夹具 / 自建装配 / 不拒启的入口可能在场 —— 如实投,不替它们编造通过。**不带句子**(拒因句只走日志与起服错误)。
|
|
21
|
+
*
|
|
22
|
+
* ## 只在起服后可答
|
|
23
|
+
* 读面挂在运行中的进程上;判官必须在目录应用之后调(`judgeServedModelRoute` 头注),起服前没有「将要服务的表」,所以没有起服前的预判口。
|
|
24
|
+
*/
|
|
25
|
+
import type { ModelRefusalsSignal } from "@sema-agent/settings-schema";
|
|
26
|
+
import { type ModelRouteEndpointVerdict, type ModelRouteGap, type ServedModelRouteView } from "./model-route-endpoint.js";
|
|
27
|
+
import { type ModelTableLeg } from "./model-select.js";
|
|
28
|
+
import type { CandidateRejection } from "./web-admin-client/candidate-gate.js";
|
|
29
|
+
/** `modelPlane.catalog` 的闭集(消费方用穷举 switch —— 加一词不补臂 ⇒ 编译红)。 */
|
|
30
|
+
export declare const CATALOG_STANCES: readonly ["absent", "adopted", "refused"];
|
|
31
|
+
export type CatalogStance = (typeof CATALOG_STANCES)[number];
|
|
32
|
+
/** `GET /v1/models.modelPlane` 的 wire 形(纯数据;条件键缺席,不铸 `null` / 空串)。 */
|
|
33
|
+
export interface ModelPlaneFace {
|
|
34
|
+
readonly servedTable: ModelTableLeg;
|
|
35
|
+
readonly catalog: CatalogStance;
|
|
36
|
+
/** 起服路由判官判决的机读码(`ModelPlaneRefusalCode` 的子集:路由端点族两码)。 */
|
|
37
|
+
readonly refusalCode?: ModelRouteEndpointVerdict["code"];
|
|
38
|
+
/** 同一次判决的出路轴(缺口两词)。 */
|
|
39
|
+
readonly gap?: ModelRouteGap;
|
|
40
|
+
}
|
|
41
|
+
/** {@link buildModelPlaneFace} 读的进程事实(都由调用方从各自的座取,本函数不碰任何全局)。 */
|
|
42
|
+
export interface ModelPlaneFacts {
|
|
43
|
+
/** 严格名册布防(`isRosterGateArmed`):env 表是占位、不被判(装配第 2 段传的是同一只谓词)。 */
|
|
44
|
+
readonly envTableIsPlaceholder: boolean;
|
|
45
|
+
/** 候选判官最近一次整拒的结论座(`WebAdminRuntime.candidateRejectionState()`);座空 / 没有配置管道 ⇒ `undefined`。 */
|
|
46
|
+
readonly candidateRejection: CandidateRejection | undefined;
|
|
47
|
+
/** 模型拒因信号(`WebAdminRuntime.modelRefusalsState()`);`plane` 在场 ⇒ 最近一份候选的模型面被整组拒。 */
|
|
48
|
+
readonly modelRefusals: Pick<ModelRefusalsSignal, "plane"> | undefined;
|
|
49
|
+
}
|
|
50
|
+
export declare function buildModelPlaneFace(config: ServedModelRouteView, facts: ModelPlaneFacts): ModelPlaneFace;
|
|
51
|
+
//# sourceMappingURL=model-plane-face.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { judgeServedModelRoute } from "./model-route-endpoint.js";
|
|
2
|
+
import { servedModelTableLeg } from "./model-select.js";
|
|
3
|
+
export const CATALOG_STANCES = ["absent", "adopted", "refused"];
|
|
4
|
+
function catalogStanceOf(served, wholeRefused) {
|
|
5
|
+
if (wholeRefused)
|
|
6
|
+
return "refused";
|
|
7
|
+
switch (served) {
|
|
8
|
+
case "catalog":
|
|
9
|
+
return "adopted";
|
|
10
|
+
case "env":
|
|
11
|
+
return "absent";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function buildModelPlaneFace(config, facts) {
|
|
15
|
+
const servedTable = servedModelTableLeg(config);
|
|
16
|
+
const wholeRefused = facts.candidateRejection !== undefined || facts.modelRefusals?.plane !== undefined;
|
|
17
|
+
const verdict = judgeServedModelRoute(config, { envTableIsPlaceholder: facts.envTableIsPlaceholder });
|
|
18
|
+
return {
|
|
19
|
+
servedTable,
|
|
20
|
+
catalog: catalogStanceOf(servedTable, wholeRefused),
|
|
21
|
+
...(verdict !== undefined ? { refusalCode: verdict.code, gap: verdict.gap } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=model-plane-face.js.map
|
package/dist/model-provider.d.ts
CHANGED
|
@@ -99,6 +99,11 @@ export declare function mountRoutes<R extends object, T>(view: {
|
|
|
99
99
|
export declare function anthropicRouteRoot(route: {
|
|
100
100
|
readonly baseUrl?: string | undefined;
|
|
101
101
|
}): string;
|
|
102
|
+
/**
|
|
103
|
+
* **请求根「算不算声明了」的唯一尺**:缺席、空串、纯空白都是没声明(core 原话 "nothing, an empty string and whitespace read as undeclared"),声明了就原样带回。
|
|
104
|
+
* anthropic 路由的请求根({@link anthropicRouteRoot})、openai 兼容路由的有效端点(`model-route-endpoint.ts` 的 `openaiRouteBaseUrl`)与 env 值级端口的 `endpointDeclared` 读同一只。
|
|
105
|
+
*/
|
|
106
|
+
export declare function declaredRootUrl(url: string | undefined): string | undefined;
|
|
102
107
|
/** 判词侧的路由表:值 = 路由自己的配置({@link mountRoutes} 的恒等铸法 —— 判官不读值,只问键)。 */
|
|
103
108
|
export declare function routeTableOf<R extends object>(view: {
|
|
104
109
|
readonly anthropic?: R | undefined;
|
package/dist/model-provider.js
CHANGED
|
@@ -29,8 +29,10 @@ export function mountRoutes(view, mount) {
|
|
|
29
29
|
return route !== undefined ? { anthropic: mount(route) } : {};
|
|
30
30
|
}
|
|
31
31
|
export function anthropicRouteRoot(route) {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
return declaredRootUrl(route.baseUrl) ?? ANTHROPIC_DEFAULT_BASE_URL;
|
|
33
|
+
}
|
|
34
|
+
export function declaredRootUrl(url) {
|
|
35
|
+
return url !== undefined && url.trim() !== "" ? url : undefined;
|
|
34
36
|
}
|
|
35
37
|
export function routeTableOf(view) {
|
|
36
38
|
return mountRoutes(view, (route) => route);
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* 经 {@link judgeServedModelRoute}:目录被采纳 ⇒ 判目录表(目录视图),目录缺席 / 被整拒 / 没有启用条目 ⇒ 判 env 表(env 视图);
|
|
21
21
|
* 严格名册布防(`isRosterGateArmed`)时 env 表是占位、从不被派发 ⇒ 不判它(备用网关那一条与表无关,照判)。
|
|
22
22
|
* 不在 `loadConfig()`:那是目录应用**之前**,env 表还不知道会不会服务(目录一旦采纳就整张换掉它);
|
|
23
|
-
* ·
|
|
24
|
-
*
|
|
23
|
+
* · 壳 / 包问「这台引擎服务哪张表、起服判官怎么说」读 `GET /v1/models` 的 `modelPlane`(`model-plane-face.ts`,同一只 {@link judgeServedModelRoute});
|
|
24
|
+
* 起服前没有「将要服务的表」可判,所以没有起服前的预判口;
|
|
25
25
|
* · 热路径:`web-admin-client/apply-effective.ts` 的模型面 stage ⇒ 模型面组拒(opus 腿 O3:同候选其余组照落)、上一代模型面继续服务(目录视图);
|
|
26
26
|
* · run-local:配置源解析完之后按真要派发的表判(`run-local.ts`)—— 本入口没有名册门,不豁免占位;
|
|
27
27
|
* · 登记:`config-invariants.ts` 的 `model-route-endpoint` 条(表的「不许有表外不变量」职责);
|
|
@@ -43,22 +43,19 @@ export declare const MODEL_ROUTE_ENDPOINT_MISSING_CODE = "config.model_route_end
|
|
|
43
43
|
/** 同族第二码:备用网关设了、主网关没设。与上一码分开是因为出路不同(补主网关 / 撤备用 vs 补主网关 / 给条目 baseUrl)。 */
|
|
44
44
|
export declare const GATEWAY_FALLBACK_WITHOUT_PRIMARY_CODE = "config.gateway_fallback_without_primary";
|
|
45
45
|
/**
|
|
46
|
-
* **路由缺口的出路轴**(
|
|
46
|
+
* **路由缺口的出路轴**(闭集;`GET /v1/models.modelPlane.gap` 的词,包根导出其型)。**只有缺口两词** —— 通过 = 判决为 `undefined`(没有第三个词可说「无缺口」)。
|
|
47
47
|
*
|
|
48
48
|
* 与上面的**码**是两根轴:码是组拒的机读词(`ModelPlaneRefusalCode`,settings-schema 属主),这里是**出路**:
|
|
49
49
|
* · `endpoint_missing` —— 缺的是网关端点:openai 兼容腿上的条目解析不到 base URL(或备用网关设了、主网关没设);
|
|
50
50
|
* 出路 = 设 `MODEL_GATEWAY_BASEURL`,或(目录视图)给条目自己的 `baseUrl` / (env 视图)挂 anthropic 路由、或不设 `MODEL_ID` 让目录缺省服务;
|
|
51
51
|
* · `lane_credential_missing` —— 缺的是**车道凭据**:条目的 provider 词是 `anthropic`(用户选的是 anthropic 车道),
|
|
52
52
|
* 却因 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` 都没有而没装上 anthropic 路由、落进了 openai 腿,那条腿又没有端点;
|
|
53
|
-
* 出路 = 补那两把钥匙之一(设网关是另一条出路,拒因句一并给)
|
|
54
|
-
* · `none` —— 这份配置能派发到的每一条 openai 兼容路由都解析得到端点。
|
|
53
|
+
* 出路 = 补那两把钥匙之一(设网关是另一条出路,拒因句一并给)。
|
|
55
54
|
*
|
|
56
|
-
* **声明序 =
|
|
55
|
+
* **声明序 = 语义序**;加一词 ⇒ 所有穷举 switch 当场编译红。
|
|
57
56
|
*/
|
|
58
|
-
export declare const MODEL_ROUTE_GAP_WORDS: readonly ["endpoint_missing", "lane_credential_missing"
|
|
57
|
+
export declare const MODEL_ROUTE_GAP_WORDS: readonly ["endpoint_missing", "lane_credential_missing"];
|
|
59
58
|
export type ModelRouteGap = (typeof MODEL_ROUTE_GAP_WORDS)[number];
|
|
60
|
-
/** 有缺口的那两词(判决的结构化形只在有缺口时存在,`none` = 判决为 `undefined`)。 */
|
|
61
|
-
export type ModelRouteGapBreach = Exclude<ModelRouteGap, "none">;
|
|
62
59
|
/**
|
|
63
60
|
* 拒因给出的**本机网关显式写法**。`src/` 里本机 8000 那个字面的**唯一**住处 —— 源码门钉在
|
|
64
61
|
* `test/config-gateway-endpoint-required.test.ts` ⑧(出现在别处 = 有人又在铸缺省)。
|
|
@@ -107,8 +104,8 @@ export declare function modelRouteEndpointRefusal(view: ModelRouteEndpointView,
|
|
|
107
104
|
/** S-768:部署级判决的结构化形 —— 码与拒因句由**同一次**判决给出(一个不变量 id 两个码,组拒码在判决那刻当数据带出,不从句子里抠)。 */
|
|
108
105
|
export interface ModelRouteEndpointVerdict {
|
|
109
106
|
readonly code: typeof GATEWAY_FALLBACK_WITHOUT_PRIMARY_CODE | typeof MODEL_ROUTE_ENDPOINT_MISSING_CODE;
|
|
110
|
-
/** 出路轴({@link MODEL_ROUTE_GAP_WORDS}
|
|
111
|
-
readonly gap:
|
|
107
|
+
/** 出路轴({@link MODEL_ROUTE_GAP_WORDS}):同一次判决给出,不从句子或码里反推(`lane_credential_missing` 与 `endpoint_missing` 共用一个码)。 */
|
|
108
|
+
readonly gap: ModelRouteGap;
|
|
112
109
|
readonly reason: string;
|
|
113
110
|
}
|
|
114
111
|
/**
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { brainLaneFor, catalogBrainLane, routeTableOf } from "./model-provider.js";
|
|
1
|
+
import { brainLaneFor, catalogBrainLane, declaredRootUrl, routeTableOf } from "./model-provider.js";
|
|
2
2
|
import { DEFAULT_MODEL_REF, servedModelTableLeg } from "./model-select.js";
|
|
3
3
|
export const MODEL_ROUTE_ENDPOINT_MISSING_CODE = "config.model_route_endpoint_missing";
|
|
4
4
|
export const GATEWAY_FALLBACK_WITHOUT_PRIMARY_CODE = "config.gateway_fallback_without_primary";
|
|
5
|
-
export const MODEL_ROUTE_GAP_WORDS = ["endpoint_missing", "lane_credential_missing"
|
|
5
|
+
export const MODEL_ROUTE_GAP_WORDS = ["endpoint_missing", "lane_credential_missing"];
|
|
6
6
|
export const LOCAL_GATEWAY_HINT = "MODEL_GATEWAY_BASEURL=http://127.0.0.1:8000/v1";
|
|
7
|
-
function declared(url) {
|
|
8
|
-
return url !== undefined && url.trim() !== "" ? url : undefined;
|
|
9
|
-
}
|
|
10
7
|
export function openaiRouteBaseUrl(routeBaseUrl, gatewayBaseUrl) {
|
|
11
|
-
return
|
|
8
|
+
return declaredRootUrl(routeBaseUrl) ?? declaredRootUrl(gatewayBaseUrl);
|
|
12
9
|
}
|
|
13
10
|
function unresolvedRouteLabel(name, provider) {
|
|
14
11
|
return catalogBrainLane(provider) === "anthropic"
|
|
@@ -23,7 +20,7 @@ export function modelRouteEndpointRefusal(view, leg) {
|
|
|
23
20
|
return judgeModelRouteEndpoint(view, leg)?.reason;
|
|
24
21
|
}
|
|
25
22
|
export function judgeModelRouteEndpoint(view, leg) {
|
|
26
|
-
const gateway =
|
|
23
|
+
const gateway = declaredRootUrl(view.gatewayBaseUrl);
|
|
27
24
|
if (gateway === undefined && view.gatewayFallbackUrls.length > 0) {
|
|
28
25
|
const reason = (`env MODEL_GATEWAY_FALLBACK_URLS is set but MODEL_GATEWAY_BASEURL is not [${GATEWAY_FALLBACK_WITHOUT_PRIMARY_CODE}] — ` +
|
|
29
26
|
"the fallback URLs are mirrors of the primary gateway (same provider, same account, same key scope), tried only " +
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@sema-agent/server/model-route-env` —— 模型路由 env 读法的**精选入口**(纯数据 + 纯函数;import 不写文件、不起句柄、不装监听器、不出声 —— 依赖的包在装载时读自己的环境变量不在此列)。
|
|
3
|
+
*
|
|
4
|
+
* 为什么有这只文件:引擎(core)是 BYOM —— 它只吃调用方交的路由表与 `baseUrl` / `apiKey`,从不读 `MODEL_*` / `ANTHROPIC_*` 这些 env 键。
|
|
5
|
+
* 「env 里哪几把键是模型路由、空串算不算设了、provider 怎么推断、这只模型走哪条车道、这条车道的端点 / 凭据取哪一对键」的读法属本服务,
|
|
6
|
+
* 在引擎起之前就要答这句话的调用方(壳首启、客户端运行时、sdk 转口)读这一只,不各抄一份键名与车道判。
|
|
7
|
+
*
|
|
8
|
+
* 为什么是子路径而不是包根:包根的依赖闭包是整台服务(存储、HTTP、沙箱……),这里只需要一张键表和几只纯函数;
|
|
9
|
+
* 值依赖仅 `@sema-agent/core`(车道判词)与 `@sema-agent/settings-schema`,仓内只有四只纯叶(`test/model-route-env-port.test.ts` 钉死)。
|
|
10
|
+
*
|
|
11
|
+
* 为什么是精选而不是把 `model-route-gap.ts` 整只暴露:那个模块里还有起服自己的读法助手(逗号串分词、cheap 槽铸 id)。把它们变成公开面,等于替实现细节背上 semver。
|
|
12
|
+
* 要加名字 = 改这只文件 + 同批改 `test/model-route-env-port.test.ts` 的闭集(新增公开面必须是一次有意的动作)。
|
|
13
|
+
*
|
|
14
|
+
* · `MODEL_ROUTE_ENV_KEYS` —— 九把路由 env 键的闭表(字段名 → 键名);
|
|
15
|
+
* · `readModelRouteEnv(env)` —— 读口:`env` 交整张 `Record<string, string | undefined>`(`process.env` 或等价快照),只按表点名取值;
|
|
16
|
+
* · `envLaneTable(mainId, main, cheap)` —— env 腿的条目表(别名 `default` + 主槽 id + cheap 槽 id);
|
|
17
|
+
* · `laneAndEndpointFor(env, model, routes)` —— 值级端口:车道 + 端点 / 凭据的键名(不含任何 env 值)。
|
|
18
|
+
*/
|
|
19
|
+
export { MODEL_ROUTE_ENV_KEYS, readModelRouteEnv, envLaneTable, laneAndEndpointFor } from "./model-route-gap.js";
|
|
20
|
+
export type { EnvCheapSlot, LaneAndEndpoint, ModelRouteEnv, ModelRouteEnvName, ModelRouteEnvReading, ModelRouteSubject } from "./model-route-gap.js";
|
|
21
|
+
export type { ModelBrainLane } from "./model-provider.js";
|
|
22
|
+
//# sourceMappingURL=model-route-env.d.ts.map
|