@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
package/dist/http/admission.js
CHANGED
|
@@ -1,52 +1,85 @@
|
|
|
1
1
|
import { APPROVAL_REACH, MCP_IMAGE_MAX_BASE64, isApprovalReach, isPermissionMode, isThinkingLevel, expandTiers } from "@sema-agent/core";
|
|
2
2
|
import { isAtMentionable, matchCatalogModel, refusedCatalogEntry, selectableCatalog } from "../model-select.js";
|
|
3
|
-
import { modelUnavailableMessage } from "../model-entry-refusal.js";
|
|
3
|
+
import { echoModelRef, modelUnavailableMessage } from "../model-entry-refusal.js";
|
|
4
4
|
import { HttpError, sessionIdShapeIssue } from "../security.js";
|
|
5
5
|
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, MAX_SETTINGS_ENV_VARS, MAX_SETTINGS_ENV_KEY_CHARS, MAX_SETTINGS_ENV_VALUE_CHARS, PERMISSION_MODE_WORDS, parseTaskSettings, settingsPermissionBucketIssue, skillListingBudgetFractionOk, skillListingMaxDescOk, stampEntryPermissionMode, taskHooksHonored, taskSettingsKeyIssue } from "../task-settings.js";
|
|
6
|
+
import { tightenOnlySeatIssue } from "../tighten-only-seats.js";
|
|
6
7
|
import { buildEntryModeClampNotice } from "../entry-mode-clamp-notice.js";
|
|
7
8
|
import { autonomyModeFloor } from "../runtime-governance.js";
|
|
8
9
|
import { taskBodyKeyIssue } from "../request-key-closure.js";
|
|
9
|
-
import { FILE_HISTORY_DISABLED_NO_RESTORE, fileHistoryRestoreConflict, inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
10
|
+
import { FILE_HISTORY_DISABLED_NO_RESTORE, fileHistoryRestoreConflict, fileHistoryRestoreKeysInBody, inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
10
11
|
import * as facts from "../capability-facts.js";
|
|
11
|
-
import {
|
|
12
|
+
import { buildHooksRefusal, parseHooksConfig, hooksMatcherIssue } from "../hooks/hook-runner.js";
|
|
12
13
|
import { judgeRequestWebSearch } from "../plugins/web-search.js";
|
|
13
|
-
import { normalizeApproachNotice, skillToolListOk,
|
|
14
|
+
import { normalizeApproachNotice, skillToolListOk, unknownTaskAgentModelRef, validateTaskAgents } from "../spec-fields.js";
|
|
15
|
+
import { allowSelectorWarningsOf, skillToolListsOverCap } from "../rule-entry-list.js";
|
|
16
|
+
import { limitFacts, limitRefusal } from "../limit-refusal.js";
|
|
17
|
+
import { fieldConflictFacts } from "../field-conflict.js";
|
|
18
|
+
import { echoCallerText, quotedCallerText } from "../caller-text-echo.js";
|
|
14
19
|
import { MAX_ADDITIONAL_DIRS } from "../task-cwd.js";
|
|
15
20
|
import { verifyRoundsFromBody } from "./verify-rounds.js";
|
|
16
21
|
import { skillCarriesRetiredManifest } from "./retired-skill-manifest.js";
|
|
17
22
|
import { resolveDevicePlacementIntent } from "./device-placement.js";
|
|
23
|
+
import { callerTrust, requestTrustRefusal } from "./caller-trust.js";
|
|
18
24
|
import { createRunAcceptance } from "../run-acceptance.js";
|
|
19
25
|
import { sendError, sendHttpError } from "./send.js";
|
|
26
|
+
import { refuseSubmitBody } from "./request-guards.js";
|
|
27
|
+
import { sqlWallsOf } from "../plugins/sql-driver.js";
|
|
20
28
|
import { ABSOLUTE_HOST_PATH_MAX, isAbsoluteHostPath, WEB_ADMIN_ENV } from "@sema-agent/settings-schema";
|
|
21
29
|
const APPROVAL_REACH_WORDS = APPROVAL_REACH.map((word) => JSON.stringify(word)).join(" / ");
|
|
22
30
|
export const MAX_SKILL_CONTENT_CHARS = 1_048_576;
|
|
23
31
|
export const MAX_SYSTEM_PROMPT_CHARS = 16_384;
|
|
24
32
|
export const MAX_OUTPUT_SCHEMA_CHARS = 32_768;
|
|
33
|
+
const MAX_JOB_ID_CHARS = 64;
|
|
34
|
+
const MAX_CLIENT_TIMEZONE_CHARS = 64;
|
|
35
|
+
const MAX_CLIENT_USER_EMAIL_CHARS = 256;
|
|
36
|
+
const MAX_SANDBOX_IMAGE_PROFILE_CHARS = 128;
|
|
37
|
+
const MAX_RESUME_AT_CHARS = 64;
|
|
38
|
+
const overCharsFacts = (field, v, cap) => (typeof v === "string" && v.length > cap ? limitFacts(field, "characters", v.length, cap) : undefined);
|
|
39
|
+
const multiAttemptFields = (body) => {
|
|
40
|
+
const out = [];
|
|
41
|
+
if (body.verify === true)
|
|
42
|
+
out.push("verify");
|
|
43
|
+
if (body.cascade === true)
|
|
44
|
+
out.push("cascade");
|
|
45
|
+
return out;
|
|
46
|
+
};
|
|
25
47
|
export function validateUserSkills(skills) {
|
|
26
48
|
if (skills === undefined)
|
|
27
49
|
return null;
|
|
28
50
|
if (!Array.isArray(skills))
|
|
29
|
-
return "skills must be an array of { name, description, content }";
|
|
30
|
-
for (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
return { message: "skills must be an array of { name, description, content }" };
|
|
52
|
+
for (let k = 0; k < skills.length; k++) {
|
|
53
|
+
const shape = userSkillShapeIssue(skills[k], k);
|
|
54
|
+
if (shape !== null)
|
|
55
|
+
return shape;
|
|
56
|
+
const over = skillToolListsOverCap(skills[k], `skills[${k}]`, "top");
|
|
57
|
+
if (over !== undefined)
|
|
58
|
+
return { message: over.message, ...(over.extra !== undefined ? { facts: over.extra } : {}) };
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
function userSkillShapeIssue(item, index) {
|
|
63
|
+
if (item === null || typeof item !== "object")
|
|
64
|
+
return { message: "each skill must be an object { name, description, content }" };
|
|
65
|
+
const s = item;
|
|
66
|
+
if (typeof s["name"] !== "string" || s["name"].length === 0)
|
|
67
|
+
return { message: "skill.name must be a non-empty string" };
|
|
68
|
+
if (typeof s["description"] !== "string")
|
|
69
|
+
return { message: "skill.description must be a string" };
|
|
70
|
+
if (typeof s["content"] !== "string" || s["content"].length === 0 || s["content"].length > MAX_SKILL_CONTENT_CHARS) {
|
|
71
|
+
const facts = overCharsFacts(`skills[${index}].content`, s["content"], MAX_SKILL_CONTENT_CHARS);
|
|
72
|
+
return { message: `skill.content must be a non-empty string of at most ${MAX_SKILL_CONTENT_CHARS} characters (the engine rejects skills over this size outright at load time)`, ...(facts === undefined ? {} : { facts }) };
|
|
73
|
+
}
|
|
74
|
+
if (s["baseDir"] !== undefined && !isAbsoluteHostPath(s["baseDir"])) {
|
|
75
|
+
const facts = overCharsFacts(`skills[${index}].baseDir`, s["baseDir"], ABSOLUTE_HOST_PATH_MAX);
|
|
76
|
+
return { message: `skill.baseDir must be an absolute path string of at most ${ABSOLUTE_HOST_PATH_MAX} characters with no ".." segment and no NUL byte (it is not resolved or read here — the engine only substitutes it into the skill's own text)`, ...(facts === undefined ? {} : { facts }) };
|
|
77
|
+
}
|
|
78
|
+
if (skillCarriesRetiredManifest(s))
|
|
79
|
+
return { message: SKILL_MANIFEST_RETIRED };
|
|
80
|
+
for (const key of ["allowedTools", "disallowedTools"]) {
|
|
81
|
+
if (s[key] !== undefined && !skillToolListOk(s[key]))
|
|
82
|
+
return { message: `skill.${key} must be an array of strings (permission-rule spellings: a tool name, mcp__<server> / mcp__<server>__*, Bash(<prefix>:*), Read(//<dir>/**))` };
|
|
50
83
|
}
|
|
51
84
|
return null;
|
|
52
85
|
}
|
|
@@ -60,15 +93,68 @@ function refuseUnavailableModel(res, config, field, ref) {
|
|
|
60
93
|
const hit = refusedCatalogEntry(ref, config.modelRefusals);
|
|
61
94
|
if (hit === undefined)
|
|
62
95
|
return false;
|
|
63
|
-
const message = modelUnavailableMessage(field, ref
|
|
96
|
+
const message = modelUnavailableMessage(field, ref, hit.name, hit.refusal);
|
|
64
97
|
sendError(res, 400, "request.model_unavailable", message);
|
|
65
98
|
return true;
|
|
66
99
|
}
|
|
100
|
+
const kindOf = (v) => (v === null ? "null" : Array.isArray(v) ? "an array" : typeof v === "object" ? "an object" : `a ${typeof v}`);
|
|
101
|
+
function hostPathListRefusal(field, raw) {
|
|
102
|
+
if (!Array.isArray(raw))
|
|
103
|
+
return { message: `${field} must be an array of absolute host paths` };
|
|
104
|
+
if (raw.length > MAX_ADDITIONAL_DIRS)
|
|
105
|
+
return limitRefusal(field, "entries", raw.length, MAX_ADDITIONAL_DIRS);
|
|
106
|
+
const index = raw.findIndex((d) => !isAbsoluteHostPath(d));
|
|
107
|
+
if (index < 0)
|
|
108
|
+
return undefined;
|
|
109
|
+
const bad = raw[index];
|
|
110
|
+
return { message: `${field}[${index}] must be a non-empty absolute host path (no '..' segments) — got ${typeof bad === "string" ? quotedCallerText(bad) : kindOf(bad)}`, facts: { field, reason: "bad_entry", index } };
|
|
111
|
+
}
|
|
67
112
|
const modelIdOf = (model) => (typeof model === "string" ? model : model?.id);
|
|
68
113
|
export function createAdmission(ctx) {
|
|
69
114
|
const { deps, readJson, runnerFor } = ctx;
|
|
70
115
|
async function prepareSpec(req, res, bodyIn, onTypedFailure, legFacts) {
|
|
71
116
|
const body = bodyIn ?? (await readJson(req));
|
|
117
|
+
{
|
|
118
|
+
const refusal = refuseSubmitBody(sqlWallsOf(deps.sqlEngine), body);
|
|
119
|
+
if (refusal !== null) {
|
|
120
|
+
const facts = { ...limitFacts("body", "bytes", refusal.bytes, refusal.limitBytes), wallSource: refusal.wallSource };
|
|
121
|
+
switch (refusal.wallSource) {
|
|
122
|
+
case "reported":
|
|
123
|
+
switch (refusal.by) {
|
|
124
|
+
case "row":
|
|
125
|
+
sendError(res, 413, "request.payload_too_large", `task body is ${refusal.bytes} bytes, over this deployment's ${refusal.limitBytes}-byte limit: the database stores each submitted task in one row and holds at most ${refusal.wallBytes} bytes per row — shrink the inline images / userAttachments, or ask the operator to raise the database's single-row limit (TiDB performance.txn-entry-size-limit)`, facts);
|
|
126
|
+
break;
|
|
127
|
+
case "packet":
|
|
128
|
+
sendError(res, 413, "request.payload_too_large", `task body is ${refusal.bytes} bytes as sent to the database (JSON text with SQL string escaping), over this deployment's ${refusal.limitBytes}-byte limit: the database takes each submitted task in one statement and accepts at most ${refusal.wallBytes} bytes per statement — shrink the inline images / userAttachments, or ask the operator to raise the database's max_allowed_packet`, facts);
|
|
129
|
+
break;
|
|
130
|
+
default: {
|
|
131
|
+
const unhandled = refusal.by;
|
|
132
|
+
throw new Error(`submit body refusal without an HTTP answer: ${String(unhandled)}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
case "assumed":
|
|
137
|
+
switch (refusal.by) {
|
|
138
|
+
case "row":
|
|
139
|
+
sendError(res, 413, "request.payload_too_large", `task body is ${refusal.bytes} bytes, over this deployment's ${refusal.limitBytes}-byte limit: the database's single-row limit was not read (engine facts not read yet, or the limit could not be read); refusing conservatively at ${refusal.wallBytes} bytes per row (the smallest documented single-row limit among the supported engines) — retry shortly; if it persists, ask the operator to let the service's database account read the engine's row-size limit`, facts);
|
|
140
|
+
break;
|
|
141
|
+
case "packet":
|
|
142
|
+
sendError(res, 413, "request.payload_too_large", `task body is ${refusal.bytes} bytes as sent to the database (JSON text with SQL string escaping), over this deployment's ${refusal.limitBytes}-byte limit: the database's statement limit was not read (engine facts not read yet, or max_allowed_packet could not be read); refusing conservatively at ${refusal.wallBytes} bytes per statement (smallest documented max_allowed_packet default) — retry shortly; if it persists, ask the operator to check that the service's database account can read max_allowed_packet`, facts);
|
|
143
|
+
break;
|
|
144
|
+
default: {
|
|
145
|
+
const unhandled = refusal.by;
|
|
146
|
+
throw new Error(`submit body refusal without an HTTP answer: ${String(unhandled)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
default: {
|
|
151
|
+
const unhandled = refusal.wallSource;
|
|
152
|
+
throw new Error(`submit body refusal without an HTTP answer: ${String(unhandled)}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
72
158
|
if (!body || typeof body.objective !== "string") {
|
|
73
159
|
sendError(res, 400, "request.field_invalid", "missing 'objective' string");
|
|
74
160
|
return null;
|
|
@@ -84,8 +170,8 @@ export function createAdmission(ctx) {
|
|
|
84
170
|
return null;
|
|
85
171
|
}
|
|
86
172
|
}
|
|
87
|
-
if (body.jobId !== undefined && (typeof body.jobId !== "string" || body.jobId.length === 0 || body.jobId.length >
|
|
88
|
-
sendError(res, 400, "request.field_invalid", "jobId must be a non-empty string of at most 64 characters");
|
|
173
|
+
if (body.jobId !== undefined && (typeof body.jobId !== "string" || body.jobId.length === 0 || body.jobId.length > MAX_JOB_ID_CHARS)) {
|
|
174
|
+
sendError(res, 400, "request.field_invalid", "jobId must be a non-empty string of at most 64 characters", overCharsFacts("jobId", body.jobId, MAX_JOB_ID_CHARS));
|
|
89
175
|
return null;
|
|
90
176
|
}
|
|
91
177
|
{
|
|
@@ -96,7 +182,7 @@ export function createAdmission(ctx) {
|
|
|
96
182
|
}
|
|
97
183
|
}
|
|
98
184
|
if (typeof body.systemPrompt === "string" && body.systemPrompt.length > MAX_SYSTEM_PROMPT_CHARS) {
|
|
99
|
-
sendError(res, 400, "request.field_invalid", `systemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters
|
|
185
|
+
sendError(res, 400, "request.field_invalid", `systemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters`, limitFacts("systemPrompt", "characters", body.systemPrompt.length, MAX_SYSTEM_PROMPT_CHARS));
|
|
100
186
|
return null;
|
|
101
187
|
}
|
|
102
188
|
if (body.appendSystemPrompt !== undefined) {
|
|
@@ -105,7 +191,7 @@ export function createAdmission(ctx) {
|
|
|
105
191
|
return null;
|
|
106
192
|
}
|
|
107
193
|
if (body.appendSystemPrompt.length > MAX_SYSTEM_PROMPT_CHARS) {
|
|
108
|
-
sendError(res, 400, "request.field_invalid", `appendSystemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters
|
|
194
|
+
sendError(res, 400, "request.field_invalid", `appendSystemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters`, limitFacts("appendSystemPrompt", "characters", body.appendSystemPrompt.length, MAX_SYSTEM_PROMPT_CHARS));
|
|
109
195
|
return null;
|
|
110
196
|
}
|
|
111
197
|
}
|
|
@@ -113,35 +199,13 @@ export function createAdmission(ctx) {
|
|
|
113
199
|
sendError(res, 400, "request.field_invalid", "cwd must be a non-empty absolute host path");
|
|
114
200
|
return null;
|
|
115
201
|
}
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
sendError(res, 400, "request.field_invalid", `additionalDirectories must have at most ${MAX_ADDITIONAL_DIRS} entries`);
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
const bad = addDirsRaw.find((d) => !isAbsoluteHostPath(d));
|
|
127
|
-
if (bad !== undefined) {
|
|
128
|
-
sendError(res, 400, "request.field_invalid", "each additionalDirectories entry must be a non-empty absolute host path (no '..' segments)");
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const addReadDirsRaw = body.additionalReadDirectories;
|
|
133
|
-
if (addReadDirsRaw !== undefined) {
|
|
134
|
-
if (!Array.isArray(addReadDirsRaw)) {
|
|
135
|
-
sendError(res, 400, "request.field_invalid", "additionalReadDirectories must be an array of absolute host paths");
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
if (addReadDirsRaw.length > MAX_ADDITIONAL_DIRS) {
|
|
139
|
-
sendError(res, 400, "request.field_invalid", `additionalReadDirectories must have at most ${MAX_ADDITIONAL_DIRS} entries`);
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
const badRead = addReadDirsRaw.find((d) => !isAbsoluteHostPath(d));
|
|
143
|
-
if (badRead !== undefined) {
|
|
144
|
-
sendError(res, 400, "request.field_invalid", "each additionalReadDirectories entry must be a non-empty absolute host path (no '..' segments)");
|
|
202
|
+
for (const field of ["additionalDirectories", "additionalReadDirectories"]) {
|
|
203
|
+
const raw = body[field];
|
|
204
|
+
if (raw === undefined)
|
|
205
|
+
continue;
|
|
206
|
+
const refusal = hostPathListRefusal(field, raw);
|
|
207
|
+
if (refusal !== undefined) {
|
|
208
|
+
sendError(res, 400, "request.field_invalid", refusal.message, refusal.facts);
|
|
145
209
|
return null;
|
|
146
210
|
}
|
|
147
211
|
}
|
|
@@ -160,14 +224,12 @@ export function createAdmission(ctx) {
|
|
|
160
224
|
}
|
|
161
225
|
}
|
|
162
226
|
if (typeof st.outputStyle === "string" && st.outputStyle.length > MAX_SETTINGS_OUTPUT_STYLE_CHARS) {
|
|
163
|
-
sendError(res, 400, "request.field_invalid", `settings.outputStyle must be at most ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} characters
|
|
227
|
+
sendError(res, 400, "request.field_invalid", `settings.outputStyle must be at most ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} characters`, limitFacts("settings.outputStyle", "characters", st.outputStyle.length, MAX_SETTINGS_OUTPUT_STYLE_CHARS));
|
|
164
228
|
return null;
|
|
165
229
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
body.appendSystemPrompt.length + 2 + st.outputStyle.length > MAX_SYSTEM_PROMPT_CHARS) {
|
|
170
|
-
sendError(res, 400, "request.field_conflict", `appendSystemPrompt + settings.outputStyle fold into one system-prompt block — combined they must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters (including the 2-char joiner)`);
|
|
230
|
+
const foldedChars = typeof st.outputStyle === "string" && st.outputStyle.length > 0 && typeof body.appendSystemPrompt === "string" ? body.appendSystemPrompt.length + 2 + st.outputStyle.length : 0;
|
|
231
|
+
if (foldedChars > MAX_SYSTEM_PROMPT_CHARS) {
|
|
232
|
+
sendError(res, 400, "request.field_conflict", `appendSystemPrompt + settings.outputStyle fold into one system-prompt block — combined they must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters (including the 2-char joiner)`, fieldConflictFacts("system_prompt_fold", ["appendSystemPrompt", "settings.outputStyle"], { count: foldedChars, cap: MAX_SYSTEM_PROMPT_CHARS }));
|
|
171
233
|
return null;
|
|
172
234
|
}
|
|
173
235
|
const perms = st.permissions;
|
|
@@ -182,6 +244,13 @@ export function createAdmission(ctx) {
|
|
|
182
244
|
return null;
|
|
183
245
|
}
|
|
184
246
|
}
|
|
247
|
+
{
|
|
248
|
+
const seatIssue = tightenOnlySeatIssue(st);
|
|
249
|
+
if (seatIssue) {
|
|
250
|
+
sendError(res, 400, "request.field_invalid", seatIssue.message, seatIssue.fields);
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
185
254
|
const envRaw = st.env;
|
|
186
255
|
if (envRaw !== undefined && envRaw !== null) {
|
|
187
256
|
if (typeof envRaw !== "object" || Array.isArray(envRaw)) {
|
|
@@ -190,12 +259,16 @@ export function createAdmission(ctx) {
|
|
|
190
259
|
}
|
|
191
260
|
const entries = Object.entries(envRaw);
|
|
192
261
|
if (entries.length > MAX_SETTINGS_ENV_VARS) {
|
|
193
|
-
sendError(res, 400, "request.field_invalid", `settings.env must have at most ${MAX_SETTINGS_ENV_VARS} variables
|
|
262
|
+
sendError(res, 400, "request.field_invalid", `settings.env must have at most ${MAX_SETTINGS_ENV_VARS} variables`, limitFacts("settings.env", "entries", entries.length, MAX_SETTINGS_ENV_VARS));
|
|
194
263
|
return null;
|
|
195
264
|
}
|
|
196
265
|
for (const [k, val] of entries) {
|
|
197
|
-
|
|
198
|
-
|
|
266
|
+
const keyOver = k.length > MAX_SETTINGS_ENV_KEY_CHARS;
|
|
267
|
+
const valueOver = typeof val === "string" && val.length > MAX_SETTINGS_ENV_VALUE_CHARS;
|
|
268
|
+
if (keyOver || valueOver) {
|
|
269
|
+
const field = `settings.env.${echoCallerText(k, { maxChars: MAX_SETTINGS_ENV_KEY_CHARS })}`;
|
|
270
|
+
const facts = keyOver ? limitFacts(field, "characters", k.length, MAX_SETTINGS_ENV_KEY_CHARS) : limitFacts(field, "characters", val.length, MAX_SETTINGS_ENV_VALUE_CHARS);
|
|
271
|
+
sendError(res, 400, "request.field_invalid", `settings.env keys must be ≤${MAX_SETTINGS_ENV_KEY_CHARS} chars and values ≤${MAX_SETTINGS_ENV_VALUE_CHARS} chars`, facts);
|
|
199
272
|
return null;
|
|
200
273
|
}
|
|
201
274
|
}
|
|
@@ -215,12 +288,13 @@ export function createAdmission(ctx) {
|
|
|
215
288
|
if (st.hooks !== undefined && st.hooks !== null) {
|
|
216
289
|
const hooksParsed = parseHooksConfig(st.hooks);
|
|
217
290
|
if (!hooksParsed.config) {
|
|
218
|
-
|
|
291
|
+
const refusal = buildHooksRefusal(hooksParsed.issue);
|
|
292
|
+
sendError(res, 400, "request.field_invalid", refusal.message, { field: refusal.field, detail: refusal.detail });
|
|
219
293
|
return null;
|
|
220
294
|
}
|
|
221
|
-
const toolMatcher =
|
|
295
|
+
const toolMatcher = hooksMatcherIssue(hooksParsed.config, taskHooksHonored(deps.config) ? "regex" : "literal");
|
|
222
296
|
if (toolMatcher !== undefined) {
|
|
223
|
-
const refusal =
|
|
297
|
+
const refusal = buildHooksRefusal(toolMatcher);
|
|
224
298
|
sendError(res, 400, "request.field_invalid", refusal.message, { field: refusal.field, detail: refusal.detail });
|
|
225
299
|
return null;
|
|
226
300
|
}
|
|
@@ -235,18 +309,19 @@ export function createAdmission(ctx) {
|
|
|
235
309
|
}
|
|
236
310
|
const skillsErr = validateUserSkills(body.skills);
|
|
237
311
|
if (skillsErr) {
|
|
238
|
-
sendError(res, 400, "request.field_invalid", skillsErr);
|
|
312
|
+
sendError(res, 400, "request.field_invalid", skillsErr.message, skillsErr.facts);
|
|
239
313
|
return null;
|
|
240
314
|
}
|
|
241
315
|
if (Array.isArray(body.images)) {
|
|
242
316
|
if (body.images.length > MAX_IMAGES_PER_REQUEST) {
|
|
243
|
-
sendError(res, 413, "request.payload_too_large", `at most ${MAX_IMAGES_PER_REQUEST} images per request
|
|
317
|
+
sendError(res, 413, "request.payload_too_large", `at most ${MAX_IMAGES_PER_REQUEST} images per request`, limitFacts("images", "entries", body.images.length, MAX_IMAGES_PER_REQUEST));
|
|
244
318
|
return null;
|
|
245
319
|
}
|
|
246
|
-
for (const img of body.images) {
|
|
320
|
+
for (const [i, img] of body.images.entries()) {
|
|
247
321
|
const data = img.data;
|
|
248
|
-
|
|
249
|
-
|
|
322
|
+
const dataBytes = typeof data === "string" ? Buffer.byteLength(data, "utf8") : 0;
|
|
323
|
+
if (dataBytes > MAX_IMAGE_BASE64_BYTES) {
|
|
324
|
+
sendError(res, 413, "request.payload_too_large", `each inline image must be at most ${MAX_IMAGE_BASE64_BYTES} base64 bytes (the engine's inline-image limit — the model API's 5 MB image cap)`, limitFacts(`images[${i}].data`, "bytes", dataBytes, MAX_IMAGE_BASE64_BYTES));
|
|
250
325
|
return null;
|
|
251
326
|
}
|
|
252
327
|
}
|
|
@@ -257,17 +332,17 @@ export function createAdmission(ctx) {
|
|
|
257
332
|
sendError(res, 400, "request.field_invalid", "clientContext must be an object");
|
|
258
333
|
return null;
|
|
259
334
|
}
|
|
260
|
-
if (cc.timeZone !== undefined && (typeof cc.timeZone !== "string" || cc.timeZone.length >
|
|
261
|
-
sendError(res, 400, "request.field_invalid", "clientContext.timeZone must be a string of at most 64 characters");
|
|
335
|
+
if (cc.timeZone !== undefined && (typeof cc.timeZone !== "string" || cc.timeZone.length > MAX_CLIENT_TIMEZONE_CHARS)) {
|
|
336
|
+
sendError(res, 400, "request.field_invalid", "clientContext.timeZone must be a string of at most 64 characters", overCharsFacts("clientContext.timeZone", cc.timeZone, MAX_CLIENT_TIMEZONE_CHARS));
|
|
262
337
|
return null;
|
|
263
338
|
}
|
|
264
|
-
if (cc.userEmail !== undefined && (typeof cc.userEmail !== "string" || cc.userEmail.length >
|
|
265
|
-
sendError(res, 400, "request.field_invalid", "clientContext.userEmail must be a string of at most 256 characters");
|
|
339
|
+
if (cc.userEmail !== undefined && (typeof cc.userEmail !== "string" || cc.userEmail.length > MAX_CLIENT_USER_EMAIL_CHARS)) {
|
|
340
|
+
sendError(res, 400, "request.field_invalid", "clientContext.userEmail must be a string of at most 256 characters", overCharsFacts("clientContext.userEmail", cc.userEmail, MAX_CLIENT_USER_EMAIL_CHARS));
|
|
266
341
|
return null;
|
|
267
342
|
}
|
|
268
343
|
}
|
|
269
|
-
if (body.sandboxImageProfile !== undefined && (typeof body.sandboxImageProfile !== "string" || body.sandboxImageProfile.length === 0 || body.sandboxImageProfile.length >
|
|
270
|
-
sendError(res, 400, "request.field_invalid", "sandboxImageProfile must be a non-empty string of at most 128 characters");
|
|
344
|
+
if (body.sandboxImageProfile !== undefined && (typeof body.sandboxImageProfile !== "string" || body.sandboxImageProfile.length === 0 || body.sandboxImageProfile.length > MAX_SANDBOX_IMAGE_PROFILE_CHARS)) {
|
|
345
|
+
sendError(res, 400, "request.field_invalid", "sandboxImageProfile must be a non-empty string of at most 128 characters", overCharsFacts("sandboxImageProfile", body.sandboxImageProfile, MAX_SANDBOX_IMAGE_PROFILE_CHARS));
|
|
271
346
|
return null;
|
|
272
347
|
}
|
|
273
348
|
if (body.capabilitiesNeeded !== undefined && (!Array.isArray(body.capabilitiesNeeded) || body.capabilitiesNeeded.some((c) => typeof c !== "string"))) {
|
|
@@ -275,11 +350,11 @@ export function createAdmission(ctx) {
|
|
|
275
350
|
return null;
|
|
276
351
|
}
|
|
277
352
|
if (Array.isArray(body.capabilitiesNeeded) && body.capabilitiesNeeded.length > 0 && (typeof body.sandboxImageProfile !== "string" || body.sandboxImageProfile.length === 0)) {
|
|
278
|
-
sendError(res, 400, "request.field_conflict", "capabilitiesNeeded requires sandboxImageProfile (it constrains the selected image)");
|
|
353
|
+
sendError(res, 400, "request.field_conflict", "capabilitiesNeeded requires sandboxImageProfile (it constrains the selected image)", fieldConflictFacts("image_profile", ["capabilitiesNeeded", "sandboxImageProfile"]));
|
|
279
354
|
return null;
|
|
280
355
|
}
|
|
281
356
|
if (typeof body.sandboxImageProfile === "string" && body.sandboxImageProfile.length > 0 && (body.cascade === true || body.verify === true)) {
|
|
282
|
-
sendError(res, 400, "request.field_conflict", "sandboxImageProfile is not supported together with cascade/verify in v1 (the per-task image would not bind to the cascade rungs / verifier sub-run)");
|
|
357
|
+
sendError(res, 400, "request.field_conflict", "sandboxImageProfile is not supported together with cascade/verify in v1 (the per-task image would not bind to the cascade rungs / verifier sub-run)", fieldConflictFacts("cascade_verify", ["sandboxImageProfile", ...multiAttemptFields(body)]));
|
|
283
358
|
return null;
|
|
284
359
|
}
|
|
285
360
|
if (body.outputSchema !== undefined) {
|
|
@@ -287,8 +362,9 @@ export function createAdmission(ctx) {
|
|
|
287
362
|
sendError(res, 400, "request.field_invalid", "outputSchema must be a JSON Schema object");
|
|
288
363
|
return null;
|
|
289
364
|
}
|
|
290
|
-
|
|
291
|
-
|
|
365
|
+
const schemaChars = JSON.stringify(body.outputSchema).length;
|
|
366
|
+
if (schemaChars > MAX_OUTPUT_SCHEMA_CHARS) {
|
|
367
|
+
sendError(res, 400, "request.field_invalid", `outputSchema must serialize to at most ${MAX_OUTPUT_SCHEMA_CHARS} characters`, limitFacts("outputSchema", "characters", schemaChars, MAX_OUTPUT_SCHEMA_CHARS));
|
|
292
368
|
return null;
|
|
293
369
|
}
|
|
294
370
|
}
|
|
@@ -297,12 +373,12 @@ export function createAdmission(ctx) {
|
|
|
297
373
|
return null;
|
|
298
374
|
}
|
|
299
375
|
if (body.resumeAt !== undefined) {
|
|
300
|
-
if (typeof body.resumeAt !== "string" || body.resumeAt.length === 0 || body.resumeAt.length >
|
|
301
|
-
sendError(res, 400, "request.field_invalid", "resumeAt must be a non-empty message eventId string (≤64 chars)");
|
|
376
|
+
if (typeof body.resumeAt !== "string" || body.resumeAt.length === 0 || body.resumeAt.length > MAX_RESUME_AT_CHARS) {
|
|
377
|
+
sendError(res, 400, "request.field_invalid", "resumeAt must be a non-empty message eventId string (≤64 chars)", overCharsFacts("resumeAt", body.resumeAt, MAX_RESUME_AT_CHARS));
|
|
302
378
|
return null;
|
|
303
379
|
}
|
|
304
380
|
if (body.verify === true || body.cascade === true) {
|
|
305
|
-
sendError(res, 400, "request.field_conflict", "resumeAt is not supported with verify or cascade (those start a fresh/replaced session)");
|
|
381
|
+
sendError(res, 400, "request.field_conflict", "resumeAt is not supported with verify or cascade (those start a fresh/replaced session)", fieldConflictFacts("cascade_verify", ["resumeAt", ...multiAttemptFields(body)]));
|
|
306
382
|
return null;
|
|
307
383
|
}
|
|
308
384
|
}
|
|
@@ -312,7 +388,7 @@ export function createAdmission(ctx) {
|
|
|
312
388
|
return null;
|
|
313
389
|
}
|
|
314
390
|
if (body.resumeAt === undefined) {
|
|
315
|
-
sendError(res, 400, "request.field_conflict", "resumeAtMode requires resumeAt (it qualifies the rewind target)");
|
|
391
|
+
sendError(res, 400, "request.field_conflict", "resumeAtMode requires resumeAt (it qualifies the rewind target)", fieldConflictFacts("resume_anchor", ["resumeAtMode", "resumeAt"]));
|
|
316
392
|
return null;
|
|
317
393
|
}
|
|
318
394
|
}
|
|
@@ -363,7 +439,7 @@ export function createAdmission(ctx) {
|
|
|
363
439
|
}
|
|
364
440
|
}
|
|
365
441
|
if (fileHistoryRestoreConflict(body)) {
|
|
366
|
-
sendError(res, 400, "request.field_conflict", FILE_HISTORY_DISABLED_NO_RESTORE);
|
|
442
|
+
sendError(res, 400, "request.field_conflict", FILE_HISTORY_DISABLED_NO_RESTORE, fieldConflictFacts("file_history_restore", ["fileHistory", ...fileHistoryRestoreKeysInBody(body)]));
|
|
367
443
|
return null;
|
|
368
444
|
}
|
|
369
445
|
if (body.requireExistingSession !== undefined && typeof body.requireExistingSession !== "boolean") {
|
|
@@ -461,7 +537,7 @@ export function createAdmission(ctx) {
|
|
|
461
537
|
if (body.agents !== undefined) {
|
|
462
538
|
const agentsErr = validateTaskAgents(body.agents);
|
|
463
539
|
if (agentsErr) {
|
|
464
|
-
sendError(res, 400, "request.field_invalid", agentsErr);
|
|
540
|
+
sendError(res, 400, "request.field_invalid", agentsErr.message, agentsErr.facts);
|
|
465
541
|
return null;
|
|
466
542
|
}
|
|
467
543
|
const agentsBare = deps.config.models ?? {};
|
|
@@ -470,7 +546,7 @@ export function createAdmission(ctx) {
|
|
|
470
546
|
if (um !== undefined && refuseUnavailableModel(res, deps.config, `agents[${um.index}].model`, um.ref))
|
|
471
547
|
return null;
|
|
472
548
|
if (um !== undefined) {
|
|
473
|
-
sendError(res, 400, "request.unknown_reference", `unknown agents[${um.index}].model "${um.ref
|
|
549
|
+
sendError(res, 400, "request.unknown_reference", `unknown agents[${um.index}].model "${echoModelRef(um.ref)}" — not in the configured catalog (a catalog name or tier word)`, { available: mentionableNames(deps.config, agentsCatalog) });
|
|
474
550
|
return null;
|
|
475
551
|
}
|
|
476
552
|
}
|
|
@@ -497,9 +573,12 @@ export function createAdmission(ctx) {
|
|
|
497
573
|
return null;
|
|
498
574
|
}
|
|
499
575
|
}
|
|
500
|
-
if (body.disableSkills === true
|
|
501
|
-
|
|
502
|
-
|
|
576
|
+
if (body.disableSkills === true) {
|
|
577
|
+
const skillSeats = [...((body.skills?.length ?? 0) > 0 ? ["skills"] : []), ...(body.agents ?? []).flatMap((a, i) => ((a.skills?.length ?? 0) > 0 ? [`agents[${i}].skills`] : []))];
|
|
578
|
+
if (skillSeats.length > 0) {
|
|
579
|
+
sendError(res, 400, "request.field_conflict", "disableSkills: true means this run installs no skill at all (not the deployment's, not the request's), so it cannot come with a non-empty skills or agents[].skills — send one or the other", fieldConflictFacts("skills_disabled", ["disableSkills", ...skillSeats]));
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
503
582
|
}
|
|
504
583
|
{
|
|
505
584
|
const v = body.userInvokedSkills;
|
|
@@ -564,7 +643,7 @@ export function createAdmission(ctx) {
|
|
|
564
643
|
if (matchCatalogModel(body.model, catalog, deps.config.modelRefusals) === undefined) {
|
|
565
644
|
if (refuseUnavailableModel(res, deps.config, "model", body.model))
|
|
566
645
|
return null;
|
|
567
|
-
sendError(res, 400, "request.unknown_reference", `unknown model "${body.model
|
|
646
|
+
sendError(res, 400, "request.unknown_reference", `unknown model "${echoModelRef(body.model)}" — not in the configured catalog (name, tier word, or id)`, { available: mentionableNames(deps.config, catalog) });
|
|
568
647
|
return null;
|
|
569
648
|
}
|
|
570
649
|
}
|
|
@@ -578,7 +657,7 @@ export function createAdmission(ctx) {
|
|
|
578
657
|
if (matchCatalogModel(body.compactionModel, catalog, deps.config.modelRefusals) === undefined) {
|
|
579
658
|
if (refuseUnavailableModel(res, deps.config, "compactionModel", body.compactionModel))
|
|
580
659
|
return null;
|
|
581
|
-
sendError(res, 400, "request.unknown_reference", `unknown compactionModel "${body.compactionModel
|
|
660
|
+
sendError(res, 400, "request.unknown_reference", `unknown compactionModel "${echoModelRef(body.compactionModel)}" — not in the configured catalog (name, tier word, or id)`, { available: mentionableNames(deps.config, catalog) });
|
|
582
661
|
return null;
|
|
583
662
|
}
|
|
584
663
|
}
|
|
@@ -619,17 +698,24 @@ export function createAdmission(ctx) {
|
|
|
619
698
|
const verify = verifyRoundsFromBody(body);
|
|
620
699
|
const cascade = body.cascade === true;
|
|
621
700
|
if (cascade && verify) {
|
|
622
|
-
sendError(res, 400, "request.field_conflict", "verify and cascade are mutually exclusive (verify = adversarial gate; cascade = cheap→strong ladder)");
|
|
701
|
+
sendError(res, 400, "request.field_conflict", "verify and cascade are mutually exclusive (verify = adversarial gate; cascade = cheap→strong ladder)", fieldConflictFacts("cascade_verify", ["verify", "cascade"]));
|
|
623
702
|
return null;
|
|
624
703
|
}
|
|
625
704
|
if (body.suggestNextPrompts && (verify || cascade)) {
|
|
626
|
-
sendError(res, 400, "request.field_conflict", "suggestNextPrompts is not supported with verify or cascade (those return a result, not a streamed run)");
|
|
705
|
+
sendError(res, 400, "request.field_conflict", "suggestNextPrompts is not supported with verify or cascade (those return a result, not a streamed run)", fieldConflictFacts("cascade_verify", ["suggestNextPrompts", ...multiAttemptFields(body)]));
|
|
627
706
|
return null;
|
|
628
707
|
}
|
|
629
708
|
if (cascade && deps.config.cascadeLadder.length === 0) {
|
|
630
709
|
sendError(res, 400, "request.precondition_unmet", "cascade requested but no ladder configured — set MODEL_CASCADE_LADDER (catalog model names, cheapest→strongest)");
|
|
631
710
|
return null;
|
|
632
711
|
}
|
|
712
|
+
{
|
|
713
|
+
const refusal = requestTrustRefusal({ permissions: parseTaskSettings(body.settings).settings?.permissions, skills: body.skills, userInvokedSkills: body.userInvokedSkills }, callerTrust(req, deps.config));
|
|
714
|
+
if (refusal !== undefined) {
|
|
715
|
+
sendError(res, 400, "request.field_invalid", refusal.message, refusal.facts);
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
633
719
|
const { body: admitted, entry: entryMode } = stampEntryPermissionMode(body, autonomyModeFloor(deps.config.autonomy));
|
|
634
720
|
try {
|
|
635
721
|
const auth = deps.authorize ? await deps.authorize({ req, body: admitted }) : undefined;
|
|
@@ -647,7 +733,8 @@ export function createAdmission(ctx) {
|
|
|
647
733
|
const acceptance = createRunAcceptance({ sessionTitler: deps.sessionTitler }, { ...(spec.sessionId ? { sessionId: spec.sessionId } : {}), objective: spec.objective, ...(model !== undefined ? { model } : {}) });
|
|
648
734
|
const clampNotice = buildEntryModeClampNotice(entryMode, spec.sessionId);
|
|
649
735
|
const pendingNotices = clampNotice !== undefined ? [clampNotice, ...engineNotices] : engineNotices;
|
|
650
|
-
|
|
736
|
+
const warnings = allowSelectorWarningsOf(admitted, spec.tools ?? []);
|
|
737
|
+
return { spec, runner: runnerFor(spec), auth, verify, cascade, jobId: admitted.jobId, body: admitted, acceptance, ...(bindingIntent === undefined ? {} : { bindingIntent }), ...(pendingNotices.length > 0 ? { engineNotices: pendingNotices } : {}), ...(warnings.length > 0 ? { warnings } : {}) };
|
|
651
738
|
}
|
|
652
739
|
catch (err) {
|
|
653
740
|
if (err instanceof HttpError) {
|