@sema-agent/server 7.132.0 → 7.133.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +266 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +174 -55
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +79 -19
- package/dist/approval-card.js +44 -13
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +6 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -0
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +5 -6
- package/dist/boot/stores.js +2 -2
- package/dist/boot/web-admin.d.ts +4 -0
- package/dist/boot/web-admin.js +151 -63
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/caller-text-echo.d.ts +9 -6
- package/dist/caller-text-echo.js +8 -11
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +27 -4
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +103 -60
- package/dist/http/approval-sweeps.js +55 -18
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +16 -16
- package/dist/http/checkpoint-ctx.js +13 -10
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +10 -4
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +34 -10
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +48 -23
- package/dist/http/principal-gate.js +39 -12
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/request-guards.d.ts +16 -23
- package/dist/http/request-guards.js +30 -15
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +3 -4
- package/dist/http/resume-legs.js +126 -69
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +5 -1
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +33 -106
- package/dist/http/routes/session-sync.js +15 -28
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +50 -14
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +17 -18
- package/dist/http/server.js +15 -13
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.js +4 -3
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +10 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/mcp-tool-faces.js +1 -3
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +3 -17
- package/dist/observability/prompt-manifest.js +45 -42
- package/dist/observability/tool-trace.js +9 -9
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
- package/dist/plugins/checkpoint-store-sql.js +20 -2
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +6 -1
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +110 -5
- package/dist/plugins/one-time-migrations.js +320 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +29 -6
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +28 -4
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +36 -6
- package/dist/runs.d.ts +10 -9
- package/dist/runs.js +21 -3
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +7 -66
- package/dist/task-settings.d.ts +89 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +303 -87
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +104 -22
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +3 -2
- package/dist/trace/project.d.ts +80 -12
- package/dist/trace/project.js +41 -28
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +298 -2
- package/dist/trace/wire-projection-faces.js +154 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +4 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +7 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SessionError, materializeA2aTools, materializeMcpTools, sanitizePathComponent } from "@sema-agent/core";
|
|
2
2
|
import { a2aForScenario, mcpForScenario } from "../../web-admin-client/facade.js";
|
|
3
|
-
import { HttpError, isUuidShape, legacyUnownedSessionOk } from "../../security.js";
|
|
3
|
+
import { HttpError, isUuidShape, legacyUnownedSessionOk, sessionOwnerCellOf } from "../../security.js";
|
|
4
4
|
import { windowMessages, truncateMessageBlobs, redactSessionViewForRead } from "../../audit.js";
|
|
5
5
|
import { redactSecrets } from "../../trace/redact.js";
|
|
6
6
|
import { recordFailOpen } from "../../observability/fail-open.js";
|
|
@@ -9,18 +9,19 @@ import { sentMemoryComplianceFailure } from "../memory-compliance-failure-reply.
|
|
|
9
9
|
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, MAX_SETTINGS_ENV_VARS, MAX_SETTINGS_ENV_KEY_CHARS, MAX_SETTINGS_ENV_VALUE_CHARS } from "../../task-settings.js";
|
|
10
10
|
import { readWritableSessionPermissionRules } from "../../session-policy-wire.js";
|
|
11
11
|
import { sendJson, sendError, sendSessionError, sendSessionPolicyError, sseHeaders, httpErrorBody } from "../send.js";
|
|
12
|
-
import { gatedPrincipal, explicitOperatorOk, sessionOwnerReadable, sendPrincipalRefusal, sendUnauthorized } from "../principal-gate.js";
|
|
12
|
+
import { gatedPrincipal, explicitOperatorOk, sessionCallerOf, sessionOwnerReadable, sendPrincipalRefusal, sendUnauthorized } from "../principal-gate.js";
|
|
13
|
+
import { runRowReadableOnSessionFace } from "../owner-access.js";
|
|
13
14
|
import { assertNever, SESSION_NOT_FOUND_MESSAGE } from "../route-ctx.js";
|
|
14
15
|
import * as facts from "../../capability-facts.js";
|
|
15
16
|
import { rosterAgentId } from "./agents-roster.js";
|
|
16
17
|
import { projectSessionListRow } from "./sessions-list.js";
|
|
17
18
|
import { readSessionRowPatch } from "../../session-row.js";
|
|
19
|
+
import { buildBoundedToolNames } from "../../panel-tool-names.js";
|
|
18
20
|
const MCP_STATUS_TTL_MS = 5_000;
|
|
19
21
|
const A2A_STATUS_TTL_MS = 5_000;
|
|
20
22
|
const A2A_MATERIALIZE_TIMEOUT_MS = 10_000;
|
|
21
23
|
const MEMORY_STATUS_TTL_MS = 5_000;
|
|
22
24
|
const LAST_LEG_LEDGER_TIMEOUT_MS = 2_000;
|
|
23
|
-
const A2A_PANEL_MAX_TOOL_NAMES = 200;
|
|
24
25
|
export function createSessionsLocal() {
|
|
25
26
|
return {
|
|
26
27
|
sseConnections: 0,
|
|
@@ -30,11 +31,11 @@ export function createSessionsLocal() {
|
|
|
30
31
|
memoryStatusCache: new Map(),
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
|
-
async function lastLegMcpFor(deps, sessionId,
|
|
34
|
+
async function lastLegMcpFor(deps, sessionId, caller) {
|
|
34
35
|
let timer;
|
|
35
36
|
try {
|
|
36
37
|
return await Promise.race([
|
|
37
|
-
readLastLegMcp(deps, sessionId,
|
|
38
|
+
readLastLegMcp(deps, sessionId, caller),
|
|
38
39
|
new Promise((r) => { timer = setTimeout(() => { recordFailOpen("server.mcp-panel.last-leg-unreadable", `ledger read exceeded ${LAST_LEG_LEDGER_TIMEOUT_MS}ms`); r(undefined); }, LAST_LEG_LEDGER_TIMEOUT_MS); }),
|
|
39
40
|
]);
|
|
40
41
|
}
|
|
@@ -47,14 +48,14 @@ async function lastLegMcpFor(deps, sessionId, principal) {
|
|
|
47
48
|
clearTimeout(timer);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
async function readLastLegMcp(deps, sessionId,
|
|
51
|
+
async function readLastLegMcp(deps, sessionId, caller) {
|
|
51
52
|
const runStore = deps.runStore;
|
|
52
53
|
if (!runStore || sessionId === null)
|
|
53
54
|
return undefined;
|
|
54
55
|
const latest = await runStore.latestRunForSession(sessionId);
|
|
55
56
|
if (latest === undefined)
|
|
56
57
|
return undefined;
|
|
57
|
-
if (!
|
|
58
|
+
if (!runRowReadableOnSessionFace(deps, caller, latest.owner, "owner_or_operator"))
|
|
58
59
|
return undefined;
|
|
59
60
|
const events = await runStore.getEvents(latest.taskId, 0);
|
|
60
61
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
@@ -79,7 +80,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
79
80
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
80
81
|
return undefined;
|
|
81
82
|
}
|
|
82
|
-
if (!sessionOwnerOk(req, res, owner))
|
|
83
|
+
if (!sessionOwnerOk(req, res, await sessionOwnerCellOf(deps.sessionStorage, sessionId, owner)))
|
|
83
84
|
return undefined;
|
|
84
85
|
}
|
|
85
86
|
let audit;
|
|
@@ -95,7 +96,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
95
96
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
96
97
|
return undefined;
|
|
97
98
|
}
|
|
98
|
-
if (!sessionOwnerOk(req, res, audit.owner))
|
|
99
|
+
if (!sessionOwnerOk(req, res, await sessionOwnerCellOf(deps.sessionStorage, sessionId, audit.owner)))
|
|
99
100
|
return undefined;
|
|
100
101
|
return audit;
|
|
101
102
|
};
|
|
@@ -138,12 +139,13 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
138
139
|
}
|
|
139
140
|
{
|
|
140
141
|
if (match.decl.id === "session-mcp") {
|
|
141
|
-
const
|
|
142
|
+
const caller = sessionCallerOf(req, deps);
|
|
143
|
+
const principal = caller.principal;
|
|
142
144
|
if (deps.config.requirePrincipal && !principal) {
|
|
143
145
|
sendPrincipalRefusal(res, req, deps.config);
|
|
144
146
|
return;
|
|
145
147
|
}
|
|
146
|
-
const lastLegMcp = await lastLegMcpFor(deps, safeDecode(match.params.sessionId),
|
|
148
|
+
const lastLegMcp = await lastLegMcpFor(deps, safeDecode(match.params.sessionId), caller);
|
|
147
149
|
const ledgerHalf = lastLegMcp === undefined ? {} : { lastLegMcp };
|
|
148
150
|
let scenarioName;
|
|
149
151
|
try {
|
|
@@ -233,13 +235,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
233
235
|
...(s.agentName ? { agentName: s.agentName } : {}),
|
|
234
236
|
...(s.agentDescription ? { agentDescription: s.agentDescription } : {}),
|
|
235
237
|
...(s.endpoint ? { endpoint: redactSecrets(String(s.endpoint)).slice(0, 2048) } : {}),
|
|
236
|
-
...(s.toolNames
|
|
237
|
-
? {
|
|
238
|
-
toolCount: s.toolNames.length,
|
|
239
|
-
toolNames: s.toolNames.slice(0, A2A_PANEL_MAX_TOOL_NAMES),
|
|
240
|
-
...(s.toolNames.length > A2A_PANEL_MAX_TOOL_NAMES ? { toolNamesTruncated: true } : {}),
|
|
241
|
-
}
|
|
242
|
-
: {}),
|
|
238
|
+
...(s.toolNames ? { toolCount: s.toolNames.length, ...buildBoundedToolNames(s.toolNames) } : {}),
|
|
243
239
|
...(s.error ? { error: redactSecrets(String(s.error)).slice(0, 200) } : {}),
|
|
244
240
|
})),
|
|
245
241
|
};
|
|
@@ -277,7 +273,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
277
273
|
return;
|
|
278
274
|
}
|
|
279
275
|
owner = head.owner;
|
|
280
|
-
if (!sessionOwnerOk(req, res, owner ?? null))
|
|
276
|
+
if (!sessionOwnerOk(req, res, await sessionOwnerCellOf(deps.sessionStorage, headSession, owner ?? null)))
|
|
281
277
|
return;
|
|
282
278
|
leafId = head.leafId;
|
|
283
279
|
}
|
|
@@ -287,7 +283,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
287
283
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
288
284
|
return;
|
|
289
285
|
}
|
|
290
|
-
if (!sessionOwnerOk(req, res, owner ?? null))
|
|
286
|
+
if (!sessionOwnerOk(req, res, await sessionOwnerCellOf(deps.sessionStorage, headSession, owner ?? null)))
|
|
291
287
|
return;
|
|
292
288
|
leafId = await getLeafId(headSession);
|
|
293
289
|
}
|
|
@@ -344,13 +340,13 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
344
340
|
return;
|
|
345
341
|
}
|
|
346
342
|
sse.sseOwnerLookups++;
|
|
347
|
-
const
|
|
348
|
-
void
|
|
343
|
+
const cellP = ownerOf(evSession).then((o) => (o === undefined ? undefined : sessionOwnerCellOf(evFact.sessionStorage, evSession, o)));
|
|
344
|
+
void cellP.catch(() => undefined).then(() => { sse.sseOwnerLookups--; });
|
|
349
345
|
let stallTimer;
|
|
350
|
-
let
|
|
346
|
+
let cell;
|
|
351
347
|
try {
|
|
352
|
-
|
|
353
|
-
|
|
348
|
+
cell = await Promise.race([
|
|
349
|
+
cellP,
|
|
354
350
|
new Promise((r) => { stallTimer = setTimeout(() => r("__stall__"), stallBound); stallTimer.unref?.(); }),
|
|
355
351
|
]);
|
|
356
352
|
}
|
|
@@ -360,21 +356,22 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
360
356
|
}
|
|
361
357
|
if (closed)
|
|
362
358
|
return;
|
|
363
|
-
if (
|
|
359
|
+
if (cell === "__stall__") {
|
|
364
360
|
cleanup();
|
|
365
361
|
res.setHeader("retry-after", "5");
|
|
366
362
|
sendError(res, 503, "state.sse_owner_lookup_stalled", "session-events owner lookup stalled — retry");
|
|
367
363
|
return;
|
|
368
364
|
}
|
|
369
|
-
if (
|
|
365
|
+
if (cell === undefined) {
|
|
370
366
|
cleanup();
|
|
371
367
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
372
368
|
return;
|
|
373
369
|
}
|
|
374
|
-
if (!sessionOwnerOk(req, res,
|
|
370
|
+
if (!sessionOwnerOk(req, res, cell)) {
|
|
375
371
|
cleanup();
|
|
376
372
|
return;
|
|
377
373
|
}
|
|
374
|
+
const owner = cell.owner;
|
|
378
375
|
const q = new URLSearchParams(match.search);
|
|
379
376
|
const lastLeafId = q.get("lastLeafId");
|
|
380
377
|
let first = true;
|
|
@@ -678,7 +675,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
678
675
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
679
676
|
return;
|
|
680
677
|
}
|
|
681
|
-
if (!sessionOwnerOk(req, res, face.owner))
|
|
678
|
+
if (!sessionOwnerOk(req, res, await sessionOwnerCellOf(store, sessionId, face.owner)))
|
|
682
679
|
return;
|
|
683
680
|
const read = readSessionRowPatch(await readJson(req));
|
|
684
681
|
if ("problem" in read) {
|
|
@@ -717,7 +714,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
717
714
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
718
715
|
return;
|
|
719
716
|
}
|
|
720
|
-
if (!scope.fleetWide && owner !== scope.gateOwner && !legacyUnownedSessionOk(deps.config.requirePrincipal,
|
|
717
|
+
if (!scope.fleetWide && owner !== scope.gateOwner && !legacyUnownedSessionOk(deps.config.requirePrincipal, sessionCallerOf(req, deps), await sessionOwnerCellOf(forkFact.sessionStorage, sourceId, owner))) {
|
|
721
718
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
722
719
|
return;
|
|
723
720
|
}
|
|
@@ -755,7 +752,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
755
752
|
sendJson(res, 200, { deleted: false });
|
|
756
753
|
return;
|
|
757
754
|
}
|
|
758
|
-
if (!scope.fleetWide && owner !== scope.gateOwner && !legacyUnownedSessionOk(deps.config.requirePrincipal,
|
|
755
|
+
if (!scope.fleetWide && owner !== scope.gateOwner && !legacyUnownedSessionOk(deps.config.requirePrincipal, sessionCallerOf(req, deps), await sessionOwnerCellOf(deleteFact.sessionStorage, sessionId, owner))) {
|
|
759
756
|
sendJson(res, 200, { deleted: false });
|
|
760
757
|
return;
|
|
761
758
|
}
|
|
@@ -805,7 +802,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
805
802
|
sendError(res, 409, "conflict.session_ownerless", "this session has no recorded owner, so its rules can be neither read nor changed through this route; rules already stored for it keep applying to the runs of the principal they were stored under. Ways out: on the local backend, during the upgrade window, the first task submitted with a principal on a session written by an earlier version claims it for that principal (this route then serves its owner); or delete the session (DELETE /v1/sessions/:id), which removes its rules with it");
|
|
806
803
|
return;
|
|
807
804
|
}
|
|
808
|
-
const operator = explicitOperatorOk(principal, deps.config
|
|
805
|
+
const operator = explicitOperatorOk(principal, deps.config);
|
|
809
806
|
if (!operator && owner !== (principal ?? null)) {
|
|
810
807
|
sendError(res, 404, "not_found.session", SESSION_NOT_FOUND_MESSAGE);
|
|
811
808
|
return;
|
|
@@ -822,14 +819,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
822
819
|
}
|
|
823
820
|
return;
|
|
824
821
|
}
|
|
825
|
-
|
|
826
|
-
try {
|
|
827
|
-
body = (await readJson(req));
|
|
828
|
-
}
|
|
829
|
-
catch {
|
|
830
|
-
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
822
|
+
const body = (await readJson(req));
|
|
833
823
|
const read = readWritableSessionPermissionRules(body.rules);
|
|
834
824
|
if (read.refusal !== undefined) {
|
|
835
825
|
sendSessionPolicyError(res, read.refusal);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MODEL_ROLES, expandTiers, isThinkingLevel } from "@sema-agent/core";
|
|
2
2
|
import { HttpError } from "../../security.js";
|
|
3
|
+
import { echoCallerText } from "../../caller-text-echo.js";
|
|
3
4
|
import { isAtMentionable, matchCatalogModel, refusedCatalogEntry, selectableCatalog } from "../../model-select.js";
|
|
4
|
-
import { modelUnavailableMessage } from "../../model-entry-refusal.js";
|
|
5
|
+
import { echoModelRef, modelUnavailableMessage } from "../../model-entry-refusal.js";
|
|
5
6
|
import { redactSecrets } from "../../trace/redact.js";
|
|
6
7
|
import { admitProviderEcho, redactErrorMessage } from "../../observability/run-terminal.js";
|
|
7
8
|
import { sendJson, sendError, sendHttpError, msg } from "../send.js";
|
|
@@ -12,6 +13,7 @@ export function isCorePreflightValidationError(message) {
|
|
|
12
13
|
return CORE_PREFLIGHT_VALIDATION_PREFIXES.some((prefix) => message.startsWith(prefix));
|
|
13
14
|
}
|
|
14
15
|
export const CORE_PREFLIGHT_VALIDATION_ANCHORS = CORE_PREFLIGHT_VALIDATION_PREFIXES;
|
|
16
|
+
const MODEL_ROLE_ECHO_CHARS = 80;
|
|
15
17
|
function isModelRole(value) {
|
|
16
18
|
return typeof value === "string" && MODEL_ROLES.includes(value);
|
|
17
19
|
}
|
|
@@ -62,7 +64,7 @@ export async function handleSideQuery(req, res, match, ctx) {
|
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
64
66
|
if (body.modelRole !== undefined && !isModelRole(body.modelRole)) {
|
|
65
|
-
const shown = (typeof body.modelRole === "string" ? JSON.stringify(body.modelRole
|
|
67
|
+
const shown = (typeof body.modelRole === "string" ? JSON.stringify(echoCallerText(body.modelRole, { maxChars: MODEL_ROLE_ECHO_CHARS })) : `of type ${body.modelRole === null ? "null" : Array.isArray(body.modelRole) ? "array" : typeof body.modelRole}`);
|
|
66
68
|
sendError(res, 400, "request.field_invalid", `invalid modelRole ${shown} — must be a string, one of ${MODEL_ROLES.join(" / ")} (the engine's role vocabulary); a value outside it is refused before any model call`);
|
|
67
69
|
return;
|
|
68
70
|
}
|
|
@@ -70,12 +72,12 @@ export async function handleSideQuery(req, res, match, ctx) {
|
|
|
70
72
|
const catalog = selectableCatalog(deps.config.models ?? {}, deps.config.tiers, deps.config.modelRefusals);
|
|
71
73
|
const unavailable = matchCatalogModel(body.model, catalog, deps.config.modelRefusals) === undefined ? refusedCatalogEntry(body.model, deps.config.modelRefusals) : undefined;
|
|
72
74
|
if (unavailable !== undefined) {
|
|
73
|
-
const message = modelUnavailableMessage("model", body.model
|
|
75
|
+
const message = modelUnavailableMessage("model", body.model, unavailable.name, unavailable.refusal);
|
|
74
76
|
sendError(res, 400, "request.model_unavailable", message);
|
|
75
77
|
return;
|
|
76
78
|
}
|
|
77
79
|
if (!isAtMentionable(body.model, catalog, deps.config.atMention, deps.config.modelRefusals)) {
|
|
78
|
-
sendError(res, 400, "request.model_not_allowed", `model is not @-mentionable on this deployment: "${body.model
|
|
80
|
+
sendError(res, 400, "request.model_not_allowed", `model is not @-mentionable on this deployment: "${echoModelRef(body.model)}" — which models can be @-mentioned is configured by the operator (models.atMention)`);
|
|
79
81
|
return;
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -18,7 +18,7 @@ import { contextUsageEventData, turnEndEventData, toolStartEventData, toolEndEve
|
|
|
18
18
|
import { cascadeConfig, runMeta } from "../run-meta.js";
|
|
19
19
|
import { idemCallerOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
|
|
20
20
|
import { replayOfExistingRun } from "../submit-replay.js";
|
|
21
|
-
import { sendJson, sendError, sseHeaders } from "../send.js";
|
|
21
|
+
import { httpErrorCode, sendJson, sendError, sseHeaders } from "../send.js";
|
|
22
22
|
import { collectSsePreamble } from "../sse-log.js";
|
|
23
23
|
import { buildApprovalPreamble, buildApprovalPreambleSseFrames } from "../../approval-card.js";
|
|
24
24
|
import { createApprovalCardEmitter, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
|
|
@@ -34,6 +34,9 @@ import { persistSubmitCtx } from "../submit-ctx.js";
|
|
|
34
34
|
import { serviceVersion } from "../../service-version.js";
|
|
35
35
|
import { withModelReachScope } from "../../model-reach-scope.js";
|
|
36
36
|
import { createInstructionSelectionLeg } from "../../instruction-selection.js";
|
|
37
|
+
import { fieldConflictFacts } from "../../field-conflict.js";
|
|
38
|
+
import { refusalBody } from "../refusal-body.js";
|
|
39
|
+
import { heldWorkflowParkDecisions } from "../../parked-decide.js";
|
|
37
40
|
const DISCONNECT_PARK_GRACE_MS = 10_000;
|
|
38
41
|
function sseData(res, payload) {
|
|
39
42
|
const anchor = payload.eventId;
|
|
@@ -60,8 +63,8 @@ function sendSubmitResult(res, resp) {
|
|
|
60
63
|
: raw;
|
|
61
64
|
sendJson(res, 200, body);
|
|
62
65
|
}
|
|
63
|
-
function writeMetaFrame(res, taskId, sessionId) {
|
|
64
|
-
res.write(`event: meta\ndata: ${JSON.stringify({ type: "meta", taskId, ...(sessionId ? { sessionId } : {}) })}\n\n`);
|
|
66
|
+
function writeMetaFrame(res, taskId, sessionId, warnings) {
|
|
67
|
+
res.write(`event: meta\ndata: ${JSON.stringify({ type: "meta", taskId, ...(sessionId ? { sessionId } : {}), ...(warnings !== undefined ? { warnings } : {}) })}\n\n`);
|
|
65
68
|
}
|
|
66
69
|
function refusalDoneResult(body) {
|
|
67
70
|
if (isActiveRunConflictBody(body))
|
|
@@ -148,13 +151,13 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
148
151
|
if (!prepared)
|
|
149
152
|
return;
|
|
150
153
|
const principal = prepared.auth?.principal;
|
|
151
|
-
const wiringOperatorFace = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config
|
|
154
|
+
const wiringOperatorFace = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
|
|
152
155
|
let wiringReceipt;
|
|
153
156
|
const instructionLeg = createInstructionSelectionLeg();
|
|
154
157
|
const withRunReceipt = (out) => wiringReceipt !== undefined ? { ...out, wiringManifest: wiringReceipt } : out;
|
|
155
158
|
if (liveStream) {
|
|
156
159
|
if (prepared.verify || prepared.cascade) {
|
|
157
|
-
sendError(res, 400, "request.field_conflict", "verify / cascade are not supported on /v1/tasks/stream (both are multi-attempt, not a single stream) — use /v1/tasks or /v1/runs");
|
|
160
|
+
sendError(res, 400, "request.field_conflict", "verify / cascade are not supported on /v1/tasks/stream (both are multi-attempt, not a single stream) — use /v1/tasks or /v1/runs", fieldConflictFacts("cascade_verify", prepared.verify ? (prepared.cascade ? ["verify", "cascade"] : ["verify"]) : ["cascade"]));
|
|
158
161
|
return;
|
|
159
162
|
}
|
|
160
163
|
const earlyDurableTid = facts.durableRuns(deps).available && prepared.spec.sessionId ? uuidv7() : undefined;
|
|
@@ -169,7 +172,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
169
172
|
reqState.streamDetached = detachOnDisconnect;
|
|
170
173
|
sseHeaders(res, earlyDurableTid ? { "x-task-id": earlyDurableTid } : undefined);
|
|
171
174
|
if (earlyDurableTid)
|
|
172
|
-
writeMetaFrame(res, earlyDurableTid, prepared.spec.sessionId);
|
|
175
|
+
writeMetaFrame(res, earlyDurableTid, prepared.spec.sessionId, prepared.warnings);
|
|
173
176
|
const ac = createRunAbort();
|
|
174
177
|
let closed = false;
|
|
175
178
|
let detachLogged = false;
|
|
@@ -215,14 +218,26 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
215
218
|
parkFacility: deps.checkpointStore !== undefined,
|
|
216
219
|
});
|
|
217
220
|
const replaySessionId = replayGate.active ? prepared.spec.sessionId : undefined;
|
|
221
|
+
const presentedOnConnection = new Set();
|
|
222
|
+
const presentedCompleted = new Set();
|
|
223
|
+
const admitPresentedComplete = (askId) => {
|
|
224
|
+
if (!presentedOnConnection.has(askId))
|
|
225
|
+
return true;
|
|
226
|
+
if (presentedCompleted.has(askId))
|
|
227
|
+
return false;
|
|
228
|
+
presentedCompleted.add(askId);
|
|
229
|
+
return true;
|
|
230
|
+
};
|
|
218
231
|
if (replaySessionId) {
|
|
219
232
|
const replayOwner = gatedPrincipal(req, deps.config) ?? null;
|
|
220
233
|
const askStore = replayGate.active ? replayGate.askStore : undefined;
|
|
234
|
+
let presentedAskIds = [];
|
|
221
235
|
const preambleFrames = await collectSsePreamble(async (signal) => {
|
|
222
236
|
if (!askStore)
|
|
223
237
|
return [];
|
|
224
238
|
const rows = await askStore.listPendingBySession(replaySessionId, replayOwner, signal);
|
|
225
239
|
const { frames, skipped, dropped } = buildApprovalPreamble(rows, Date.now(), deps.config.streamApproval.replayMax);
|
|
240
|
+
presentedAskIds = frames.map((f) => f.askId);
|
|
226
241
|
if (skipped > 0)
|
|
227
242
|
deps.logger?.warn?.("approval_preamble_row_skipped", { sessionId: replaySessionId, skipped, face: "tasks.stream" });
|
|
228
243
|
if (dropped > 0)
|
|
@@ -232,6 +247,16 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
232
247
|
if (!res.writableEnded && !res.destroyed) {
|
|
233
248
|
for (const f of preambleFrames)
|
|
234
249
|
res.write(`event: ${f.event}\ndata: ${JSON.stringify(f.data)}\n\n`);
|
|
250
|
+
if (deps.toolApproval && preambleFrames.length > 0) {
|
|
251
|
+
for (const askId of presentedAskIds)
|
|
252
|
+
presentedOnConnection.add(askId);
|
|
253
|
+
const unwatch = deps.toolApproval.watchPresentedCards(presentedAskIds, (frame) => {
|
|
254
|
+
if (res.writableEnded || res.destroyed || !admitPresentedComplete(frame.askId))
|
|
255
|
+
return;
|
|
256
|
+
res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
|
|
257
|
+
});
|
|
258
|
+
res.once("close", unwatch);
|
|
259
|
+
}
|
|
235
260
|
}
|
|
236
261
|
}
|
|
237
262
|
const hb = setInterval(() => {
|
|
@@ -378,7 +403,9 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
378
403
|
const tailContentMode = prepared.spec.forwardSubagentEvents === true ? "on" : "progress_only";
|
|
379
404
|
const childReasoning = createReasoningSegments();
|
|
380
405
|
const topReasoning = createReasoningSegments();
|
|
406
|
+
const heldDecisions = prepared.spec.sessionId !== undefined ? await heldWorkflowParkDecisions(deps, prepared.spec.sessionId) : {};
|
|
381
407
|
const fwdInternals = {
|
|
408
|
+
...heldDecisions,
|
|
382
409
|
onForwardEvent: (e) => {
|
|
383
410
|
fleetPub?.onForwardEvent(e);
|
|
384
411
|
ledgerSink?.onForwardEvent(e);
|
|
@@ -457,6 +484,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
457
484
|
liveStreamRef = liveStream;
|
|
458
485
|
if (durableTaskId)
|
|
459
486
|
steerableRuns.set(durableTaskId, liveStream);
|
|
487
|
+
prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
|
|
460
488
|
for await (const ev of liveStream) {
|
|
461
489
|
if (closed)
|
|
462
490
|
break;
|
|
@@ -659,6 +687,8 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
659
687
|
writeLive: (frame) => {
|
|
660
688
|
if (res.writableEnded || res.destroyed)
|
|
661
689
|
throw new Error("live stream ended");
|
|
690
|
+
if (frame.type === "approval_complete" && !admitPresentedComplete(frame.askId))
|
|
691
|
+
return;
|
|
662
692
|
emitAsk(frame);
|
|
663
693
|
},
|
|
664
694
|
});
|
|
@@ -670,7 +700,6 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
670
700
|
? {
|
|
671
701
|
taskId: askTaskId,
|
|
672
702
|
owner: askOwner,
|
|
673
|
-
emit: emitApproval,
|
|
674
703
|
abortSignal: ac.signal,
|
|
675
704
|
...(prepared.spec.sessionId ? { sessionId: prepared.spec.sessionId } : {}),
|
|
676
705
|
...(streamApprovalOn
|
|
@@ -680,7 +709,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
680
709
|
legKey: "",
|
|
681
710
|
...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
|
|
682
711
|
}
|
|
683
|
-
: {}),
|
|
712
|
+
: { emit: emitApproval }),
|
|
684
713
|
}
|
|
685
714
|
: undefined;
|
|
686
715
|
if (deps.toolApproval) {
|
|
@@ -843,7 +872,13 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
843
872
|
res.end();
|
|
844
873
|
}
|
|
845
874
|
else {
|
|
846
|
-
const withSyncSubmitKeys = (body) =>
|
|
875
|
+
const withSyncSubmitKeys = (body) => {
|
|
876
|
+
const extra = {
|
|
877
|
+
...(prepared.verify || prepared.cascade ? { notice: MULTI_ATTEMPT_NO_EVENT_CHANNEL_NOTICE } : {}),
|
|
878
|
+
...(prepared.warnings !== undefined ? { warnings: prepared.warnings } : {}),
|
|
879
|
+
};
|
|
880
|
+
return Object.keys(extra).length > 0 ? { ...body, ...extra } : body;
|
|
881
|
+
};
|
|
847
882
|
const runSyncSubmitLeg = async () => {
|
|
848
883
|
const syncLegStartedAt = Date.now();
|
|
849
884
|
let durableTaskId;
|
|
@@ -902,10 +937,11 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
902
937
|
let result;
|
|
903
938
|
counters.uncountedBillableInflight++;
|
|
904
939
|
try {
|
|
905
|
-
const
|
|
906
|
-
const
|
|
940
|
+
const heldDecisions = prepared.spec.sessionId !== undefined ? await heldWorkflowParkDecisions(deps, prepared.spec.sessionId) : {};
|
|
941
|
+
const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, heldDecisions);
|
|
942
|
+
const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), heldDecisions);
|
|
907
943
|
const plainLeg = async () => {
|
|
908
|
-
const stream = prepared.runner.runTaskStream(specWithSignal);
|
|
944
|
+
const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
|
|
909
945
|
for await (const ev of stream) {
|
|
910
946
|
observeSyncLegEvent(ev);
|
|
911
947
|
prepared.acceptance.observe(ev);
|
|
@@ -942,8 +978,8 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
942
978
|
const retryAfterSec = resumeAtPlane.errorCode === "memory.admission_required" && result.retryAfterMs !== undefined
|
|
943
979
|
? Math.max(1, Math.ceil(result.retryAfterMs / 1000))
|
|
944
980
|
: undefined;
|
|
945
|
-
const refusalFacts = zeroWorkRefusalFacts(redactTerminalResult(sealResultForExit(result)).terminal);
|
|
946
|
-
return { status: resumeAtStatus, body: { errorCode: resumeAtPlane.errorCode,
|
|
981
|
+
const refusalFacts = zeroWorkRefusalFacts(redactTerminalResult(sealResultForExit(result)).terminal, prepared.warnings);
|
|
982
|
+
return { status: resumeAtStatus, body: refusalBody({ errorCode: httpErrorCode(resumeAtStatus, resumeAtPlane.errorCode), message: redactErrorMessage(resumeAtPlane.errorMessage) ?? "resume-at failed", facts: { ...(retryAfterSec !== undefined ? { retryAfterSec } : {}), ...refusalFacts } }) };
|
|
947
983
|
}
|
|
948
984
|
const exitResult = await mintSubmitExitResult(result, deps.checkpointStore);
|
|
949
985
|
const syncPlane = outwardPlane(result.terminal);
|