@sema-agent/server 7.131.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 +575 -0
- package/README.md +12 -9
- package/README.zh-CN.md +9 -6
- package/USAGE.md +326 -98
- 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 +82 -20
- package/dist/approval-card.js +46 -16
- 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 +33 -19
- package/dist/audit.js +12 -16
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +27 -12
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.d.ts +2 -2
- 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/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +74 -123
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +15 -2
- package/dist/boot/session-faces.d.ts +2 -7
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +4 -2
- package/dist/boot/stage-06-runners.js +11 -7
- package/dist/boot/stage-07-capability-layer.d.ts +4 -2
- package/dist/boot/stage-07-capability-layer.js +27 -6
- package/dist/boot/stage-08-reapers.d.ts +4 -2
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +6 -9
- package/dist/boot/stage-10-http-server.d.ts +6 -9
- package/dist/boot/stage-10-http-server.js +7 -9
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +7 -8
- package/dist/boot/web-admin.d.ts +4 -3
- package/dist/boot/web-admin.js +186 -98
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +25 -25
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +23 -0
- package/dist/caller-text-echo.js +21 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +30 -6
- package/dist/capabilities/hands-lane.js +11 -1
- package/dist/capabilities/mcp-probe.d.ts +48 -3
- package/dist/capabilities/mcp-probe.js +47 -135
- package/dist/capabilities/scenarios.d.ts +95 -45
- package/dist/capabilities/scenarios.js +53 -38
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- 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 +47 -32
- 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-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +9 -2
- package/dist/config-provider.js +18 -6
- package/dist/config-types.d.ts +75 -20
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +137 -62
- 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 -22
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +56 -10
- package/dist/execution-lane-caps.js +50 -0
- 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 +91 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +79 -36
- package/dist/hooks/hook-runner.d.ts +349 -95
- package/dist/hooks/hook-runner.js +855 -568
- 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.d.ts +8 -2
- package/dist/http/admission.js +188 -101
- package/dist/http/approval-sweeps.js +99 -21
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +41 -24
- package/dist/http/checkpoint-ctx.js +23 -16
- package/dist/http/claimed-run.d.ts +14 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +7 -11
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +15 -13
- package/dist/http/durable-run-leg.d.ts +6 -33
- package/dist/http/durable-run-leg.js +36 -10
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +70 -28
- package/dist/http/principal-gate.js +61 -15
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +43 -23
- package/dist/http/request-guards.js +53 -17
- 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 +28 -4
- package/dist/http/resume-legs.js +169 -91
- 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 +21 -5
- 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 +6 -2
- 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 +34 -107
- package/dist/http/routes/session-sync.js +15 -26
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +8 -7
- package/dist/http/routes/tasks.js +67 -21
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +33 -10
- package/dist/http/send.js +21 -4
- package/dist/http/server.d.ts +27 -18
- package/dist/http/server.js +34 -6
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +40 -0
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +11 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/lane-home-probe.d.ts +112 -0
- package/dist/lane-home-probe.js +101 -0
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +59 -0
- package/dist/limit-refusal.js +15 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +32 -19
- package/dist/mcp-assertion-header.js +10 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +6 -4
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +24 -17
- 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 +44 -12
- package/dist/model-provider.js +21 -2
- package/dist/model-route-endpoint.d.ts +9 -12
- package/dist/model-route-endpoint.js +8 -11
- 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/cost-taxonomy.d.ts +7 -7
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +76 -14
- package/dist/observability/fail-open.js +76 -14
- package/dist/observability/metrics.js +4 -1
- package/dist/observability/prompt-manifest.d.ts +33 -82
- package/dist/observability/prompt-manifest.js +122 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +58 -49
- 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/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- 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 +83 -15
- package/dist/plugins/blob-backend.js +68 -15
- 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 +28 -4
- package/dist/plugins/checkpoint-store-sql.js +59 -28
- 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/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +11 -3
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-store.js +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 +245 -93
- package/dist/plugins/one-time-migrations.js +668 -207
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +20 -8
- package/dist/plugins/pg-session-storage.js +34 -21
- package/dist/plugins/remote-env-adb.d.ts +12 -12
- package/dist/plugins/remote-env-adb.js +21 -6
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +103 -38
- package/dist/plugins/remote-env-k8s.js +288 -95
- package/dist/plugins/remote-env-local-docker.d.ts +27 -13
- package/dist/plugins/remote-env-local-docker.js +82 -11
- package/dist/plugins/remote-env-ssh.d.ts +21 -12
- package/dist/plugins/remote-env-ssh.js +117 -5
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- 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 +39 -0
- package/dist/plugins/session-epoch-anchor.js +22 -0
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +205 -1
- package/dist/plugins/sql-driver.js +325 -13
- package/dist/plugins/sql-errors.d.ts +64 -0
- package/dist/plugins/sql-errors.js +57 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +42 -15
- 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 +8 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +29 -5
- 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/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- 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 +9 -2
- package/dist/request-key-closure.js +11 -5
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +38 -11
- package/dist/rule-entry-list.js +106 -30
- 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 +54 -24
- package/dist/runs.d.ts +15 -8
- package/dist/runs.js +35 -1
- 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/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- 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 +27 -6
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +66 -54
- package/dist/sql-engine-posture.d.ts +31 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +82 -107
- package/dist/task-settings.d.ts +95 -108
- package/dist/task-settings.js +77 -98
- package/dist/text-bidi.d.ts +1 -48
- package/dist/text-bidi.js +3 -5
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +304 -88
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +122 -20
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +98 -17
- package/dist/trace/project.js +98 -50
- 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 +377 -3
- package/dist/trace/wire-projection-faces.js +164 -1
- 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/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +11 -9
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
|
@@ -64,7 +64,27 @@ export function mutateInPlace(target, source) {
|
|
|
64
64
|
Object.assign(target, source);
|
|
65
65
|
}
|
|
66
66
|
const appliedGeneration = new WeakMap();
|
|
67
|
-
const
|
|
67
|
+
const envModelPlane = new WeakMap();
|
|
68
|
+
function envModelPlaneOf(config) {
|
|
69
|
+
let snap = envModelPlane.get(config);
|
|
70
|
+
if (snap === undefined) {
|
|
71
|
+
snap = {
|
|
72
|
+
models: { ...config.models },
|
|
73
|
+
model: config.envModel,
|
|
74
|
+
modelApiKeyEnv: { ...config.modelApiKeyEnv },
|
|
75
|
+
modelApiKeys: { ...config.modelApiKeys },
|
|
76
|
+
modelRefusals: { ...config.modelRefusals },
|
|
77
|
+
droppedCatalogEntries: [...config.droppedCatalogEntries],
|
|
78
|
+
quotaWeights: { ...config.modelQuotaWeights },
|
|
79
|
+
roles: { ...config.roles },
|
|
80
|
+
activeTiers: { ...config.tiers },
|
|
81
|
+
atMention: config.atMention,
|
|
82
|
+
infoLine: {},
|
|
83
|
+
};
|
|
84
|
+
envModelPlane.set(config, snap);
|
|
85
|
+
}
|
|
86
|
+
return snap;
|
|
87
|
+
}
|
|
68
88
|
function stageAtMention(raw, usableNames, logger) {
|
|
69
89
|
const read = readAtMention(raw);
|
|
70
90
|
if (read === undefined) {
|
|
@@ -172,7 +192,7 @@ function commitStaged(config, staged) {
|
|
|
172
192
|
config.droppedCatalogEntries = mp.droppedCatalogEntries;
|
|
173
193
|
mutateInPlace(config.modelQuotaWeights, mp.quotaWeights);
|
|
174
194
|
mutateInPlace(config.models, mp.models);
|
|
175
|
-
config.model =
|
|
195
|
+
config.model = mp.model;
|
|
176
196
|
mutateInPlace(config.roles, mp.roles);
|
|
177
197
|
mutateInPlace(config.tiers, mp.activeTiers);
|
|
178
198
|
config.atMention = mp.atMention;
|
|
@@ -227,7 +247,38 @@ function modelPlaneGroupReport(group) {
|
|
|
227
247
|
};
|
|
228
248
|
}
|
|
229
249
|
const ROLE_BINDING_UNAVAILABLE_HINT = "tasks resolving this role fail: alias/tier expansion cannot mint this name; the engine refuses it loud — bind the role to a usable model, or make the entry usable (see the entry's own warn)";
|
|
250
|
+
export const NO_CENTER_EFFECTIVE = deepFreeze({ version: 0, updatedAt: "", models: { models: [], roles: {} }, mcp: { servers: [] } });
|
|
251
|
+
export const isNoCenterEffective = (eff) => eff === NO_CENTER_EFFECTIVE;
|
|
252
|
+
function deepFreeze(v) {
|
|
253
|
+
if (v !== null && typeof v === "object") {
|
|
254
|
+
for (const x of Object.values(v))
|
|
255
|
+
deepFreeze(x);
|
|
256
|
+
Object.freeze(v);
|
|
257
|
+
}
|
|
258
|
+
return v;
|
|
259
|
+
}
|
|
260
|
+
function stageEnvModelPlane(config) {
|
|
261
|
+
if (servedModelTableLeg(config) === "env")
|
|
262
|
+
return { stages: {} };
|
|
263
|
+
const snap = envModelPlane.get(config);
|
|
264
|
+
if (snap === undefined)
|
|
265
|
+
throw new Error("applyEffective: the center model plane is in force but no env snapshot was taken — the model plane was written outside applyEffective, so the no-center tier has no baseline to return to");
|
|
266
|
+
return {
|
|
267
|
+
stages: {
|
|
268
|
+
models: {
|
|
269
|
+
...snap,
|
|
270
|
+
modelApiKeyEnv: { ...snap.modelApiKeyEnv },
|
|
271
|
+
modelApiKeys: { ...snap.modelApiKeys },
|
|
272
|
+
modelRefusals: { ...snap.modelRefusals },
|
|
273
|
+
droppedCatalogEntries: [...snap.droppedCatalogEntries],
|
|
274
|
+
infoLine: { source: "no-center-baseline", default: snap.model.id, roles: Object.keys(snap.roles), tiers: [], atMention: snap.atMention.mode },
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
230
279
|
function stageModelPlane(config, eff, logger, sealedKeys) {
|
|
280
|
+
if (isNoCenterEffective(eff))
|
|
281
|
+
return stageEnvModelPlane(config);
|
|
231
282
|
const enabled = (eff.models?.models ?? []).filter((m) => m.enabled !== false);
|
|
232
283
|
const verdict = judgeCatalogEntries(enabled, { anthropicRouteMounted: config.anthropic !== undefined }, eff.models?.droppedCatalogEntries);
|
|
233
284
|
if (enabled.length === 0 && verdict.malformed.length === 0 && verdict.dropped.every((row) => row.identity?.enabled === false))
|
|
@@ -293,8 +344,7 @@ function stageModelPlane(config, eff, logger, sealedKeys) {
|
|
|
293
344
|
quotaWeights[m.id] = qw;
|
|
294
345
|
}
|
|
295
346
|
}
|
|
296
|
-
|
|
297
|
-
envRolesBaseline.set(config, { ...config.roles });
|
|
347
|
+
const envPlane = envModelPlaneOf(config);
|
|
298
348
|
const centerRoles = {};
|
|
299
349
|
for (const [role, tgt] of Object.entries(eff.models.roles ?? {})) {
|
|
300
350
|
if ("model" in tgt)
|
|
@@ -302,7 +352,7 @@ function stageModelPlane(config, eff, logger, sealedKeys) {
|
|
|
302
352
|
else if ("select" in tgt)
|
|
303
353
|
centerRoles[role] = { select: tgt.select };
|
|
304
354
|
}
|
|
305
|
-
const roles = { ...
|
|
355
|
+
const roles = { ...envPlane.roles, ...centerRoles };
|
|
306
356
|
const activeTiers = {};
|
|
307
357
|
for (const [tier, target] of Object.entries(resolveActiveTiers(eff.models) ?? {})) {
|
|
308
358
|
if (models[target] !== undefined) {
|
|
@@ -365,6 +415,7 @@ function stageModelPlane(config, eff, logger, sealedKeys) {
|
|
|
365
415
|
const defaultModel = models.default;
|
|
366
416
|
const plane = {
|
|
367
417
|
models,
|
|
418
|
+
model: defaultModel,
|
|
368
419
|
modelApiKeyEnv,
|
|
369
420
|
modelApiKeys,
|
|
370
421
|
modelRefusals: { ...verdict.refused },
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 配置候选的**唯一判官**:一份候选(中心有效视图,或本地 `config.d` 读出的那份)能不能收 —— 只有这一种判法。
|
|
3
3
|
*
|
|
4
4
|
* 判据(三件,任一即拒;每条拒因带成因词,闭集 {@link CandidateRejectReason}):读腿交出的 `domainErrors`(某个域读不懂 / 拼错键 / 坏文件:那个域已落
|
|
5
|
-
* schema 缺省)与 prompts
|
|
5
|
+
* schema 缺省)与 prompts 面的判官(`judgePromptsWire`:契约包的 wire 形再交引擎 verify —— 中心层只有一种形)—— 成因 `domain_invalid`;读腿交出的
|
|
6
6
|
* `retiredDomains`(带事实的退役域文档,契约包的墓碑;拒句点名退役版本与一次性迁移)—— 成因 `retired_domain`。任一 ⇒ `rejected`:
|
|
7
7
|
* **整份候选不收**,一个域都不应用。退役域此前在读腿整包抛、走「源不可达」那条臂(版本读不到、没有拒判行、刷新拍算失败);现在读腿只交数据,
|
|
8
8
|
* 坏候选只有本判官一种判法。
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
* `domains` 排序去重:收集器的顺序没有承诺,它是拒行去重键的一部分(同一份候选、同一组坏域只响一次)。`errors` 原样逐条
|
|
23
23
|
* (读腿的诊断在前、prompts 在后)—— 那是可操作的诊断,不是键。纯函数:不改入参,不读环境。
|
|
24
24
|
*
|
|
25
|
-
* **判官交值**:`clean` 判决带着 prompts
|
|
26
|
-
* 迟到起服 / LKG 起服 / `run-local`)直接用这一份值,不再自己判第二遍 —— `
|
|
25
|
+
* **判官交值**:`clean` 判决带着 prompts 面的判官结论(`prompts` = 引擎 verify 过的发布形 artifact;候选不带 prompts 键 ⇒ `undefined`)。采纳 prompts 的各处
|
|
26
|
+
* (起服 / 刷新 / 迟到起服 / LKG 起服 / `run-local`)直接用这一份值,不再自己判第二遍 —— `judgePromptsWire` 在 src 里只有本判官一个调用点
|
|
27
27
|
* (盘上 LKG 的读回复判也经本判官,`config-lkg.ts`)。
|
|
28
28
|
*/
|
|
29
|
-
import {
|
|
29
|
+
import type { PublishedPromptArtifact } from "@sema-agent/core";
|
|
30
30
|
import type { EffectiveConfig } from "./types.js";
|
|
31
31
|
/** 读腿交出的一条域级诊断(与 `FetchEffectiveResult.domainErrors` 同形;error 文案已在产出边界脱敏)。 */
|
|
32
32
|
export interface CandidateDomainError {
|
|
@@ -46,10 +46,10 @@ export interface ConfigCandidateRead {
|
|
|
46
46
|
readonly retiredDomains?: readonly CandidateDomainError[];
|
|
47
47
|
}
|
|
48
48
|
export type ConfigCandidateVerdict =
|
|
49
|
-
/** `prompts` =
|
|
49
|
+
/** `prompts` = 候选的中心层(引擎 verify 过的发布形 artifact;候选不带 prompts 键 ⇒ `undefined` = 撤下中心层、内置提示词服务)。 */
|
|
50
50
|
{
|
|
51
51
|
readonly verdict: "clean";
|
|
52
|
-
readonly prompts:
|
|
52
|
+
readonly prompts: PublishedPromptArtifact | undefined;
|
|
53
53
|
} | {
|
|
54
54
|
readonly verdict: "rejected";
|
|
55
55
|
readonly domains: readonly string[];
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { judgePromptsWire } from "../prompts-domain-validate.js";
|
|
2
2
|
export function judgeConfigCandidate(r) {
|
|
3
3
|
const prompts = r.effective.prompts;
|
|
4
|
-
const promptsGate = prompts === undefined ? undefined :
|
|
4
|
+
const promptsGate = prompts === undefined ? undefined : judgePromptsWire(prompts);
|
|
5
5
|
const errors = [
|
|
6
6
|
...(r.domainErrors ?? []).map((de) => ({ domain: de.domain, error: de.error, reason: "domain_invalid" })),
|
|
7
7
|
...(promptsGate !== undefined && !promptsGate.ok ? [{ domain: "prompts", error: promptsGate.error, reason: "domain_invalid" }] : []),
|
|
8
8
|
...(r.retiredDomains ?? []).map((rd) => ({ domain: rd.domain, error: rd.error, reason: "retired_domain" })),
|
|
9
9
|
];
|
|
10
10
|
if (errors.length === 0)
|
|
11
|
-
return { verdict: "clean", prompts: promptsGate?.ok ? promptsGate.
|
|
11
|
+
return { verdict: "clean", prompts: promptsGate?.ok ? promptsGate.artifact : undefined };
|
|
12
12
|
return { verdict: "rejected", domains: [...new Set(errors.map((e) => e.domain))].sort(), errors };
|
|
13
13
|
}
|
|
14
14
|
export function buildCandidateRejectedFields(r, verdict, leg, ctx) {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* importers to update, which was done in the same commit.
|
|
49
49
|
*/
|
|
50
50
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, WebAdminHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
51
|
-
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
51
|
+
export { mutateInPlace, applyEffective, NO_CENTER_EFFECTIVE, isNoCenterEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
52
52
|
export { restartReasons, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type EngineRestartSignal, } from "./restart-signal.js";
|
|
53
53
|
export { applySkillsManifest, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
54
54
|
export { applyCenterReadFace, buildReadFaceBaseline, buildReadFaceSwapCandidate, restoreReadFaceBaseline, CENTER_READ_FACE_LIVE_KEYS, type CenterReadFaceApply, type CenterReadFaceReport, type ReadFaceBaseline, type ReadFaceSeat } from "./read-face.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, WebAdminHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
2
|
-
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
2
|
+
export { mutateInPlace, applyEffective, NO_CENTER_EFFECTIVE, isNoCenterEffective, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
3
3
|
export { restartReasons, modelPlaneChanged, } from "./restart-signal.js";
|
|
4
4
|
export { applySkillsManifest, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
5
5
|
export { applyCenterReadFace, buildReadFaceBaseline, buildReadFaceSwapCandidate, restoreReadFaceBaseline, CENTER_READ_FACE_LIVE_KEYS } from "./read-face.js";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { readEffectiveWire, PrincipalCapsWire } from "@sema-agent/settings-schema";
|
|
3
|
-
import { centerPromptsFromEffective } from "../prompts-domain-validate.js";
|
|
4
3
|
import { separateRetiredDomains, splitFoldedReadWarnings, withDroppedCatalogEntries } from "./read-warnings.js";
|
|
5
4
|
import { CENTER_PULL_TIMEOUT_MS, centerFetch } from "./center-request.js";
|
|
6
5
|
import { answerStillCurrent } from "../center-credential.js";
|
|
@@ -13,11 +12,6 @@ export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
|
|
|
13
12
|
const warnings = [];
|
|
14
13
|
const { body, retiredDomains } = separateRetiredDomains(await res.json());
|
|
15
14
|
const wire = readEffectiveWire(body, (w) => warnings.push(w));
|
|
16
|
-
const centerPrompts = centerPromptsFromEffective(wire);
|
|
17
|
-
if (centerPrompts === undefined)
|
|
18
|
-
delete wire.prompts;
|
|
19
|
-
else
|
|
20
|
-
wire.prompts = centerPrompts;
|
|
21
15
|
const { domainErrors, droppedEntries, droppedCatalogEntries, unreadFiles } = splitFoldedReadWarnings(warnings, "center");
|
|
22
16
|
const effective = withDroppedCatalogEntries(wire, droppedCatalogEntries);
|
|
23
17
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { compileReadDeny, isSwappableDepSeat, resolveReadDenyBuiltins } from "@sema-agent/core";
|
|
2
|
+
import { readReadDenyEntry } from "../read-deny-entry.js";
|
|
2
3
|
export function buildReadFaceBaseline(config) {
|
|
3
4
|
return {
|
|
4
5
|
...(config.readFace !== undefined ? { readFace: config.readFace } : {}),
|
|
@@ -44,15 +45,10 @@ function normalizeDenyPatterns(raw) {
|
|
|
44
45
|
if (!Array.isArray(raw))
|
|
45
46
|
throw new ReadFaceDomainError("readFace.denyPatterns must be an array of \"pattern\" strings or {pattern, caseSensitive?} objects");
|
|
46
47
|
return raw.map((it, i) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
const cs = it.caseSensitive;
|
|
53
|
-
if (cs !== undefined && typeof cs !== "boolean")
|
|
54
|
-
throw new ReadFaceDomainError(`readFace.denyPatterns[${i}].caseSensitive must be boolean when present`);
|
|
55
|
-
return { pattern: it.pattern, caseSensitive: cs === true };
|
|
48
|
+
const read = readReadDenyEntry(it);
|
|
49
|
+
if (!read.ok)
|
|
50
|
+
throw new ReadFaceDomainError(`readFace.denyPatterns[${i}]${read.after}`);
|
|
51
|
+
return read.entry;
|
|
56
52
|
});
|
|
57
53
|
}
|
|
58
54
|
function assertFace(raw) {
|
|
@@ -70,6 +70,19 @@ export type UnreadConfigFile = {
|
|
|
70
70
|
readonly why: "not-a-domain" | "non-portable-domain";
|
|
71
71
|
readonly domain?: string;
|
|
72
72
|
};
|
|
73
|
+
/**
|
|
74
|
+
* `config.d` 里一份**被读**的文件中、本地读腿结构上**不读**的一键(本服务铸,不是契约告警):今天只有 `prompts.json` 的 `workers` —— 本地腿没有
|
|
75
|
+
* worker 身份,中心层的唯一选择读法(`promptArtifactFor`)对它恒以 `null` 读,只交 `artifact`。写了不生效要响:调用方在采纳路径上一键一行 `config_unread_key`
|
|
76
|
+
* (与 `config_unread_file` 同频:起服与之后每次采纳一份变了的候选),不判拒。
|
|
77
|
+
*/
|
|
78
|
+
export type UnreadConfigKey = {
|
|
79
|
+
readonly file: string;
|
|
80
|
+
readonly domain: string;
|
|
81
|
+
readonly key: string;
|
|
82
|
+
readonly names: readonly string[];
|
|
83
|
+
};
|
|
84
|
+
/** `config_unread_key` 一行的体(纯数据;起服 / 刷新 / 迟到起服与 `run-local` 同一体):`dir` = 本地读腿的配置根。 */
|
|
85
|
+
export declare function buildUnreadConfigKeyFields(k: UnreadConfigKey, dir: string | undefined): Record<string, unknown>;
|
|
73
86
|
/** `config_unread_file` 一行的体(纯数据;起服 / 刷新 / 迟到起服与 `run-local` 同一体):`dir` = 本地读腿的配置根。 */
|
|
74
87
|
export declare function buildUnreadConfigFileFields(f: UnreadConfigFile, dir: string | undefined): Record<string, unknown>;
|
|
75
88
|
/** 逐条丢弃面的一行(两条读腿的 `droppedEntries` 同形,`config_entry_dropped` 日志行读它):`entry` = 被丢那条的出门形坐标(`models.1`),
|
|
@@ -22,6 +22,16 @@ export function separateRetiredDomains(body) {
|
|
|
22
22
|
}
|
|
23
23
|
return findings.length === 0 ? { body, retiredDomains: [] } : { body: rest, retiredDomains: findings };
|
|
24
24
|
}
|
|
25
|
+
export function buildUnreadConfigKeyFields(k, dir) {
|
|
26
|
+
return {
|
|
27
|
+
...(dir !== undefined ? { dir } : {}),
|
|
28
|
+
file: k.file,
|
|
29
|
+
domain: k.domain,
|
|
30
|
+
key: k.key,
|
|
31
|
+
names: k.names,
|
|
32
|
+
note: "the local config read has no worker identity, so this key is never read — prompts.json `workers` entries are not delivered, only `artifact` is; put the artifact this engine should run under `artifact` (or remove the key if it is meant for the center)",
|
|
33
|
+
};
|
|
34
|
+
}
|
|
25
35
|
export function buildUnreadConfigFileFields(f, dir) {
|
|
26
36
|
return {
|
|
27
37
|
...(dir !== undefined ? { dir } : {}),
|
|
@@ -18,6 +18,9 @@ export type SkillBodySource = Pick<ConfigProvider, "fetchSkillContent" | "skillB
|
|
|
18
18
|
* hash, deduped in memory (same hash read once). A skill whose body is absent at the source or fails to read (incl. the
|
|
19
19
|
* remote transport's hash check) is NOT installed — exactly one `web_admin_skill_failed` warn names it (`reason`:
|
|
20
20
|
* `body_absent` | `read_failed`), the baseline of that name (if any) stays, and boot is never blocked.
|
|
21
|
+
* 🔴 **「正文在场」只有一条判据:非空串**({@link skillBodyPresent})。配置源答 `undefined`(没有这个 hash)与答 `""`(空正文)同为缺席 ⇒ `body_absent`:
|
|
22
|
+
* 一条空正文的技能是**惰性无提示**(名册里有它、模型调用回空、零行日志),不是「装了个什么都不说的技能」。本地腿尤其:settings-schema 把缺省的 `content`
|
|
23
|
+
* 补成 `""`,本地配置源因此**永远答得出**(空串)—— 没有这一条,`body_absent` 臂只在中心形上可达。本地 / 中心 / 盘缓存三个来源同过这一只判据。
|
|
21
24
|
* Restart-to-apply: this runs at boot, before `buildScenarios` bakes skills into scenarios.
|
|
22
25
|
*/
|
|
23
26
|
export declare function applySkillsManifest(baseline: LoadedSkill[], manifest: {
|
|
@@ -2,10 +2,12 @@ import { readMcpSourceLabel } from "../mcp-source-label.js";
|
|
|
2
2
|
import { readMcpToolFaces } from "../mcp-tool-faces.js";
|
|
3
3
|
import { skillContentHash } from "@sema-agent/settings-schema";
|
|
4
4
|
import { readMcpToolAxes } from "@sema-agent/core";
|
|
5
|
-
import {
|
|
6
|
-
import { noteMcpAssertionHeaderNotSent } from "../mcp-assertion-header.js";
|
|
5
|
+
import { MCP_CONTENT_ORIGINS, describeBadContentOrigin, describeBadWireName, isContentOriginWord, isUsableWireName } from "@sema-agent/settings-schema";
|
|
6
|
+
import { noteMcpAssertionHeaderNotSent, sentMcpAssertionHeaderMember, withholdsMcpAssertionHeader } from "../mcp-assertion-header.js";
|
|
7
7
|
import { SHA256_HEX_RE } from "../digest-form.js";
|
|
8
|
-
|
|
8
|
+
function skillBodyPresent(body) {
|
|
9
|
+
return body !== undefined && body !== "";
|
|
10
|
+
}
|
|
9
11
|
export async function applySkillsManifest(baseline, manifest, bodies, logger) {
|
|
10
12
|
const diskCacheDir = bodies.skillBodyCacheDir;
|
|
11
13
|
const { promises: fsp } = await import("node:fs");
|
|
@@ -19,7 +21,7 @@ export async function applySkillsManifest(baseline, manifest, bodies, logger) {
|
|
|
19
21
|
try {
|
|
20
22
|
const text = await fsp.readFile(joinPath(diskCacheDir, hex), "utf8");
|
|
21
23
|
if (skillContentHash(text) === hash)
|
|
22
|
-
return text;
|
|
24
|
+
return skillBodyPresent(text) ? text : undefined;
|
|
23
25
|
logger?.warn("web_admin_skill_cache_corrupt", { hash, note: "on-disk body fails its own hash — ignored, re-reading from the config source" });
|
|
24
26
|
}
|
|
25
27
|
catch {
|
|
@@ -53,8 +55,8 @@ export async function applySkillsManifest(baseline, manifest, bodies, logger) {
|
|
|
53
55
|
content = await diskRead(m.contentHash);
|
|
54
56
|
if (content === undefined) {
|
|
55
57
|
const answered = await bodies.fetchSkillContent(m.contentHash);
|
|
56
|
-
if (answered
|
|
57
|
-
logger?.warn("web_admin_skill_failed", { name: m.name, hash: m.contentHash, reason: "body_absent", note: "the config source holds no body for this hash — this entry is NOT installed; the baseline skill of this name (if any) stays" });
|
|
58
|
+
if (!skillBodyPresent(answered)) {
|
|
59
|
+
logger?.warn("web_admin_skill_failed", { name: m.name, hash: m.contentHash, reason: "body_absent", note: "the config source holds no body for this hash (absent, or an empty string) — this entry is NOT installed; the baseline skill of this name (if any) stays" });
|
|
58
60
|
continue;
|
|
59
61
|
}
|
|
60
62
|
content = answered;
|
|
@@ -109,7 +111,7 @@ export function resolveMcpServers(mcp, logger) {
|
|
|
109
111
|
logger?.warn("web_admin_mcp_content_class_invalid", {
|
|
110
112
|
server: s.name,
|
|
111
113
|
value: describeBadContentOrigin(s.contentOrigin),
|
|
112
|
-
allowed:
|
|
114
|
+
allowed: MCP_CONTENT_ORIGINS,
|
|
113
115
|
note: "declaration DROPPED — this server's tools keep the pre-378 default (external content, session gets marked). Fix the center entry; the server itself still mounts.",
|
|
114
116
|
});
|
|
115
117
|
}
|
|
@@ -147,11 +149,11 @@ export function resolveMcpServers(mcp, logger) {
|
|
|
147
149
|
const headers = resolveRefs(s.transport.headerRefs, s.name, "header", logger);
|
|
148
150
|
if (headers === null)
|
|
149
151
|
continue;
|
|
150
|
-
if (s.transport.assertionHeader
|
|
152
|
+
if (withholdsMcpAssertionHeader(s.transport.assertionHeader))
|
|
151
153
|
noteMcpAssertionHeaderNotSent(logger, s.name);
|
|
152
154
|
out.push({
|
|
153
155
|
scenarios: s.scenarios ?? [],
|
|
154
|
-
spec: { name: s.name, transport: { kind: "http", url: s.transport.url, ...(Object.keys(headers).length ? { headers } : {}), ...(s.transport.principalHeader ? { principalHeader: s.transport.principalHeader } : {}) }, ...allow, ...elicit, ...contentOrigin, ...source, ...toolFaces, ...toolAxes },
|
|
156
|
+
spec: { name: s.name, transport: { kind: "http", url: s.transport.url, ...(Object.keys(headers).length ? { headers } : {}), ...(s.transport.principalHeader ? { principalHeader: s.transport.principalHeader } : {}), ...sentMcpAssertionHeaderMember(s.transport.assertionHeader) }, ...allow, ...elicit, ...contentOrigin, ...source, ...toolFaces, ...toolAxes },
|
|
155
157
|
});
|
|
156
158
|
}
|
|
157
159
|
}
|
|
@@ -371,9 +371,8 @@ export interface EffectiveConfig {
|
|
|
371
371
|
* 这条腿对本部署不存在,四键仍由 env / 引擎默认独占。restart-to-apply(boot 期被 `createRunnerDeps`
|
|
372
372
|
* 捕获),改动经 `read-face` restart 片通告。 */
|
|
373
373
|
readFace?: CenterReadFace;
|
|
374
|
-
/** prompts 域(
|
|
375
|
-
*
|
|
376
|
-
* 声明键位存在(unknown:候选门是唯一解释者,这里不复刻形)。 */
|
|
374
|
+
/** prompts 域(中心层;wire 形只有一种 = 契约包 `EffectivePromptsWire` `{ schemaVersion: 2, artifact }`)—— 判法只在候选判官一处
|
|
375
|
+
* (`prompts-domain-validate.ts` 的 `judgePromptsWire`,经 `judgeConfigCandidate`),本 interface 只声明键位存在(unknown:判官是唯一解释者,这里不复刻形)。 */
|
|
377
376
|
prompts?: unknown;
|
|
378
377
|
}
|
|
379
378
|
/** (stage7 P5,registry-core 0.8 `execution` 域): the center-resolved per-principal execution
|
|
@@ -39,6 +39,41 @@ export declare function workspaceCacheClaimOf(spaceKey: string): {
|
|
|
39
39
|
name: string;
|
|
40
40
|
label: string;
|
|
41
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* The directories of the sandbox image the cache volume must never hide — a CLOSED set of path prefixes: a mount that is one of them,
|
|
44
|
+
* sits under one, or is an ancestor of one (a volume mounted there shadows everything the image keeps at that path) refuses boot.
|
|
45
|
+
* - the system roots every image has (`/bin` `/boot` `/dev` `/etc` `/lib` `/lib64` `/proc` `/root` `/run` `/sbin` `/sys` `/usr` `/var`);
|
|
46
|
+
* - `/tmp` — the adapter's own scratch (the snapshot archive, the background-job directories);
|
|
47
|
+
* - `/opt/sema` — the image's package-source hook the pod start runs;
|
|
48
|
+
* - `/home/sandbox` — the sandbox user's home in the images this lane ships.
|
|
49
|
+
* One reading: the workspace mount is the set's one dynamic member (`K8S_MOUNT_PATH`); config reads both through {@link mountsOverlap}.
|
|
50
|
+
*/
|
|
51
|
+
export declare const WORKSPACE_CACHE_MOUNT_RESERVED: readonly ["/bin", "/boot", "/dev", "/etc", "/home/sandbox", "/lib", "/lib64", "/opt/sema", "/proc", "/root", "/run", "/sbin", "/sys", "/tmp", "/usr", "/var"];
|
|
52
|
+
/** The reserved directory a cache mount collides with (at / under / above it), or `undefined`. `mount` is absolute and normalized. */
|
|
53
|
+
export declare function reservedMountCollision(mount: string): (typeof WORKSPACE_CACHE_MOUNT_RESERVED)[number] | undefined;
|
|
54
|
+
/** The most spaces a {@link CacheMissMemory} holds at once (a process serving more spaces than this forgets the oldest first). */
|
|
55
|
+
export declare const CACHE_MISS_MEMORY_CAP = 1024;
|
|
56
|
+
/** A cache volume that could not be had for a pod and cost a wait: its claim did not bind in time, or it bound and the pod carrying it did not become ready. */
|
|
57
|
+
export interface CacheMissRecord {
|
|
58
|
+
readonly reason: "claim_unbound" | "claim_unmountable";
|
|
59
|
+
readonly detail: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The process's memory of cache volumes that could not be had — per space, for a window the caller states: a run that waited out a volume the cluster could not
|
|
63
|
+
* bind says so here, and the next runs of that space inside the window start without it at once (no claim request, no pod waiting on it) instead of each paying the
|
|
64
|
+
* whole wait again. A cache is regenerable, so "not asked for a while" costs only builds that re-download. Keyed by the claim's one-way digest (never the space key
|
|
65
|
+
* itself); bounded ({@link CACHE_MISS_MEMORY_CAP}: expired entries go first, then the oldest). One per deployment, held by the per-run binding — never process-global.
|
|
66
|
+
*/
|
|
67
|
+
export interface CacheMissMemory {
|
|
68
|
+
/** `spaceKey`'s volume could not be had: remembered for `windowMs` from now. */
|
|
69
|
+
remember(spaceKey: string, miss: CacheMissRecord, windowMs: number): void;
|
|
70
|
+
/** Inside the window ⇒ the remembered miss; otherwise `undefined` (and the entry is dropped). */
|
|
71
|
+
recall(spaceKey: string): CacheMissRecord | undefined;
|
|
72
|
+
/** Entries held (expired ones that were not read again included). */
|
|
73
|
+
size(): number;
|
|
74
|
+
}
|
|
75
|
+
/** A fresh {@link CacheMissMemory} (`now` = the clock, epoch ms; a test hands its own). */
|
|
76
|
+
export declare function createCacheMissMemory(now?: () => number): CacheMissMemory;
|
|
42
77
|
/** Does the cache mount overlap the workspace mount (equal, or one inside the other)? Both are absolute, normalized paths. */
|
|
43
78
|
export declare function mountsOverlap(a: string, b: string): boolean;
|
|
44
79
|
export {};
|
package/dist/workspace-cache.js
CHANGED
|
@@ -23,6 +23,42 @@ export function workspaceCacheClaimOf(spaceKey) {
|
|
|
23
23
|
const digest = createHash("sha256").update(spaceKey).digest("hex").slice(0, 20);
|
|
24
24
|
return { name: `ws-cache-${digest}`, label: digest };
|
|
25
25
|
}
|
|
26
|
+
export const WORKSPACE_CACHE_MOUNT_RESERVED = ["/bin", "/boot", "/dev", "/etc", "/home/sandbox", "/lib", "/lib64", "/opt/sema", "/proc", "/root", "/run", "/sbin", "/sys", "/tmp", "/usr", "/var"];
|
|
27
|
+
export function reservedMountCollision(mount) {
|
|
28
|
+
return WORKSPACE_CACHE_MOUNT_RESERVED.find((dir) => mountsOverlap(mount, dir));
|
|
29
|
+
}
|
|
30
|
+
export const CACHE_MISS_MEMORY_CAP = 1024;
|
|
31
|
+
export function createCacheMissMemory(now = Date.now) {
|
|
32
|
+
const held = new Map();
|
|
33
|
+
const keyOf = (spaceKey) => workspaceCacheClaimOf(spaceKey).label;
|
|
34
|
+
return {
|
|
35
|
+
remember(spaceKey, miss, windowMs) {
|
|
36
|
+
const at = now();
|
|
37
|
+
const key = keyOf(spaceKey);
|
|
38
|
+
held.delete(key);
|
|
39
|
+
held.set(key, { miss, until: at + windowMs });
|
|
40
|
+
if (held.size <= CACHE_MISS_MEMORY_CAP)
|
|
41
|
+
return;
|
|
42
|
+
for (const [k, e] of held)
|
|
43
|
+
if (e.until <= at)
|
|
44
|
+
held.delete(k);
|
|
45
|
+
while (held.size > CACHE_MISS_MEMORY_CAP)
|
|
46
|
+
held.delete(held.keys().next().value);
|
|
47
|
+
},
|
|
48
|
+
recall(spaceKey) {
|
|
49
|
+
const key = keyOf(spaceKey);
|
|
50
|
+
const e = held.get(key);
|
|
51
|
+
if (e === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (e.until <= now()) {
|
|
54
|
+
held.delete(key);
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return e.miss;
|
|
58
|
+
},
|
|
59
|
+
size: () => held.size,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
26
62
|
export function mountsOverlap(a, b) {
|
|
27
63
|
const inside = (x, y) => x === y || x.startsWith(y.endsWith("/") ? y : `${y}/`);
|
|
28
64
|
return inside(a, b) || inside(b, a);
|
|
@@ -71,8 +71,9 @@ export declare const WORKSPACE_SNAPSHOT_EXCLUDE_INVALID = "config.workspace_snap
|
|
|
71
71
|
* space snapshot and the park suspend share it). Unset / empty ⇒ no table (the upload command is what it always was).
|
|
72
72
|
*
|
|
73
73
|
* The item form is CLOSED: plain relative path segments — no leading `/`, no `.` / `..` / empty segment (`./x`, `a//b`, a
|
|
74
|
-
* trailing `/`), no whitespace, no quote characters, no control characters
|
|
75
|
-
*
|
|
74
|
+
* trailing `/`), no whitespace, no quote characters, no control characters, and no whole wildcard (an item made only of `*` / `?`
|
|
75
|
+
* names no path: `*` would exclude every top-level entry and the snapshot would be empty). Tar wildcards inside a segment (`*.log`)
|
|
76
|
+
* are items like any other. A project's `.gitignore` is NOT read (a second grammar, per project, not equivalent to tar's). Items are
|
|
76
77
|
* trimmed (the CSV separator's spacing is not part of an item); a bad item refuses boot naming its position — the value is a
|
|
77
78
|
* path pattern, never a secret, so it is echoed.
|
|
78
79
|
*/
|
package/dist/workspace-space.js
CHANGED
|
@@ -30,6 +30,8 @@ function snapshotExcludeItemProblem(item) {
|
|
|
30
30
|
return "not a plain path (it holds whitespace, a quote or a control character)";
|
|
31
31
|
if (item.startsWith("/"))
|
|
32
32
|
return "absolute (a leading /) — items are relative to the workspace root";
|
|
33
|
+
if (/^[*?]+$/.test(item))
|
|
34
|
+
return "a whole wildcard (only `*` / `?` — it names no path and would leave the snapshot without any top-level entry)";
|
|
33
35
|
const segments = item.split("/");
|
|
34
36
|
if (segments.includes(".."))
|
|
35
37
|
return "escaping the workspace (a .. segment)";
|
|
@@ -20,7 +20,8 @@ dials the device, so the device needs no inbound port, no public address and no
|
|
|
20
20
|
(this deployment has no device lane) or an object `{ enabled: true, protocolVersion, maxInflightPerDevice,
|
|
21
21
|
wsPath, management }`. Read `wsPath` from there rather than hardcoding it: the path is part of the wire
|
|
22
22
|
contract and reading it means a future path change is not a cross-repo break. `protocolVersion` tells you
|
|
23
|
-
which
|
|
23
|
+
which protocol **revision** the server speaks before you spend a handshake finding out (§2.1: the revision decides
|
|
24
|
+
which `errorCode` words the server accepts from you).
|
|
24
25
|
|
|
25
26
|
---
|
|
26
27
|
|
|
@@ -144,6 +145,13 @@ The server sends `challenge` immediately on open. From the moment the socket ope
|
|
|
144
145
|
the handshake completes, **frames are capped at `maxPreAuthFrameBytes` (4096 bytes)** and a malformed
|
|
145
146
|
pre-auth frame closes the connection outright.
|
|
146
147
|
|
|
148
|
+
**Which revision to declare.** `challenge.protocolVersion` is the highest protocol revision this server speaks
|
|
149
|
+
(`DEVICE_MIN_PROTOCOL_VERSION` is the lowest it accepts, §2.1). Put the highest revision *you* implement that is
|
|
150
|
+
not above `challenge.protocolVersion` into `hello.protocolVersion` — the same integer you sign (§1.3) — and emit
|
|
151
|
+
only the `errorCode` words of that revision (the revision table in §2.1). Nothing is renegotiated after `hello`:
|
|
152
|
+
the revision you declared is the contract for the whole connection. If the highest revision you implement is below
|
|
153
|
+
`DEVICE_MIN_PROTOCOL_VERSION`, the server answers `helloReject: protocol_version_unsupported` (§1.4).
|
|
154
|
+
|
|
147
155
|
### 1.3 The `hello` signature (byte-exact — do not improvise)
|
|
148
156
|
|
|
149
157
|
Sign with the device private key over exactly these bytes:
|
|
@@ -245,18 +253,32 @@ backoff, exponential to a 60 s ceiling, jittered — except for `revoked`, which
|
|
|
245
253
|
|
|
246
254
|
`helloAck` carries:
|
|
247
255
|
|
|
256
|
+
<!-- closed-set: DEVICE_HELLO_ACK_BOUNDS -->
|
|
257
|
+
|
|
248
258
|
| Field | Form | Meaning |
|
|
249
259
|
|---|---|---|
|
|
250
260
|
| `ok` | always `true` | — |
|
|
251
|
-
| `heartbeatIntervalMs` | integer ms | how often you should send `heartbeat` (deployment default 15000) |
|
|
252
|
-
| `maxInflight` | integer | how many instructions the server will have outstanding on this device at once (deployment default 4) |
|
|
261
|
+
| `heartbeatIntervalMs` | `integer ms ≥ 1` | how often you should send `heartbeat` (deployment default 15000) |
|
|
262
|
+
| `maxInflight` | `integer ≥ 1` | how many instructions the server will have outstanding on this device at once (deployment default 4) |
|
|
253
263
|
| `gen` | **canonical decimal string** (`"7"`, never `7`, never `"07"`) | the connection generation. Stamp it on every frame you send |
|
|
254
264
|
| `pendingInstructions` | `string[]` | instruction ids the server still considers in flight for you — see §5 R2 |
|
|
255
265
|
| `chunkWatermarks` | `{ [instructionId]: number }` | per instruction, the highest **contiguous** `streamSeq` the server has already accepted. `-1` means "nothing accepted yet" |
|
|
256
|
-
| `reconnectGraceMs` | integer ms | the reconnect grace **in force on this server** (R4): how long in-flight work survives a dropped socket. Deployment-tunable, default 120000 |
|
|
257
|
-
| `cancelGraceMs` | integer ms | the cancel grace in force (R11): how long after a `cancel` is delivered the server waits for your terminal `result`. Default 10000 |
|
|
258
|
-
| `chunkGapTimeoutMs` | integer ms | the chunk-gap timeout in force (R8): how long the server waits for a missing `streamSeq` before failing the instruction. Default 30000 |
|
|
259
|
-
| `executionCeilingGraceMs` | integer ms | the grace added to an instruction's `timeoutMs` before the server gives up and settles it as outcome-unknown (R12: the ceiling is `timeoutMs + executionCeilingGraceMs`). Default 30000 |
|
|
266
|
+
| `reconnectGraceMs` | `integer ms ≥ 0` | the reconnect grace **in force on this server** (R4): how long in-flight work survives a dropped socket. Deployment-tunable, default 120000 |
|
|
267
|
+
| `cancelGraceMs` | `integer ms ≥ 0` | the cancel grace in force (R11): how long after a `cancel` is delivered the server waits for your terminal `result`. Default 10000 |
|
|
268
|
+
| `chunkGapTimeoutMs` | `integer ms ≥ 0` | the chunk-gap timeout in force (R8): how long the server waits for a missing `streamSeq` before failing the instruction. Default 30000 |
|
|
269
|
+
| `executionCeilingGraceMs` | `integer ms ≥ 0` | the grace added to an instruction's `timeoutMs` before the server gives up and settles it as outcome-unknown (R12: the ceiling is `timeoutMs + executionCeilingGraceMs`). Default 30000 |
|
|
270
|
+
|
|
271
|
+
**Bounds.** The six numeric fields above are validated by the server when it starts: a deployment whose knob (or
|
|
272
|
+
embedding option) is outside its row's range refuses to boot — the value is never clamped and never replaced by a
|
|
273
|
+
default — so a `helloAck` on the wire is always in range, and every number in it is the value the server's own
|
|
274
|
+
timers and slot counts are armed with. Every `ms` field is also at most `2147483647` (the largest delay a
|
|
275
|
+
timer can hold; a larger value would be silently collapsed to 1 ms); `maxInflight` has no ceiling beyond an
|
|
276
|
+
integer JSON represents exactly (at most `9007199254740991`). A `0` grace means "no grace": that timer
|
|
277
|
+
fires at once. An executor that reads a value outside its row's range must treat it as a protocol violation — the executor-side twin
|
|
278
|
+
of the server's `bad_shape` refusal (§2.4): close the connection and reconnect with backoff — and must **not** read the
|
|
279
|
+
out-of-range value as the default.
|
|
280
|
+
`deviceHelloAckNumberFlaw` (from `@sema-agent/server/device-protocol`) is the same check the server applies.
|
|
281
|
+
The *absence* of one of the four grace fields is a different case, described below, and still means "not told".
|
|
260
282
|
|
|
261
283
|
The four grace fields are the values the server's own timers are armed with — not documentation defaults. Size
|
|
262
284
|
your reconnect backoff ceiling, your `cancel` answer deadline, your retransmission cadence and your own
|
|
@@ -314,8 +336,8 @@ base64 inside JSON fields.
|
|
|
314
336
|
| Constant | Value | Meaning |
|
|
315
337
|
|---|---|---|
|
|
316
338
|
| `DEVICE_WS_PATH` | `/v1/device/ws` | the upgrade path (prefer the `wsPath` from `/v1/capabilities`) |
|
|
317
|
-
| `DEVICE_PROTOCOL_VERSION` | `
|
|
318
|
-
| `DEVICE_MIN_PROTOCOL_VERSION` | `1` | the lowest
|
|
339
|
+
| `DEVICE_PROTOCOL_VERSION` | `2` | the protocol revision this server speaks (the highest it accepts) |
|
|
340
|
+
| `DEVICE_MIN_PROTOCOL_VERSION` | `1` | the lowest revision it accepts; below it (or above the highest), a loud `helloReject` — never a silent downgrade |
|
|
319
341
|
| `DEVICE_HELLO_DOMAIN_TAG` | `sema.device.hello.v1` | the handshake signature domain tag (§1.3) |
|
|
320
342
|
|
|
321
343
|
<!-- closed-set: DEVICE_WS_LIMITS -->
|
|
@@ -330,6 +352,29 @@ base64 inside JSON fields.
|
|
|
330
352
|
Note the asymmetry: the transport cap is 1 MiB, and the 4096-byte pre-auth cap is applied **after** the
|
|
331
353
|
frame has been reassembled. Keep `hello` small; it is not a place for long `supports` prose.
|
|
332
354
|
|
|
355
|
+
#### Protocol revisions and the `errorCode` set
|
|
356
|
+
|
|
357
|
+
The protocol revision is the only thing an executor can read *before* it sends `hello` (the `challenge` frame
|
|
358
|
+
carries it), so the set of `errorCode` words the server accepts from you is a function of the revision, not a
|
|
359
|
+
separate list. The table gives, per revision, the words **added** at that revision; the set at revision *N* is
|
|
360
|
+
the union of the rows up to *N*, and the full set at the current revision is the §3.3 table.
|
|
361
|
+
|
|
362
|
+
<!-- closed-set: DEVICE_OUTCOME_ERROR_CODES_BY_REVISION -->
|
|
363
|
+
|
|
364
|
+
| Revision | `errorCode` words added at this revision |
|
|
365
|
+
|---|---|
|
|
366
|
+
| `1` | `aborted`, `already_exists`, `auth_failed`, `callback_error`, `invalid`, `is_directory`, `not_directory`, `not_found`, `not_supported`, `outcome_unknown`, `permission_denied`, `precondition_failed`, `shell_unavailable`, `spawn_error`, `suspended`, `target_unavailable`, `timeout`, `transport_lost`, `unknown` |
|
|
367
|
+
| `2` | `liveness_no_output` |
|
|
368
|
+
|
|
369
|
+
Rules: adding a frame or a field is additive and does not raise the revision; adding a word to a closed set the
|
|
370
|
+
server *accepts from you* (today: the `errorCode` set) raises `DEVICE_PROTOCOL_VERSION` and adds a row here; a
|
|
371
|
+
released row never changes. Declare a revision as §1.2 says and send only the words of that revision: an executor
|
|
372
|
+
that declared revision 1 never sends `liveness_no_output` (the server does not police this per connection — it
|
|
373
|
+
decodes every connection against the current revision's full set — but a word above your declared revision is outside
|
|
374
|
+
your contract). The same sets are importable:
|
|
375
|
+
`DEVICE_OUTCOME_ERROR_CODES_BY_REVISION` and `deviceOutcomeErrorCodesAt(revision)` from
|
|
376
|
+
`@sema-agent/server/device-protocol`.
|
|
377
|
+
|
|
333
378
|
### 2.2 Device → server frames
|
|
334
379
|
|
|
335
380
|
<!-- closed-set: DEVICE_FRAME_TYPES -->
|
|
@@ -515,6 +560,9 @@ a moment ago. If you omit `created`, the consumer reports the weaker of the two
|
|
|
515
560
|
|
|
516
561
|
`message` is required on the failure arm and is shown to the model — make it specific.
|
|
517
562
|
|
|
563
|
+
This is the full set at the current revision (`2`); the revision table in §2.1 says which revision each word arrived
|
|
564
|
+
with, and an executor sends only the words of the revision it declared (§1.2).
|
|
565
|
+
|
|
518
566
|
<!-- closed-set: DEVICE_OUTCOME_ERROR_CODES -->
|
|
519
567
|
|
|
520
568
|
| `errorCode` | Use it when |
|
|
@@ -525,6 +573,7 @@ a moment ago. If you omit `created`, the consumer reports the weaker of the two
|
|
|
525
573
|
| `callback_error` | a callback/hook on the device side failed (exec family) |
|
|
526
574
|
| `invalid` | the arguments do not make sense for this target (e.g. `readLink` on a non-symlink) |
|
|
527
575
|
| `is_directory` | a file operation hit a directory |
|
|
576
|
+
| `liveness_no_output` | **you** killed the command because it produced no output for your own silence window (a hung command); the wall-clock budget `timeoutMs` running out stays `timeout`. The frame has no field for the window length — do not invent one |
|
|
528
577
|
| `not_directory` | a directory operation hit a non-directory |
|
|
529
578
|
| `not_found` | the path does not exist |
|
|
530
579
|
| `not_supported` | you do not implement this face (prefer simply not declaring it) |
|
|
@@ -539,10 +588,16 @@ a moment ago. If you omit `created`, the consumer reports the weaker of the two
|
|
|
539
588
|
| `transport_lost` | a transport the device itself depends on went away |
|
|
540
589
|
| `unknown` | none of the above |
|
|
541
590
|
|
|
542
|
-
|
|
591
|
+
Three codes carry load-bearing semantics upstream and must not be used loosely:
|
|
543
592
|
|
|
544
593
|
- `timeout` is treated as **retryable**. Use it only when you actually killed the work and know it is
|
|
545
594
|
dead. If you are not sure the command is dead, use `outcome_unknown`.
|
|
595
|
+
- `liveness_no_output` is the same kind of word — the command ran, you killed it, **retryable** — with a
|
|
596
|
+
different cause: it names the silence, `timeout` names the wall-clock budget. They are two different
|
|
597
|
+
numbers and the model is told a different sentence for each, so report the bound that actually fired.
|
|
598
|
+
The same rule applies: use it only when you actually killed the work and know it is dead; if you are
|
|
599
|
+
not sure, use `outcome_unknown`. On a file instruction it is a protocol violation (a file operation has
|
|
600
|
+
no silence window) and the server reads it as `unknown`.
|
|
546
601
|
- `outcome_unknown` is never auto-retried, anywhere. It is the honest answer for "the command may have
|
|
547
602
|
already run and I cannot confirm". Choosing `timeout`/`transport_lost` instead invites a second
|
|
548
603
|
execution of a command that already had side effects.
|