@sema-agent/server 7.141.0 → 7.143.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 +657 -0
- package/USAGE.md +102 -30
- package/dist/adoption/plan.js +22 -0
- package/dist/approval-ask-audit-store.d.ts +61 -43
- package/dist/approval-ask-audit-store.js +69 -44
- package/dist/approval-ask-machine.d.ts +15 -7
- package/dist/approval-ask-machine.js +10 -4
- package/dist/approval-card.d.ts +126 -27
- package/dist/approval-card.js +103 -23
- package/dist/approval-crash-convergence.d.ts +17 -7
- package/dist/approval-crash-convergence.js +94 -22
- package/dist/approval-deny-reasons.d.ts +34 -30
- package/dist/approval-deny-reasons.js +21 -6
- package/dist/approval-policy-settlement.d.ts +1 -1
- package/dist/approval-queue-kind.d.ts +27 -0
- package/dist/approval-queue-kind.js +6 -0
- package/dist/approval-reconciler.d.ts +41 -9
- package/dist/approval-reconciler.js +45 -42
- package/dist/audit.js +4 -2
- package/dist/auth-bridge.d.ts +9 -6
- package/dist/auth-bridge.js +9 -3
- package/dist/boot/adoption.js +2 -1
- package/dist/boot/budget-tracing.d.ts +17 -1
- package/dist/boot/budget-tracing.js +10 -6
- package/dist/boot/device-lane.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +24 -4
- package/dist/boot/execution-env.js +26 -23
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/governance-seams.d.ts +26 -41
- package/dist/boot/governance-seams.js +61 -28
- package/dist/boot/late-binds.d.ts +7 -4
- package/dist/boot/late-binds.js +3 -1
- package/dist/boot/leader.js +2 -4
- package/dist/boot/memory-consolidation.d.ts +0 -8
- package/dist/boot/memory-consolidation.js +5 -4
- package/dist/boot/parked-revive-gate.js +2 -1
- package/dist/boot/permission-rules-audit.d.ts +0 -28
- package/dist/boot/permission-rules-audit.js +2 -1
- package/dist/boot/read-deny-anchor-audit.js +2 -1
- package/dist/boot/reapers.js +9 -7
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +19 -10
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.d.ts +10 -7
- package/dist/boot/runner-deps.js +20 -29
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.d.ts +9 -0
- package/dist/boot/shutdown.js +19 -4
- package/dist/boot/stage-02-web-admin-pull.js +3 -0
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +1 -2
- package/dist/boot/stage-04-stores.d.ts +5 -2
- package/dist/boot/stage-04-stores.js +6 -7
- package/dist/boot/stage-05-execution-env.d.ts +6 -3
- package/dist/boot/stage-05-execution-env.js +8 -6
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +3 -4
- package/dist/boot/stage-07-capability-layer.d.ts +6 -3
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +6 -3
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +6 -3
- package/dist/boot/stage-10-http-server.d.ts +6 -3
- package/dist/boot/stage-10-http-server.js +14 -5
- package/dist/boot/stores.d.ts +5 -2
- package/dist/boot/stores.js +10 -9
- package/dist/boot/web-admin.d.ts +5 -1
- package/dist/boot/web-admin.js +48 -36
- package/dist/boot/webfetch-summarize-lane.js +2 -1
- package/dist/boot/workflow-orchestration.js +3 -2
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/builtin-tools.js +2 -4
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -39
- package/dist/capabilities/hands-lane.js +8 -13
- package/dist/capabilities/mcp-probe.d.ts +3 -2
- package/dist/capabilities/scenarios.d.ts +11 -1
- package/dist/capabilities/scenarios.js +1 -0
- package/dist/capabilities/skills.d.ts +1 -17
- package/dist/capabilities/skills.js +0 -8
- package/dist/capability-facts.d.ts +31 -7
- package/dist/capability-facts.js +27 -4
- package/dist/card-void.d.ts +6 -9
- package/dist/config-catalog.js +2 -1
- package/dist/config-dir-trust.js +58 -29
- package/dist/config-invariants.d.ts +7 -1
- package/dist/config-invariants.js +7 -0
- package/dist/config-provider.d.ts +10 -0
- package/dist/config-provider.js +15 -4
- package/dist/config-root-migration.d.ts +13 -0
- package/dist/config-root-migration.js +99 -0
- package/dist/config-types.d.ts +19 -8
- package/dist/config.d.ts +10 -3
- package/dist/config.js +18 -4
- package/dist/delegated-session-owner.d.ts +5 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/env-model-table-gate.d.ts +53 -0
- package/dist/env-model-table-gate.js +53 -0
- package/dist/execution-lane-caps.d.ts +2 -1
- package/dist/fleet/fleet-bus.d.ts +34 -55
- package/dist/fleet/fleet-bus.js +35 -100
- package/dist/fleet/fleet-reconciler.d.ts +4 -4
- package/dist/fleet/fleet-reconciler.js +1 -1
- package/dist/fleet/subagent-tail-bus.d.ts +14 -11
- package/dist/fleet/subagent-tail-bus.js +15 -28
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +58 -8
- package/dist/host-decision.d.ts +54 -20
- package/dist/host-decision.js +42 -14
- package/dist/http/admission.d.ts +1 -1
- package/dist/http/admission.js +7 -3
- package/dist/http/approval-sweeps.js +11 -8
- package/dist/http/caller-trust.d.ts +1 -1
- package/dist/http/dispatch.js +4 -2
- package/dist/http/durable-run-leg.js +2 -2
- package/dist/http/engine-refusal.d.ts +16 -0
- package/dist/http/engine-refusal.js +17 -0
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
- package/dist/http/memory-compliance-failure-reply.js +4 -6
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +13 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.d.ts +21 -7
- package/dist/http/resume-legs.js +76 -58
- package/dist/http/resume-restatement.d.ts +39 -0
- package/dist/http/resume-restatement.js +25 -0
- package/dist/http/route-ctx.d.ts +35 -10
- package/dist/http/route-ctx.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.d.ts +9 -1
- package/dist/http/routes/approvals-assistant.js +142 -31
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +16 -4
- package/dist/http/routes/memory-policy.d.ts +2 -2
- package/dist/http/routes/memory-policy.js +27 -7
- package/dist/http/routes/notify-wake.js +23 -25
- package/dist/http/routes/rules.js +48 -13
- package/dist/http/routes/runs.js +12 -11
- package/dist/http/routes/session-memory-sync.d.ts +91 -0
- package/dist/http/routes/session-memory-sync.js +174 -0
- package/dist/http/routes/session-sync.js +13 -20
- package/dist/http/routes/sessions-list.d.ts +2 -1
- package/dist/http/routes/sessions.d.ts +2 -2
- package/dist/http/routes/sessions.js +22 -23
- package/dist/http/routes/tasks.js +34 -54
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +9 -3
- package/dist/http/send.d.ts +5 -0
- package/dist/http/send.js +9 -2
- package/dist/http/server.d.ts +27 -15
- package/dist/http/server.js +4 -6
- package/dist/http/stored-body-replay.js +15 -4
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +2 -2
- package/dist/http/sync-submit-body.d.ts +21 -4
- package/dist/http/sync-submit-body.js +13 -0
- package/dist/http/wire-types.d.ts +17 -7
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/leader/leader.js +5 -2
- package/dist/leader/wire.d.ts +7 -1
- package/dist/leader/wire.js +6 -5
- package/dist/leg-facts.d.ts +37 -0
- package/dist/leg-facts.js +15 -0
- package/dist/memory-bundle-engine.d.ts +1 -4
- package/dist/memory-bundle-engine.js +2 -2
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-operator-faces.d.ts +30 -66
- package/dist/memory-operator-faces.js +17 -88
- package/dist/memory-scope-stores.d.ts +38 -40
- package/dist/memory-scope-stores.js +51 -36
- package/dist/memory-scope.d.ts +0 -9
- package/dist/memory-scope.js +0 -9
- package/dist/memory-sync-client.d.ts +21 -21
- package/dist/memory-sync-client.js +62 -43
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +27 -5
- package/dist/memory-sync.js +29 -7
- package/dist/model-plane-face.d.ts +13 -7
- package/dist/model-plane-face.js +2 -1
- package/dist/observability/fail-open.d.ts +47 -14
- package/dist/observability/fail-open.js +37 -11
- package/dist/observability/run-terminal.d.ts +92 -34
- package/dist/observability/run-terminal.js +171 -162
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
- package/dist/orchestration/workflow-completion-inbox.js +0 -12
- package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
- package/dist/orchestration/workflow-park-decision.d.ts +8 -3
- package/dist/orchestration/workflow-park-decision.js +5 -3
- package/dist/org-delivery-gate.d.ts +11 -0
- package/dist/org-delivery-gate.js +19 -1
- package/dist/parked-decide.d.ts +13 -9
- package/dist/parked-decide.js +7 -7
- package/dist/parked-revive-surface.js +1 -1
- package/dist/peer-inbound-face.d.ts +127 -0
- package/dist/peer-inbound-face.js +158 -0
- package/dist/permission-rule-list.d.ts +13 -9
- package/dist/permission-rule-list.js +7 -3
- package/dist/plugins/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +64 -11
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +17 -14
- package/dist/plugins/approval-ask-store-sql.d.ts +70 -23
- package/dist/plugins/approval-ask-store-sql.js +79 -30
- package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
- package/dist/plugins/checkpoint-store-sql.js +9 -7
- package/dist/plugins/file-history-store-sql.d.ts +24 -18
- package/dist/plugins/file-history-store-sql.js +24 -19
- package/dist/plugins/file-run-store.d.ts +35 -1
- package/dist/plugins/file-run-store.js +108 -9
- package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
- package/dist/plugins/imported-layer-root-retirement.js +96 -0
- package/dist/plugins/local-checkpoint-store.d.ts +1 -1
- package/dist/plugins/local-checkpoint-store.js +2 -2
- package/dist/plugins/local-session-store.d.ts +42 -9
- package/dist/plugins/local-session-store.js +83 -33
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
- package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
- package/dist/plugins/mailbox-store-sql.d.ts +12 -8
- package/dist/plugins/mailbox-store-sql.js +76 -7
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +6 -1
- package/dist/plugins/memory-run-store.js +11 -1
- package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
- package/dist/plugins/memory-sync-store-pg.js +21 -0
- package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
- package/dist/plugins/memory-sync-store-tidb.js +13 -1
- package/dist/plugins/one-time-migrations.d.ts +58 -2
- package/dist/plugins/one-time-migrations.js +161 -4
- package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
- package/dist/plugins/org-delivery-quota-store.js +2 -12
- package/dist/plugins/park-commit-watch.d.ts +1 -1
- package/dist/plugins/permission-rule-store-file.d.ts +10 -1
- package/dist/plugins/permission-rule-store-file.js +15 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
- package/dist/plugins/permission-rule-store-sql.js +35 -2
- package/dist/plugins/remote-env-device.d.ts +8 -11
- package/dist/plugins/remote-env-device.js +6 -3
- package/dist/plugins/remote-env-e2b.d.ts +23 -4
- package/dist/plugins/remote-env-e2b.js +111 -28
- package/dist/plugins/remote-env-k8s.d.ts +61 -22
- package/dist/plugins/remote-env-k8s.js +133 -33
- package/dist/plugins/remote-env-local-docker.d.ts +15 -3
- package/dist/plugins/remote-env-local-docker.js +40 -12
- package/dist/plugins/retention-store-sql.d.ts +2 -2
- package/dist/plugins/run-store-sql.d.ts +9 -1
- package/dist/plugins/run-store-sql.js +9 -1
- package/dist/plugins/sandbox-read-floor.d.ts +5 -7
- package/dist/plugins/sandbox-read-floor.js +2 -7
- package/dist/plugins/sql-errors.d.ts +10 -1
- package/dist/plugins/sql-errors.js +13 -0
- package/dist/plugins/store-backend.d.ts +33 -35
- package/dist/plugins/store-backend.js +10 -1
- package/dist/plugins/store-contracts.d.ts +50 -1
- package/dist/plugins/store-contracts.js +6 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +207 -29
- package/dist/plugins/tool-result-store-sql.d.ts +9 -8
- package/dist/plugins/tool-result-store-sql.js +23 -2
- package/dist/plugins/wiring-section-codec.d.ts +32 -0
- package/dist/plugins/wiring-section-codec.js +55 -0
- package/dist/plugins/workspace-fill.d.ts +60 -0
- package/dist/plugins/workspace-fill.js +106 -0
- package/dist/project-bundle.d.ts +38 -0
- package/dist/project-bundle.js +609 -0
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +5 -1
- package/dist/rules-consent.d.ts +28 -5
- package/dist/rules-consent.js +40 -28
- package/dist/run-local.js +11 -13
- package/dist/runs.d.ts +12 -8
- package/dist/runs.js +6 -8
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/sandbox-egress-policy.d.ts +4 -1
- package/dist/sandbox-egress-policy.js +3 -1
- package/dist/sandbox-git-plane.d.ts +31 -12
- package/dist/sandbox-git-plane.js +24 -4
- package/dist/security.d.ts +9 -0
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +4 -0
- package/dist/session-error-wire.d.ts +36 -0
- package/dist/session-error-wire.js +13 -0
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-notify-door.d.ts +106 -0
- package/dist/session-notify-door.js +93 -0
- package/dist/session-sync.d.ts +9 -14
- package/dist/session-sync.js +5 -5
- package/dist/session-workspace.d.ts +3 -13
- package/dist/session-workspace.js +0 -9
- package/dist/standing-answer-grant.d.ts +5 -0
- package/dist/standing-answer-grant.js +10 -0
- package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
- package/dist/stores-sql/session-policy-store-sql.js +3 -13
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +21 -10
- package/dist/task-settings.js +46 -13
- package/dist/terminal.d.ts +39 -19
- package/dist/terminal.js +65 -22
- package/dist/tool-approval.d.ts +56 -37
- package/dist/tool-approval.js +78 -71
- package/dist/trace/core-keyset-guard.d.ts +134 -14
- package/dist/trace/engine-notice-wire.d.ts +9 -3
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +9 -2
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +10 -6
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +55 -25
- package/dist/trace/model-segment.js +101 -33
- package/dist/trace/project.d.ts +25 -5
- package/dist/trace/project.js +22 -0
- package/dist/trace/redact.d.ts +61 -9
- package/dist/trace/redact.js +1490 -468
- package/dist/trace/self-minted-wire.d.ts +745 -24
- package/dist/trace/self-minted-wire.js +239 -9
- package/dist/trace/wire-projection-faces.d.ts +2 -2
- package/dist/trace/wire-projection-faces.js +2 -2
- package/dist/verifier-pause-card.d.ts +33 -5
- package/dist/verifier-pause-card.js +15 -10
- package/dist/web-admin-client/apply-effective.d.ts +12 -16
- package/dist/web-admin-client/apply-effective.js +109 -9
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/types.d.ts +4 -0
- package/dist/workspace-space.d.ts +19 -3
- package/dist/workspace-space.js +8 -4
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
- package/package.json +3 -2
- package/wire-changes/server@7.142.0.json +639 -0
- package/wire-changes/server@7.143.0.json +1167 -0
package/dist/http/resume-legs.js
CHANGED
|
@@ -4,7 +4,7 @@ import { uuidv7, resumeWithVerification, CheckpointError, defaultTaskRegistry, t
|
|
|
4
4
|
import { decideParkedAgent, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
|
|
5
5
|
import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
|
|
6
6
|
import { headReadOf } from "../session-incarnation.js";
|
|
7
|
-
import { createSessionWorkspaceRecorder,
|
|
7
|
+
import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
|
|
8
8
|
const DELIVERY_NOT_RECORDED = "workflow park decide: this delivery no longer holds the host session (its claim was released) — the decision was not recorded and this delivery was not started";
|
|
9
9
|
import { HttpError, decodeCheckpointScope, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
10
10
|
import { graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
|
|
@@ -15,7 +15,7 @@ import { isTerminalRunStatus } from "../plugins/store-contracts.js";
|
|
|
15
15
|
import { readTurnActivityMs, recordTurnActivity } from "../turn-activity.js";
|
|
16
16
|
import { recordResumeResourceWindow } from "../resource-window.js";
|
|
17
17
|
import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "../orchestration/workflow-completion-inbox.js";
|
|
18
|
-
import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals
|
|
18
|
+
import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals } from "../fleet/fleet-bus.js";
|
|
19
19
|
import { defaultSubagentTailBus } from "../fleet/subagent-tail-bus.js";
|
|
20
20
|
import { currentApprovalGateToken, currentGateFacesOf, sightsCurrentGate } from "../approval-gate-currency.js";
|
|
21
21
|
import { approverFacingArgs, createApprovalCardEmitter, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
|
|
@@ -25,9 +25,9 @@ import { serviceVersion } from "../service-version.js";
|
|
|
25
25
|
import { TERMINAL_PARK_GATE_KINDS } from "../plugins/checkpoint-store-sql.js";
|
|
26
26
|
import { withPrincipal } from "../observability/principal-context.js";
|
|
27
27
|
import { withModelReachScope } from "../model-reach-scope.js";
|
|
28
|
-
import {
|
|
28
|
+
import { legFactsOf } from "../leg-facts.js";
|
|
29
29
|
import { createInstructionSelectionLeg } from "../instruction-selection.js";
|
|
30
|
-
import { modelTextEventData,
|
|
30
|
+
import { modelTextEventData, appendParkRow, turnEndEventData, contextUsageEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, compactionStartedEventData, workspaceChangedEventData, wiringManifestEventData, toolRosterDeltaEventData, toolDisclosureEventData, humanInputEventData, appendModelUsageDelta, appendPromptManifest, attachModelUsage } from "../trace/project.js";
|
|
31
31
|
import { redactSecrets } from "../trace/redact.js";
|
|
32
32
|
import { buildRunObjectivePreview } from "../user-authored-text.js";
|
|
33
33
|
import { createForwardAppendFailedNote, createLedgerSink, createSerialLedgerAppend } from "../trace/ledger-sink.js";
|
|
@@ -57,9 +57,11 @@ import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnsealableAnswer } from
|
|
|
57
57
|
import { buildCheckpointVersionKeys, resumeBlockedByPolicyAnswer, resumeRefusalWithCard, sealCheckpointCtx, storedBodyReplayAnswer, storedBodyReplayLogFields, withPermissionModeRewritten } from "./checkpoint-ctx.js";
|
|
58
58
|
import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
|
|
59
59
|
import { storedBodyReplayRefusal } from "./stored-body-replay.js";
|
|
60
|
+
import { restateResumeCtx } from "./resume-restatement.js";
|
|
60
61
|
import { httpErrorRefusal } from "./send.js";
|
|
61
62
|
import { createRunAcceptance } from "../run-acceptance.js";
|
|
62
63
|
import { fieldConflictFacts } from "../field-conflict.js";
|
|
64
|
+
import { createSessionNotifyDoor } from "../session-notify-door.js";
|
|
63
65
|
function legMayHaveReopenedCheckpoint(r) {
|
|
64
66
|
return r.terminal.kind === "failed" && nestedPauseOf(r.terminal) === undefined;
|
|
65
67
|
}
|
|
@@ -107,6 +109,8 @@ const CHECKPOINT_ERROR_DISPOSITION = {
|
|
|
107
109
|
"checkpoint.reopened_concurrently": "retriable",
|
|
108
110
|
"resume.parent_constraint_missing": "retriable",
|
|
109
111
|
"resume.parent_constraint_mismatch": "retriable",
|
|
112
|
+
"resume.composition_mismatch": "retriable",
|
|
113
|
+
"checkpoint.void_unpin_failed": "terminal",
|
|
110
114
|
"resume.constraint_rejected": "retriable",
|
|
111
115
|
"resume.constraint_unprojectable": "retriable",
|
|
112
116
|
"resume.usage_window_exhausted": "retriable",
|
|
@@ -230,14 +234,19 @@ export function checkpointRefusalAnswer(e, at) {
|
|
|
230
234
|
}),
|
|
231
235
|
}, at.retriable);
|
|
232
236
|
}
|
|
237
|
+
export function decidedActionOf(binding) {
|
|
238
|
+
const { boundCallId, boundInputHash } = binding;
|
|
239
|
+
const missingKeys = [...(typeof boundCallId === "string" && boundCallId.length > 0 ? [] : ["boundCallId"]), ...(typeof boundInputHash === "string" && boundInputHash.length > 0 ? [] : ["boundInputHash"])];
|
|
240
|
+
return missingKeys.length === 0 ? { action: { boundCallId: boundCallId, boundInputHash: boundInputHash } } : { missingKeys };
|
|
241
|
+
}
|
|
233
242
|
export function createResumeLegs(ctx) {
|
|
234
243
|
const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor } = ctx;
|
|
235
244
|
const ctxOpening = (sessionId) => ({ sessionId, opener: deps.checkpointCtxSealing });
|
|
236
245
|
const resumeFleetScope = (req, auth) => req ? (gatedPrincipal(req, deps.config) ?? "default") : (auth.principal ?? "default");
|
|
237
|
-
async function resumeCheckpoint(sessionId, decision, reason, hostDecision, req, answer, binding, onResumeCommitted, acceptEarly, decider) {
|
|
246
|
+
async function resumeCheckpoint(sessionId, decision, reason, hostDecision, req, answer, binding, onResumeCommitted, acceptEarly, decider, restatement) {
|
|
238
247
|
const cs = deps.checkpointStore;
|
|
239
248
|
const token = await currentApprovalGateToken(cs, sessionId);
|
|
240
|
-
if (binding
|
|
249
|
+
if (binding.checkpointToken && !sightsCurrentGate({ face: "checkpointToken", value: binding.checkpointToken }, token ? { checkpointToken: token } : null)) {
|
|
241
250
|
let seenUnreadable = false;
|
|
242
251
|
const seen = await cs.get(binding.checkpointToken).catch((e) => {
|
|
243
252
|
seenUnreadable = true;
|
|
@@ -326,20 +335,23 @@ export function createResumeLegs(ctx) {
|
|
|
326
335
|
}),
|
|
327
336
|
};
|
|
328
337
|
}
|
|
329
|
-
|
|
338
|
+
const decided = decidedActionOf(binding);
|
|
339
|
+
if (decided.action === undefined) {
|
|
330
340
|
return {
|
|
331
341
|
status: 400,
|
|
332
342
|
body: refusalBody({
|
|
333
343
|
errorCode: "decide_requires_binding",
|
|
334
|
-
message: "decide requires the decision-action binding — echo
|
|
344
|
+
message: "decide requires the decision-action binding — echo boundCallId and boundInputHash exactly as the pending approval you are deciding shows them (GET /v1/approvals), so a decision on a view that has since been replaced is refused instead of landing on the gate that replaced it",
|
|
335
345
|
facts: {
|
|
336
346
|
bindingEnforced: true,
|
|
347
|
+
missingKeys: decided.missingKeys,
|
|
337
348
|
},
|
|
338
349
|
}),
|
|
339
350
|
};
|
|
340
351
|
}
|
|
352
|
+
const action = decided.action;
|
|
341
353
|
const s57RowCallId = cp.pendingAction.kind === "tool_approval" ? cp.pendingAction.toolCallId : undefined;
|
|
342
|
-
if (
|
|
354
|
+
if (s57RowCallId && action.boundCallId !== s57RowCallId) {
|
|
343
355
|
let s57CurrentPending;
|
|
344
356
|
if (decider !== undefined && cp.status === "pending" && cp.sessionId === sessionId && cp.pendingAction.kind === "tool_approval") {
|
|
345
357
|
s57CurrentPending = {
|
|
@@ -400,8 +412,9 @@ export function createResumeLegs(ctx) {
|
|
|
400
412
|
const parkedReq = {
|
|
401
413
|
token, scope: cp.scope, sessionId: cp.sessionId, pendingAction: cp.pendingAction,
|
|
402
414
|
decision, hostDecision, ...(reason !== undefined ? { reason } : {}),
|
|
403
|
-
|
|
415
|
+
binding: { ...(({ checkpointToken: _staleGuardOnly, ...rest }) => rest)(binding), ...action },
|
|
404
416
|
...(answer !== undefined ? { answer } : {}),
|
|
417
|
+
...(restatement !== undefined ? { restatement } : {}),
|
|
405
418
|
...(boundGrant ? { grantRemember: (rootSessionId) => boundGrant(rootSessionId) } : {}),
|
|
406
419
|
};
|
|
407
420
|
if (origin?.kind === "background" && parkedAgentStore !== undefined && parkedSurface !== undefined) {
|
|
@@ -458,7 +471,7 @@ export function createResumeLegs(ctx) {
|
|
|
458
471
|
if (decisions === undefined || runStore === undefined) {
|
|
459
472
|
return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
|
|
460
473
|
}
|
|
461
|
-
const fingerprint = parkDecisionFingerprint(plan.outcome);
|
|
474
|
+
const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
|
|
462
475
|
const liveReceiptOf = async (held) => {
|
|
463
476
|
if (held === null || held.fingerprint !== fingerprint)
|
|
464
477
|
return undefined;
|
|
@@ -488,8 +501,8 @@ export function createResumeLegs(ctx) {
|
|
|
488
501
|
.catch(() => undefined);
|
|
489
502
|
const admittedPayer = decodeCheckpointScope(cp.scope);
|
|
490
503
|
const out = hostToken
|
|
491
|
-
? await resumeWake(plan.hostSessionId, plan.message, decider?.principal, req, acceptEarly, delivery, admittedPayer)
|
|
492
|
-
: await startFreshHostTurn(plan.hostSessionId, plan.message, admittedPayer, req, delivery, plan.runId);
|
|
504
|
+
? await resumeWake(plan.hostSessionId, plan.message, decider?.principal, req, acceptEarly, delivery, admittedPayer, restatement)
|
|
505
|
+
: await startFreshHostTurn(plan.hostSessionId, plan.message, admittedPayer, req, delivery, plan.runId, restatement);
|
|
493
506
|
if (recordFailure !== undefined)
|
|
494
507
|
throw recordFailure.err;
|
|
495
508
|
if (acceptedTaskIdOf(out) === undefined)
|
|
@@ -502,9 +515,10 @@ export function createResumeLegs(ctx) {
|
|
|
502
515
|
return resumeCtxCorruptAnswer(ctxRead0.where);
|
|
503
516
|
if (ctxRead0.kind === "unsealable")
|
|
504
517
|
return resumeCtxUnsealableAnswer(ctxRead0);
|
|
505
|
-
const
|
|
506
|
-
if (!
|
|
518
|
+
const storedCtx = ctxRead0.kind === "ok" ? ctxRead0.ctx : null;
|
|
519
|
+
if (!storedCtx)
|
|
507
520
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
521
|
+
const ctx = restateResumeCtx(storedCtx, restatement);
|
|
508
522
|
const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
|
|
509
523
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
510
524
|
if (!resolved.ok)
|
|
@@ -520,21 +534,19 @@ export function createResumeLegs(ctx) {
|
|
|
520
534
|
}
|
|
521
535
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
522
536
|
const pa = cp.pendingAction;
|
|
523
|
-
const persistedCallId = pa.kind === "tool_approval" ? pa.toolCallId : "";
|
|
524
|
-
const persistedHash = pa.kind === "tool_approval" ? (pa.boundInputHash ?? "") : "";
|
|
525
537
|
const outcome = {
|
|
526
538
|
gate: "policy_ask",
|
|
527
|
-
boundCallId:
|
|
528
|
-
boundInputHash:
|
|
539
|
+
boundCallId: action.boundCallId,
|
|
540
|
+
boundInputHash: action.boundInputHash,
|
|
529
541
|
decision: decision === "approve" ? "allow" : "deny",
|
|
530
|
-
...(decision === "approve" && !isEngineQuestionRow(pa) && binding
|
|
542
|
+
...(decision === "approve" && !isEngineQuestionRow(pa) && binding.updatedInput !== undefined ? { updatedInput: binding.updatedInput } : {}),
|
|
531
543
|
...(reason ? { reason } : {}),
|
|
532
|
-
...(binding
|
|
544
|
+
...(binding.feedback !== undefined ? { feedback: binding.feedback } : {}),
|
|
533
545
|
...(answer !== undefined ? { answer } : {}),
|
|
534
546
|
hostDecision,
|
|
535
547
|
};
|
|
536
548
|
const verifyRounds = verifyRoundsFromBody(ctx.body);
|
|
537
|
-
const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner:
|
|
549
|
+
const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...captureSelectedGate() }, verifyRounds, resumeCtx: { sessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(boundGrant ? { onResumeCommitted: boundGrant } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}), ...(ownerLeaseAdmittedHere ? { ownerLeaseAdmitted: true } : {}) });
|
|
538
550
|
noteLateSettleIfAccepted(driven);
|
|
539
551
|
return driven;
|
|
540
552
|
}
|
|
@@ -547,14 +559,17 @@ export function createResumeLegs(ctx) {
|
|
|
547
559
|
const resolveResumeSpec = async (ctx, req, auth, lease) => {
|
|
548
560
|
const engineNotices = [];
|
|
549
561
|
const execution = await resolveExecutionContext(deps, { kind: "continuation", root: auth.sessionId, principal: auth.principal });
|
|
550
|
-
const
|
|
562
|
+
const resolved = await deps.resolveSpec({ ...ctx.body, ...ONE_SHOT_SUBMIT_STRIP }, req, auth, {
|
|
551
563
|
leg: "resume",
|
|
552
564
|
onNotice: (n) => engineNotices.push(n),
|
|
553
565
|
...(ctx.unattendedLeg === true ? { unattendedLeg: true } : {}),
|
|
554
566
|
lease,
|
|
555
567
|
execution,
|
|
556
|
-
})
|
|
557
|
-
|
|
568
|
+
});
|
|
569
|
+
const legFacts = legFactsOf(resolved);
|
|
570
|
+
const runner = runnerFor(resolved);
|
|
571
|
+
const spec = stampSpecRoot(resolved, execution);
|
|
572
|
+
return { spec, runner, legFacts, engineNotices, execution };
|
|
558
573
|
};
|
|
559
574
|
const refuseStoredBodyReplay = (sessionId, refusal) => {
|
|
560
575
|
deps.logger?.warn?.("resume_refused_stored_body", { sessionId, ...storedBodyReplayLogFields(refusal) });
|
|
@@ -566,8 +581,8 @@ export function createResumeLegs(ctx) {
|
|
|
566
581
|
return { ok: false, answer: refuseStoredBodyReplay(auth.sessionId, replay) };
|
|
567
582
|
const lease = deps.peerDesk.lease("resume");
|
|
568
583
|
try {
|
|
569
|
-
const { spec, engineNotices, execution } = await resolveResumeSpec(ctx, req, auth, lease);
|
|
570
|
-
return { ok: true, spec, engineNotices, execution, peerLease: lease };
|
|
584
|
+
const { spec, runner, legFacts, engineNotices, execution } = await resolveResumeSpec(ctx, req, auth, lease);
|
|
585
|
+
return { ok: true, spec, runner, legFacts, engineNotices, execution, peerLease: lease };
|
|
571
586
|
}
|
|
572
587
|
catch (e) {
|
|
573
588
|
lease.release();
|
|
@@ -603,7 +618,7 @@ export function createResumeLegs(ctx) {
|
|
|
603
618
|
const reparkStatus = outcome.gate === "plan_review" ? "needs_review" : "suspended";
|
|
604
619
|
const commitResumeCtx = () => Promise.resolve().then(() => deps.checkpointStore.putCtx(resumeCtx.sessionId, sealCheckpointCtx({ ...resumeCtx.ctx, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, resumeCtx.sessionId))).catch((e) => {
|
|
605
620
|
deps.metrics?.inc("resume_ctx_not_persisted_total");
|
|
606
|
-
deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error: errorText(e), note: "this continuation runs with the body it was given; the durable rebuild input still holds the PREVIOUS body, so the NEXT continuation of this session rebuilds from that one
|
|
621
|
+
deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error: errorText(e), note: "this continuation runs with the body it was given; the durable rebuild input still holds the PREVIOUS body, so the NEXT continuation of this session rebuilds from that one — its permission mode is never wider than this leg's, but if this leg restated its MCP / A2A peer tables (mcpServers / a2aPeers on the resume request), a later continuation that does not restate them runs with the previous tables again" });
|
|
607
622
|
});
|
|
608
623
|
const legKey = createHash("sha256").update(String(token)).digest("hex");
|
|
609
624
|
const streamApprovalOn = resolveStreamApprovalGate({
|
|
@@ -777,7 +792,7 @@ export function createResumeLegs(ctx) {
|
|
|
777
792
|
let unregisterEngineNotice;
|
|
778
793
|
try {
|
|
779
794
|
const instructionLeg = createInstructionSelectionLeg();
|
|
780
|
-
const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills:
|
|
795
|
+
const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: args.legFacts?.skills });
|
|
781
796
|
result = await instructionLeg.run(sessionId, () => withModelReachScope({ sessionId, taskId }, () => withPrincipal(principal, async () => {
|
|
782
797
|
const resumeNotifiedKeys = new NotifiedKeys();
|
|
783
798
|
if (deps.runStore && taskId) {
|
|
@@ -832,9 +847,8 @@ export function createResumeLegs(ctx) {
|
|
|
832
847
|
if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
|
|
833
848
|
defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
|
|
834
849
|
}
|
|
835
|
-
const hadRow = isFleetAgentTerminalNotification(n) ? (fleetPub?.onChildTerminal(n.sessionId ?? n.task_id, n.status, n.task_id, n.toolUseId) ?? false) : false;
|
|
836
850
|
const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
|
|
837
|
-
deps.logger?.info?.("task_notification_observed", { route: "resume-verify", taskId: n.task_id, taskType: n.task_type, status: n.status,
|
|
851
|
+
deps.logger?.info?.("task_notification_observed", { route: "resume-verify", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
|
|
838
852
|
if (parked) {
|
|
839
853
|
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, principal ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume-verify", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
840
854
|
}
|
|
@@ -856,7 +870,7 @@ export function createResumeLegs(ctx) {
|
|
|
856
870
|
resumeLegLive = true;
|
|
857
871
|
const vrEngine = await resumeWithVerification(legRunner, token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, resumeObjective, verifyRounds, verifyInternals);
|
|
858
872
|
const vrCause = cancelCtrl.cause();
|
|
859
|
-
await voidVerifierPauseCard(vrEngine,
|
|
873
|
+
await voidVerifierPauseCard(vrEngine, legRunner);
|
|
860
874
|
const vrJudged = atHostBoundary(vrEngine, sessionId);
|
|
861
875
|
if (vrJudged.terminal.kind === "paused")
|
|
862
876
|
heldPark = vrJudged;
|
|
@@ -876,9 +890,8 @@ export function createResumeLegs(ctx) {
|
|
|
876
890
|
const ap = vAppend;
|
|
877
891
|
await appendPromptManifest(ap, deps.promptManifests, taskId);
|
|
878
892
|
if (reSuspended || vrReopened) {
|
|
879
|
-
await appendModelUsageDelta(ap, deps.modelUsage, taskId);
|
|
880
893
|
const vrParkCallId = reSuspended ? await parkToolCallId(vr, deps.checkpointStore) : undefined;
|
|
881
|
-
await ap
|
|
894
|
+
await appendParkRow(ap, { modelUsage: deps.modelUsage, taskId }, reParkEvent ?? reparkStatus, { terminal: vrPaused, ...(vrParkCallId !== undefined ? { toolCallId: vrParkCallId } : {}) }, vrReopened ? (failureCodeOf(vr.terminal) ?? null) : undefined);
|
|
882
895
|
}
|
|
883
896
|
else {
|
|
884
897
|
safe = await attachModelUsage(safe, { append: ap, getEvents: (id, a) => rs2.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
|
|
@@ -940,7 +953,7 @@ export function createResumeLegs(ctx) {
|
|
|
940
953
|
const driveResume = async () => {
|
|
941
954
|
resumeLegLive = true;
|
|
942
955
|
const tailContentMode = resumeTaskConfig.forwardSubagentEvents === true ? "on" : "progress_only";
|
|
943
|
-
const resumeWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage),
|
|
956
|
+
const resumeWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), args.legFacts?.sessionWitness);
|
|
944
957
|
const stream = await legRunner.resumeStream(token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, {
|
|
945
958
|
...launchInternals,
|
|
946
959
|
onForwardEvent: (e) => {
|
|
@@ -977,9 +990,8 @@ export function createResumeLegs(ctx) {
|
|
|
977
990
|
if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
|
|
978
991
|
defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
|
|
979
992
|
}
|
|
980
|
-
const hadRow = isFleetAgentTerminalNotification(n) ? (fleetPub?.onChildTerminal(n.sessionId ?? n.task_id, n.status, n.task_id, n.toolUseId) ?? false) : false;
|
|
981
993
|
const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
|
|
982
|
-
deps.logger?.info?.("task_notification_observed", { route: "resume", taskId: n.task_id, taskType: n.task_type, status: n.status,
|
|
994
|
+
deps.logger?.info?.("task_notification_observed", { route: "resume", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
|
|
983
995
|
if (parked) {
|
|
984
996
|
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, principal ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
985
997
|
}
|
|
@@ -1141,21 +1153,18 @@ export function createResumeLegs(ctx) {
|
|
|
1141
1153
|
heldPark = r;
|
|
1142
1154
|
const rPark = r.terminal.kind === "paused" ? outwardPlane(r.terminal).status : undefined;
|
|
1143
1155
|
if (rPark === "suspended") {
|
|
1144
|
-
await append
|
|
1145
|
-
await appendModelUsageDelta(append, deps.modelUsage, taskId);
|
|
1156
|
+
await appendParkRow(append, { modelUsage: deps.modelUsage, taskId }, "suspended", await graftParkToolCallId(r, deps.checkpointStore));
|
|
1146
1157
|
return r;
|
|
1147
1158
|
}
|
|
1148
1159
|
if (rPark === "needs_review") {
|
|
1149
|
-
await append
|
|
1150
|
-
await appendModelUsageDelta(append, deps.modelUsage, taskId);
|
|
1160
|
+
await appendParkRow(append, { modelUsage: deps.modelUsage, taskId }, "needs_review", r);
|
|
1151
1161
|
return r;
|
|
1152
1162
|
}
|
|
1153
1163
|
const settledLeg = await reopenedAfterLeg(r, causeAtDone !== undefined);
|
|
1154
1164
|
if (settledLeg.reopened) {
|
|
1155
1165
|
reopenConfirmedPark = true;
|
|
1156
1166
|
try {
|
|
1157
|
-
await append
|
|
1158
|
-
await appendModelUsageDelta(append, deps.modelUsage, taskId);
|
|
1167
|
+
await appendParkRow(append, { modelUsage: deps.modelUsage, taskId }, reparkStatus, r, failureCodeOf(r.terminal) ?? null);
|
|
1159
1168
|
}
|
|
1160
1169
|
catch {
|
|
1161
1170
|
}
|
|
@@ -1311,7 +1320,7 @@ export function createResumeLegs(ctx) {
|
|
|
1311
1320
|
const owner = decodeCheckpointScope(scope ?? CHECKPOINT_PUBLIC_SCOPE);
|
|
1312
1321
|
return owner === undefined || owner === decider.principal;
|
|
1313
1322
|
}
|
|
1314
|
-
async function resumePreempted(sessionId, req, acceptEarly, decider) {
|
|
1323
|
+
async function resumePreempted(sessionId, req, acceptEarly, decider, restatement) {
|
|
1315
1324
|
const cs = deps.checkpointStore;
|
|
1316
1325
|
const RESUMABLE_GATE_KIND = "resource_limit";
|
|
1317
1326
|
const preemptBinding = { gateKinds: [RESUMABLE_GATE_KIND] };
|
|
@@ -1361,7 +1370,7 @@ export function createResumeLegs(ctx) {
|
|
|
1361
1370
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1362
1371
|
if (ctxRead.kind === "absent")
|
|
1363
1372
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1364
|
-
const ctx = ctxRead.ctx;
|
|
1373
|
+
const ctx = restateResumeCtx(ctxRead.ctx, restatement);
|
|
1365
1374
|
const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
|
|
1366
1375
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1367
1376
|
if (!resolved.ok)
|
|
@@ -1371,13 +1380,13 @@ export function createResumeLegs(ctx) {
|
|
|
1371
1380
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
1372
1381
|
const verifyRounds = verifyRoundsFromBody(ctx.body);
|
|
1373
1382
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1374
|
-
return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner:
|
|
1383
|
+
return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome: { gate: "resource_limit", decision: "continue" }, commitment: { kind: "gate_resolved", ...selectedGate }, verifyRounds, resumeCtx: { sessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
|
|
1375
1384
|
}
|
|
1376
1385
|
finally {
|
|
1377
1386
|
resolved.peerLease.release();
|
|
1378
1387
|
}
|
|
1379
1388
|
}
|
|
1380
|
-
async function startFreshHostTurn(sessionId, objective, principal, req, workflowDecision, runId) {
|
|
1389
|
+
async function startFreshHostTurn(sessionId, objective, principal, req, workflowDecision, runId, restatement) {
|
|
1381
1390
|
const cs = deps.checkpointStore;
|
|
1382
1391
|
if (!deps.runStore) {
|
|
1383
1392
|
return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
|
|
@@ -1387,8 +1396,8 @@ export function createResumeLegs(ctx) {
|
|
|
1387
1396
|
return resumeCtxCorruptAnswer(ctxRead.where);
|
|
1388
1397
|
if (ctxRead.kind === "unsealable")
|
|
1389
1398
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1390
|
-
const
|
|
1391
|
-
if (!
|
|
1399
|
+
const storedCtx = ctxRead.kind === "ok" ? ctxRead.ctx : null;
|
|
1400
|
+
if (!storedCtx) {
|
|
1392
1401
|
return {
|
|
1393
1402
|
status: 409,
|
|
1394
1403
|
body: refusalBody({
|
|
@@ -1401,6 +1410,7 @@ export function createResumeLegs(ctx) {
|
|
|
1401
1410
|
}),
|
|
1402
1411
|
};
|
|
1403
1412
|
}
|
|
1413
|
+
const ctx = restateResumeCtx(storedCtx, restatement);
|
|
1404
1414
|
const windowDenial = await usageWindowDenialFor(principal || GLOBAL_USAGE_KEY);
|
|
1405
1415
|
if (windowDenial)
|
|
1406
1416
|
return { status: windowDenial.status, body: windowDenial.body };
|
|
@@ -1412,7 +1422,7 @@ export function createResumeLegs(ctx) {
|
|
|
1412
1422
|
const { spec, engineNotices } = resolved;
|
|
1413
1423
|
const hostSpec = { ...spec, objective };
|
|
1414
1424
|
const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
|
|
1415
|
-
prepared: { spec: hostSpec, runner:
|
|
1425
|
+
prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, acceptance: createRunAcceptance({}, { objective }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1416
1426
|
fleetScope: resumeFleetScope(req, auth),
|
|
1417
1427
|
elicitOwner: principal ?? null,
|
|
1418
1428
|
source: "workflow_parked_decide",
|
|
@@ -1431,7 +1441,7 @@ export function createResumeLegs(ctx) {
|
|
|
1431
1441
|
resolved.peerLease.release();
|
|
1432
1442
|
}
|
|
1433
1443
|
}
|
|
1434
|
-
async function resumeWake(sessionId, message, caller, req, acceptEarly, workflowDecision, ownerLeaseAdmittedFor) {
|
|
1444
|
+
async function resumeWake(sessionId, message, caller, req, acceptEarly, workflowDecision, ownerLeaseAdmittedFor, restatement) {
|
|
1435
1445
|
const cs = deps.checkpointStore;
|
|
1436
1446
|
const wakeBinding = { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" };
|
|
1437
1447
|
const token = (await cs.findPendingTokenBySession(sessionId, undefined, wakeBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
|
|
@@ -1488,7 +1498,7 @@ export function createResumeLegs(ctx) {
|
|
|
1488
1498
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1489
1499
|
if (ctxRead.kind === "absent")
|
|
1490
1500
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1491
|
-
const ctx = ctxRead.ctx;
|
|
1501
|
+
const ctx = restateResumeCtx(ctxRead.ctx, restatement);
|
|
1492
1502
|
const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
|
|
1493
1503
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1494
1504
|
if (!resolved.ok)
|
|
@@ -1499,7 +1509,8 @@ export function createResumeLegs(ctx) {
|
|
|
1499
1509
|
return await driveResumeIntoRunLog({
|
|
1500
1510
|
peerLease: resolved.peerLease,
|
|
1501
1511
|
execution: resolved.execution,
|
|
1502
|
-
runner:
|
|
1512
|
+
runner: resolved.runner,
|
|
1513
|
+
legFacts: resolved.legFacts,
|
|
1503
1514
|
token,
|
|
1504
1515
|
sessionId: cp.sessionId,
|
|
1505
1516
|
principal: auth.principal,
|
|
@@ -1599,8 +1610,9 @@ export function createResumeLegs(ctx) {
|
|
|
1599
1610
|
return refuse(refuseStoredBodyReplay(sessionId, replay));
|
|
1600
1611
|
return { ok: true, prepared: { sessionId, token, cp, ctx: ctxRead.ctx } };
|
|
1601
1612
|
}
|
|
1602
|
-
async function drivePlanReview(prepared, decision, editedPlan, reason, hostDecision, req, acceptEarly, permissionModeAfter) {
|
|
1603
|
-
const { sessionId, token, cp
|
|
1613
|
+
async function drivePlanReview(prepared, decision, editedPlan, reason, hostDecision, req, acceptEarly, permissionModeAfter, restatement) {
|
|
1614
|
+
const { sessionId, token, cp } = prepared;
|
|
1615
|
+
const ctx = restateResumeCtx(prepared.ctx, restatement);
|
|
1604
1616
|
if ((await deps.checkpointStore.findPendingTokenBySession(sessionId, undefined, { gateKinds: ["plan_review"] })) !== token)
|
|
1605
1617
|
return notResumableAnswer();
|
|
1606
1618
|
const auth = { sessionId: cp.sessionId, principal: decodeCheckpointScope(cp.scope), memoryScope: ctx.memoryScope };
|
|
@@ -1625,20 +1637,26 @@ export function createResumeLegs(ctx) {
|
|
|
1625
1637
|
hostDecision,
|
|
1626
1638
|
};
|
|
1627
1639
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1628
|
-
const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner:
|
|
1640
|
+
const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: cp.sessionId, principal: auth.principal, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...selectedGate }, verifyRounds, resumeCtx: { sessionId, ctx: rebuildCtx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
|
|
1629
1641
|
return out;
|
|
1630
1642
|
}
|
|
1631
1643
|
finally {
|
|
1632
1644
|
resolved.peerLease.release();
|
|
1633
1645
|
}
|
|
1634
1646
|
}
|
|
1647
|
+
const sessionNotifyDoor = createSessionNotifyDoor({
|
|
1648
|
+
activeTaskIdOf: async (sessionId) => deps.runStore?.getActiveTaskId?.(sessionId),
|
|
1649
|
+
liveRuns: steerableRuns,
|
|
1650
|
+
inbox: deps.workflowCompletionInbox,
|
|
1651
|
+
headOf: headReadOf(deps.sessionStorage),
|
|
1652
|
+
});
|
|
1635
1653
|
const routeCtxBase = {
|
|
1636
1654
|
deps,
|
|
1637
1655
|
registry: { idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters },
|
|
1638
1656
|
helpers: { readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk },
|
|
1639
1657
|
local: { images: createImagesLocal(deps), sessions: createSessionsLocal(), sessionSync: createSessionSyncLocal(), capabilities: createCapabilitiesLocal() },
|
|
1640
|
-
legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview },
|
|
1658
|
+
legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview, sessionNotify: sessionNotifyDoor },
|
|
1641
1659
|
};
|
|
1642
|
-
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, mayDiscloseRowError, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview };
|
|
1660
|
+
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, mayDiscloseRowError, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
|
|
1643
1661
|
}
|
|
1644
1662
|
//# sourceMappingURL=resume-legs.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 续跑请求的**重述键** —— 「我此刻的对端表」随续跑请求一起说出来(唯一属主)。
|
|
3
|
+
*
|
|
4
|
+
* ## 律(一条)
|
|
5
|
+
* 续跑请求体可带 {@link RESUME_RESTATABLE_KEYS} 里的键(今天两只:`mcpServers` / `a2aPeers`),键名与值形 = 提交体(`POST /v1/tasks`)的同一键:
|
|
6
|
+
* · **在场**(值不是 `undefined` / `null`)⇒ 先过提交腿**同一只**判官(`assertRequestMcpEntries` / `assertRequestA2aEntries`;坏形 = 与提交腿同码同句的
|
|
7
|
+
* 400,判在续跑腿任何状态改动之前),再**取代**续跑重建输入(`checkpoint_ctx` 体)里的那一键:本次重建读它,续跑赢下 CAS 之后随重建输入一起写回
|
|
8
|
+
* (`DriveResumeArgs.resumeCtx` 那一只写点)⇒ 之后的续跑在没有新重述时重放的也是它;
|
|
9
|
+
* · **缺席**(或 `null`,与提交体「缺席或 `null` = 没声明」同一读法)⇒ 存量体那一键原样重放(冻结读法)。
|
|
10
|
+
* 重建之后的路与存量体逐字同一条(`resolveSpec` 的续跑腿:部署锁、闸、部署保留名、合并、对端座登记、用户面通告),所以一份重述在本部署上能挂上什么,
|
|
11
|
+
* 与它作为一次新提交能挂上什么是同一个答案;引擎从 `ResumeTaskConfig.mcp` / `.a2a`(与 `TaskSpec` 同键)收到的就是这张表。
|
|
12
|
+
*
|
|
13
|
+
* ## 不在本仓判的
|
|
14
|
+
* 「停驻快照里那一只调用的目标台还在不在当前表里」是引擎续跑准入的判(引擎 7.61.0 起三码各答各形,以 core 为准:工具不在了 ⇒ `resume.tool_unavailable`、同名而已不是批准时那一只 ⇒ `resume.tool_contract_mismatch`(两者重开检查点)、还是那一只而面或声明变了 ⇒ `resume.target_moved`(否决);本服务逐字过境)—— 本服务只负责把当前表送到,不自判、不预拒。
|
|
15
|
+
*
|
|
16
|
+
* ## 为什么是一张闭表
|
|
17
|
+
* 与提交腿的一次性动作那张闭表(`resume-legs.ts` 的 `ONE_SHOT_SUBMIT_KEYS`:重建时剥掉)对称 —— 那张说「哪些提交键不随重建走」,这张说「哪些提交键由续跑请求重述」。
|
|
18
|
+
* 加一键 = 改这条律本身:判官表 {@link RESTATEMENT_JUDGES} 缺行即编译红,接收它的续跑门各自在键闭集里声明它。
|
|
19
|
+
*/
|
|
20
|
+
import type { TaskRequestBody } from "./wire-types.js";
|
|
21
|
+
import type { CheckpointCtx } from "./route-ctx.js";
|
|
22
|
+
/** 续跑请求可重述的提交键(闭集;`satisfies` 钉在提交体的具名键上 —— 写一个提交体上没有的词 = 编译红)。 */
|
|
23
|
+
export declare const RESUME_RESTATABLE_KEYS: readonly ["a2aPeers", "mcpServers"];
|
|
24
|
+
export type ResumeRestatableKey = (typeof RESUME_RESTATABLE_KEYS)[number];
|
|
25
|
+
/** 一次续跑请求读出的重述(只含在场的键;读者 {@link readResumeRestatement},用者 {@link restateResumeCtx})。 */
|
|
26
|
+
export type ResumeRestatement = {
|
|
27
|
+
readonly [K in ResumeRestatableKey]?: TaskRequestBody[K];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* 从一份续跑请求体里读出重述:在场的键逐一过判官,全部过 ⇒ 交回只含在场键的重述;一键都不在 ⇒ `undefined`(冻结读法)。
|
|
31
|
+
* 判官的拒原样抛出(调用方是路由,`HttpError` 由分发器按提交腿同一只渲染器落 wire)。体不是对象 ⇒ `undefined`(体形由各门自己的根形门答)。
|
|
32
|
+
*/
|
|
33
|
+
export declare function readResumeRestatement(body: unknown): ResumeRestatement | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* 把重述盖进续跑重建输入:在场的键取代体里的同名键,其余位(记忆域 / 无人值守标 / 读法记号 / 写者版本)原样随行。`undefined` ⇒ 原 ctx 原样(同一个对象)。
|
|
36
|
+
* 各续跑腿在读出 ctx 的那一拍调一次,之后重建(`resolveResumeSpecOrBlocked`)与写回(`resumeCtx`)读的都是这一份。
|
|
37
|
+
*/
|
|
38
|
+
export declare function restateResumeCtx(ctx: CheckpointCtx, restatement: ResumeRestatement | undefined): CheckpointCtx;
|
|
39
|
+
//# sourceMappingURL=resume-restatement.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { assertRequestMcpEntries } from "../task-mcp.js";
|
|
2
|
+
import { assertRequestA2aEntries } from "../task-a2a.js";
|
|
3
|
+
export const RESUME_RESTATABLE_KEYS = ["a2aPeers", "mcpServers"];
|
|
4
|
+
const RESTATEMENT_JUDGES = {
|
|
5
|
+
a2aPeers: assertRequestA2aEntries,
|
|
6
|
+
mcpServers: assertRequestMcpEntries,
|
|
7
|
+
};
|
|
8
|
+
export function readResumeRestatement(body) {
|
|
9
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
10
|
+
return undefined;
|
|
11
|
+
const raw = body;
|
|
12
|
+
let out;
|
|
13
|
+
for (const key of RESUME_RESTATABLE_KEYS) {
|
|
14
|
+
const value = Object.hasOwn(raw, key) ? raw[key] : undefined;
|
|
15
|
+
if (value === undefined || value === null)
|
|
16
|
+
continue;
|
|
17
|
+
RESTATEMENT_JUDGES[key](value);
|
|
18
|
+
(out ??= {})[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
export function restateResumeCtx(ctx, restatement) {
|
|
23
|
+
return restatement === undefined ? ctx : { ...ctx, body: { ...ctx.body, ...restatement } };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=resume-restatement.js.map
|