@sema-agent/server 7.138.0 → 7.140.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 +457 -7
- package/README.md +7 -4
- package/README.zh-CN.md +6 -4
- package/USAGE.md +91 -41
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/lib/lanes.json +3 -2
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +26 -26
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/arms.js +1 -3
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/bench/s1/run-firm.js +2 -2
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +8 -3
- package/dist/boot/device-lane.js +7 -2
- package/dist/boot/execution-env.d.ts +4 -2
- package/dist/boot/execution-env.js +28 -34
- package/dist/boot/execution-lane.d.ts +9 -1
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/governance-seams.d.ts +3 -2
- package/dist/boot/governance-seams.js +9 -11
- package/dist/boot/memory-boundary.d.ts +14 -51
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +15 -11
- package/dist/boot/memory-consolidation.js +25 -14
- package/dist/boot/resolve-spec.d.ts +4 -6
- package/dist/boot/resolve-spec.js +10 -13
- package/dist/boot/retention-lane.d.ts +5 -5
- package/dist/boot/retention-lane.js +0 -6
- package/dist/boot/runner-deps.d.ts +6 -4
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.d.ts +0 -3
- package/dist/boot/session-faces.js +15 -8
- package/dist/boot/stage-02-web-admin-pull.js +2 -2
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +2 -6
- package/dist/boot/stage-06-runners.js +2 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -6
- package/dist/boot/stage-08-reapers.d.ts +2 -6
- package/dist/boot/stage-09-leader.d.ts +2 -6
- package/dist/boot/stage-09-leader.js +1 -2
- package/dist/boot/stage-10-http-server.d.ts +2 -6
- package/dist/boot/stage-10-http-server.js +7 -6
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +27 -40
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +37 -11
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/mcp-probe.js +1 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +15 -7
- package/dist/capability-facts.js +8 -3
- package/dist/config-catalog.js +9 -8
- package/dist/config-invariants.d.ts +23 -3
- package/dist/config-invariants.js +42 -0
- package/dist/config-provider.d.ts +33 -37
- package/dist/config-provider.js +51 -30
- package/dist/config-types.d.ts +21 -7
- package/dist/config.d.ts +33 -0
- package/dist/config.js +46 -16
- package/dist/delegated-session-owner.d.ts +4 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/deployment-shape.d.ts +10 -9
- package/dist/deployment-shape.js +4 -4
- package/dist/device-enrollment.d.ts +41 -2
- package/dist/device-enrollment.js +27 -12
- package/dist/device-store.d.ts +58 -85
- package/dist/device-store.js +19 -49
- package/dist/device-ws-hub.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +5 -4
- package/dist/exec-cut.d.ts +60 -0
- package/dist/exec-cut.js +36 -0
- package/dist/execution-lane-caps.d.ts +115 -105
- package/dist/execution-lane-caps.js +76 -82
- package/dist/execution-placement.d.ts +259 -0
- package/dist/execution-placement.js +199 -0
- package/dist/field-conflict.d.ts +3 -2
- package/dist/field-conflict.js +1 -0
- package/dist/hosted-posture.d.ts +2 -2
- package/dist/http/admission.js +8 -19
- package/dist/http/checkpoint-ctx.d.ts +21 -12
- package/dist/http/checkpoint-ctx.js +4 -2
- package/dist/http/claimed-run.d.ts +1 -1
- package/dist/http/durable-run-leg.js +9 -5
- package/dist/http/execution-context.d.ts +218 -0
- package/dist/http/execution-context.js +330 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +63 -36
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-ctx.d.ts +14 -8
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/background.d.ts +29 -1
- package/dist/http/routes/background.js +29 -2
- package/dist/http/routes/devices.d.ts +13 -19
- package/dist/http/routes/devices.js +21 -26
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-compliance.js +8 -1
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +5 -0
- package/dist/http/routes/session-sync.js +110 -15
- package/dist/http/routes/sessions.d.ts +6 -0
- package/dist/http/routes/sessions.js +143 -22
- package/dist/http/routes/side-query.d.ts +12 -4
- package/dist/http/routes/side-query.js +4 -5
- package/dist/http/routes/tasks.js +41 -33
- package/dist/http/server.d.ts +40 -44
- package/dist/http/server.js +13 -2
- package/dist/http/session-inherit-env.d.ts +3 -4
- package/dist/http/session-inherit-env.js +1 -1
- package/dist/http/wire-types.d.ts +8 -12
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +29 -5
- package/dist/memory-scope.js +16 -4
- package/dist/memory-sync-client.d.ts +70 -18
- package/dist/memory-sync-client.js +215 -117
- package/dist/memory-sync.d.ts +1 -1
- package/dist/memory-sync.js +3 -2
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +12 -0
- package/dist/observability/fail-open.js +12 -0
- package/dist/observability/run-terminal.js +0 -1
- package/dist/orchestration/workflow-notify-journal.js +4 -4
- package/dist/org-memory-admission.d.ts +4 -3
- package/dist/org-memory-admission.js +6 -6
- package/dist/parked-decide.d.ts +34 -9
- package/dist/parked-decide.js +12 -19
- package/dist/parked-revive-surface.d.ts +12 -15
- package/dist/parked-revive-surface.js +3 -6
- package/dist/peer-seat.d.ts +13 -7
- package/dist/peer-seat.js +37 -3
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-file.d.ts +7 -0
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
- package/dist/plugins/approval-ask-store-sql.js +44 -26
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/caching-session-store.d.ts +6 -2
- package/dist/plugins/caching-session-store.js +9 -3
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +6 -5
- package/dist/plugins/checkpoint-store-sql.js +21 -23
- package/dist/plugins/device-store-sql.d.ts +25 -51
- package/dist/plugins/device-store-sql.js +68 -122
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +151 -0
- package/dist/plugins/execution-placement-sql.js +223 -0
- package/dist/plugins/file-history-store-sql.d.ts +9 -8
- package/dist/plugins/file-history-store-sql.js +9 -9
- package/dist/plugins/file-run-store.d.ts +6 -1
- package/dist/plugins/file-run-store.js +4 -0
- package/dist/plugins/fork-routing-session-store.d.ts +6 -0
- package/dist/plugins/fork-routing-session-store.js +16 -0
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-session-store.d.ts +149 -50
- package/dist/plugins/local-session-store.js +382 -107
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-key-guards.d.ts +4 -0
- package/dist/plugins/memory-key-guards.js +1 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +117 -8
- package/dist/plugins/one-time-migrations.js +408 -38
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -19
- package/dist/plugins/permission-rule-store-sql.js +29 -32
- package/dist/plugins/pg-pool.d.ts +7 -3
- package/dist/plugins/pg-session-storage.d.ts +31 -20
- package/dist/plugins/pg-session-storage.js +120 -52
- package/dist/plugins/remote-env-adb.d.ts +18 -19
- package/dist/plugins/remote-env-adb.js +91 -66
- package/dist/plugins/remote-env-device.d.ts +23 -31
- package/dist/plugins/remote-env-device.js +19 -17
- package/dist/plugins/remote-env-e2b.d.ts +27 -21
- package/dist/plugins/remote-env-e2b.js +91 -45
- package/dist/plugins/remote-env-file-error.d.ts +3 -1
- package/dist/plugins/remote-env-file-error.js +9 -3
- package/dist/plugins/remote-env-host.d.ts +31 -34
- package/dist/plugins/remote-env-host.js +91 -72
- package/dist/plugins/remote-env-k8s.d.ts +13 -29
- package/dist/plugins/remote-env-k8s.js +63 -55
- package/dist/plugins/remote-env-local-docker.d.ts +24 -12
- package/dist/plugins/remote-env-local-docker.js +49 -61
- package/dist/plugins/remote-env-ssh.d.ts +11 -19
- package/dist/plugins/remote-env-ssh.js +74 -57
- package/dist/plugins/remote-shell.d.ts +100 -3
- package/dist/plugins/remote-shell.js +166 -2
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +10 -7
- package/dist/plugins/retention-store-sql.js +13 -7
- package/dist/plugins/run-store-sql.d.ts +13 -3
- package/dist/plugins/run-store-sql.js +20 -15
- package/dist/plugins/schema-consistency.d.ts +21 -11
- package/dist/plugins/schema-consistency.js +15 -9
- package/dist/plugins/schema-drift-sentence.d.ts +27 -0
- package/dist/plugins/schema-drift-sentence.js +38 -0
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-fork.d.ts +54 -0
- package/dist/plugins/session-fork.js +38 -1
- package/dist/plugins/session-row-sql.d.ts +22 -0
- package/dist/plugins/session-row-sql.js +81 -0
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +5 -7
- package/dist/plugins/store-backend.js +23 -11
- package/dist/plugins/store-contracts.d.ts +25 -5
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.d.ts +12 -7
- package/dist/plugins/tidb-pool.js +13 -7
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +57 -26
- package/dist/plugins/tidb-session-store.js +127 -59
- package/dist/plugins/tool-result-store-sql.d.ts +5 -4
- package/dist/plugins/tool-result-store-sql.js +21 -13
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/project-memory.d.ts +9 -15
- package/dist/project-memory.js +5 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +6 -7
- package/dist/request-value-closure.js +1 -3
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-local.d.ts +6 -0
- package/dist/run-local.js +34 -35
- package/dist/runs.d.ts +10 -5
- package/dist/runs.js +52 -66
- package/dist/security.d.ts +38 -12
- package/dist/security.js +8 -2
- package/dist/server-secret-env.d.ts +9 -5
- package/dist/session-children-retire.d.ts +27 -9
- package/dist/session-children-retire.js +9 -5
- package/dist/session-incarnation.d.ts +20 -10
- package/dist/session-incarnation.js +5 -3
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-row.d.ts +114 -5
- package/dist/session-row.js +55 -5
- package/dist/session-titler.d.ts +2 -2
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-a2a.js +5 -6
- package/dist/task-cwd.d.ts +6 -1
- package/dist/task-mcp.d.ts +22 -9
- package/dist/task-mcp.js +17 -9
- package/dist/terminal.d.ts +27 -0
- package/dist/terminal.js +6 -0
- package/dist/tool-approval.d.ts +6 -0
- package/dist/tool-approval.js +8 -1
- package/dist/trace/project.d.ts +1 -0
- package/dist/trace/project.js +1 -0
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +80 -28
- package/dist/trace/self-minted-wire.d.ts +169 -2
- package/dist/trace/self-minted-wire.js +54 -1
- package/dist/url-refusal.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +17 -3
- package/dist/web-admin-client/apply-effective.js +20 -10
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +3 -2
- package/dist/web-admin-client/types.d.ts +6 -0
- package/package.json +3 -3
- package/wire-changes/server@7.139.0.json +348 -0
- package/wire-changes/server@7.140.0.json +184 -0
- package/dist/http/device-placement.d.ts +0 -175
- package/dist/http/device-placement.js +0 -145
package/dist/http/resume-legs.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { uuidv7, resumeWithVerification, CheckpointError, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY
|
|
3
|
+
import { uuidv7, resumeWithVerification, CheckpointError, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
|
|
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
7
|
import { createSessionWorkspaceRecorder, legSessionWitnessOf, 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
|
-
const headUnavailable = async (sessionId) => {
|
|
10
|
-
throw new Error(`parked decide cannot verify which occupant session ${sessionId} belongs to: this deployment's session store has no head read (headOf; every built-in store has one) — refusing rather than resuming unverified`);
|
|
11
|
-
};
|
|
12
9
|
import { HttpError, decodeCheckpointScope, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
13
10
|
import { graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort } from "../runs.js";
|
|
14
|
-
import { failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane } from "../terminal.js";
|
|
11
|
+
import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane } from "../terminal.js";
|
|
15
12
|
import { buildCancelledLedgerRow, createRunAbort, mintCancelledResult } from "../run-cancel-context.js";
|
|
16
13
|
import { isTerminalRunStatus } from "../plugins/store-contracts.js";
|
|
17
14
|
import { readTurnActivityMs, recordTurnActivity } from "../turn-activity.js";
|
|
@@ -50,10 +47,11 @@ import { createImagesLocal } from "./routes/images.js";
|
|
|
50
47
|
import { createCapabilitiesLocal } from "./routes/capabilities.js";
|
|
51
48
|
import { gatedPrincipal, explicitOperatorOk, runIdentityOf } from "./principal-gate.js";
|
|
52
49
|
import { buildActiveRunConflict, resumeEntryForGate } from "./active-run-conflict.js";
|
|
53
|
-
import {
|
|
50
|
+
import { commitExecutionContext, isRootSessionGoneError, resolveExecutionContext, rootSessionAbsentAnswer, stampSpecRoot } from "./execution-context.js";
|
|
54
51
|
import { commitSessionInheritEnv } from "./session-inherit-env.js";
|
|
55
52
|
import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
|
|
56
53
|
import { deploymentListAsks } from "../approval.js";
|
|
54
|
+
import { isParkLedgerEventType } from "../trace/ledger-events.js";
|
|
57
55
|
import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnsealableAnswer } from "./resume-ctx-read.js";
|
|
58
56
|
import { buildCheckpointVersionKeys, resumeBlockedByPolicyAnswer, resumeRefusalWithCard, sealCheckpointCtx, storedBodyReplayAnswer, storedBodyReplayLogFields, withPermissionModeRewritten } from "./checkpoint-ctx.js";
|
|
59
57
|
import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
|
|
@@ -64,12 +62,6 @@ import { fieldConflictFacts } from "../field-conflict.js";
|
|
|
64
62
|
function legMayHaveReopenedCheckpoint(r) {
|
|
65
63
|
return r.terminal.kind === "failed" && nestedPauseOf(r.terminal) === undefined;
|
|
66
64
|
}
|
|
67
|
-
function nestedParkStatusOf(r) {
|
|
68
|
-
const paused = nestedPauseOf(r.terminal);
|
|
69
|
-
if (paused === undefined)
|
|
70
|
-
return undefined;
|
|
71
|
-
return PAUSE_REGISTRY[paused.gate.kind].taskStatus;
|
|
72
|
-
}
|
|
73
65
|
const WORKER_SWAP_REDEEMABLE = {
|
|
74
66
|
version_newer: true,
|
|
75
67
|
env_factory_missing: true,
|
|
@@ -102,6 +94,7 @@ const WORKER_SWAP_REDEEMABLE = {
|
|
|
102
94
|
unknown_model_ref: true,
|
|
103
95
|
not_a_model_ref: true,
|
|
104
96
|
unknown_role_word: true,
|
|
97
|
+
no_model_for_role: true,
|
|
105
98
|
};
|
|
106
99
|
function checkpointRowRedeemableElsewhere(reason) {
|
|
107
100
|
return reason !== undefined && WORKER_SWAP_REDEEMABLE[reason] === true;
|
|
@@ -416,10 +409,30 @@ export function createResumeLegs(ctx) {
|
|
|
416
409
|
checkpointStore: cs,
|
|
417
410
|
registry: defaultTaskRegistry,
|
|
418
411
|
reviveSurface: parkedSurface,
|
|
419
|
-
headOf: headReadOf(deps.sessionStorage) ?? headUnavailable,
|
|
420
412
|
...(deps.parkedKnownAgentTypes ? { knownAgentTypes: deps.parkedKnownAgentTypes } : {}),
|
|
421
413
|
...(deps.parkedReviveInheritedGate ? { rebuildInheritedGate: deps.parkedReviveInheritedGate } : {}),
|
|
422
414
|
...(deps.toolApproval ? { approverSeatFor: windowZeroSeatOf(deps.toolApproval) } : {}),
|
|
415
|
+
execution: {
|
|
416
|
+
resolve: async (root) => {
|
|
417
|
+
let ctx;
|
|
418
|
+
try {
|
|
419
|
+
ctx = await resolveExecutionContext(deps, { kind: "continuation", root, principal: decodeCheckpointScope(cp.scope) });
|
|
420
|
+
}
|
|
421
|
+
catch (e) {
|
|
422
|
+
if (isRootSessionGoneError(e))
|
|
423
|
+
return { ok: false, gone: true };
|
|
424
|
+
if (e instanceof HttpError)
|
|
425
|
+
return { ok: false, gone: false, answer: resumeRefusalWithCard(resumeBlockedByPolicyAnswer(httpErrorRefusal(e)), true) };
|
|
426
|
+
throw e;
|
|
427
|
+
}
|
|
428
|
+
const occupant = ctx.occupant;
|
|
429
|
+
if (occupant === undefined) {
|
|
430
|
+
throw new Error(`parked decide: root session ${root} resolved without an occupant reading — the parked revive leg is wired to a session store without an execution placement seat (sessionStorage.executionPlacement), which createHttpServer should have refused at startup; refusing rather than resuming with nobody judging the root session's occupant after the claim`);
|
|
431
|
+
}
|
|
432
|
+
return { ok: true, ctx: { ...ctx, occupant } };
|
|
433
|
+
},
|
|
434
|
+
commitDeps: deps,
|
|
435
|
+
},
|
|
423
436
|
...(deps.logger ? { warn: parkWarn } : {}),
|
|
424
437
|
}, { ...parkedReq, selectedGate: captureSelectedGate() }, { handle: origin.handle, row: origin.row }));
|
|
425
438
|
void ctxPromise.catch(() => { });
|
|
@@ -520,7 +533,7 @@ export function createResumeLegs(ctx) {
|
|
|
520
533
|
hostDecision,
|
|
521
534
|
};
|
|
522
535
|
const verifyRounds = verifyRoundsFromBody(ctx.body);
|
|
523
|
-
const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, runner: runnerFor(spec), 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 } : {}) });
|
|
536
|
+
const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: runnerFor(spec), 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 } : {}) });
|
|
524
537
|
noteLateSettleIfAccepted(driven);
|
|
525
538
|
return driven;
|
|
526
539
|
}
|
|
@@ -528,17 +541,19 @@ export function createResumeLegs(ctx) {
|
|
|
528
541
|
resolved.peerLease.release();
|
|
529
542
|
}
|
|
530
543
|
}
|
|
531
|
-
const ONE_SHOT_SUBMIT_KEYS = ["resumeAt", "restoreFiles", "acceptPartialRestore", "rewindFilesTo", "
|
|
544
|
+
const ONE_SHOT_SUBMIT_KEYS = ["resumeAt", "restoreFiles", "acceptPartialRestore", "rewindFilesTo", "userAttachments", "images"];
|
|
532
545
|
const ONE_SHOT_SUBMIT_STRIP = Object.fromEntries(ONE_SHOT_SUBMIT_KEYS.map((k) => [k, undefined]));
|
|
533
546
|
const resolveResumeSpec = async (ctx, req, auth, lease) => {
|
|
534
547
|
const engineNotices = [];
|
|
535
|
-
const
|
|
548
|
+
const execution = await resolveExecutionContext(deps, { kind: "continuation", root: auth.sessionId, principal: auth.principal });
|
|
549
|
+
const spec = stampSpecRoot(await deps.resolveSpec({ ...ctx.body, ...ONE_SHOT_SUBMIT_STRIP }, req, auth, {
|
|
536
550
|
leg: "resume",
|
|
537
551
|
onNotice: (n) => engineNotices.push(n),
|
|
538
552
|
...(ctx.unattendedLeg === true ? { unattendedLeg: true } : {}),
|
|
539
553
|
lease,
|
|
540
|
-
|
|
541
|
-
|
|
554
|
+
execution,
|
|
555
|
+
}), execution);
|
|
556
|
+
return { spec, engineNotices, execution };
|
|
542
557
|
};
|
|
543
558
|
const refuseStoredBodyReplay = (sessionId, refusal) => {
|
|
544
559
|
deps.logger?.warn?.("resume_refused_stored_body", { sessionId, ...storedBodyReplayLogFields(refusal) });
|
|
@@ -550,8 +565,8 @@ export function createResumeLegs(ctx) {
|
|
|
550
565
|
return { ok: false, answer: refuseStoredBodyReplay(auth.sessionId, replay) };
|
|
551
566
|
const lease = deps.peerDesk.lease("resume");
|
|
552
567
|
try {
|
|
553
|
-
const { spec, engineNotices } = await resolveResumeSpec(ctx, req, auth, lease);
|
|
554
|
-
return { ok: true, spec, engineNotices, peerLease: lease };
|
|
568
|
+
const { spec, engineNotices, execution } = await resolveResumeSpec(ctx, req, auth, lease);
|
|
569
|
+
return { ok: true, spec, engineNotices, execution, peerLease: lease };
|
|
555
570
|
}
|
|
556
571
|
catch (e) {
|
|
557
572
|
lease.release();
|
|
@@ -583,7 +598,7 @@ export function createResumeLegs(ctx) {
|
|
|
583
598
|
}
|
|
584
599
|
async function driveResumeLeg(args, onAccepted) {
|
|
585
600
|
const resumeLegStartedAt = Date.now();
|
|
586
|
-
const { runner: legRunner, token, sessionId, principal, fleetScope, taskConfig, resumeObjective, outcome, verifyRounds, resumeCtx } = args;
|
|
601
|
+
const { runner: legRunner, token, sessionId, principal, fleetScope, taskConfig, resumeObjective, outcome, verifyRounds, resumeCtx, execution } = args;
|
|
587
602
|
const reparkStatus = outcome.gate === "plan_review" ? "needs_review" : "suspended";
|
|
588
603
|
const commitResumeCtx = () => Promise.resolve().then(() => deps.checkpointStore.putCtx(resumeCtx.sessionId, sealCheckpointCtx({ ...resumeCtx.ctx, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, resumeCtx.sessionId))).catch((e) => {
|
|
589
604
|
deps.metrics?.inc("resume_ctx_not_persisted_total");
|
|
@@ -627,12 +642,14 @@ export function createResumeLegs(ctx) {
|
|
|
627
642
|
if (created.existing) {
|
|
628
643
|
throw new Error(`wake fresh run: createRun observed an existing row for the freshly minted taskId ${freshId} (no idempotency key was sent) — refusing to treat it as a busy session`);
|
|
629
644
|
}
|
|
645
|
+
if (created.sessionAbsent)
|
|
646
|
+
return rootSessionAbsentAnswer();
|
|
630
647
|
if (!created.ok) {
|
|
631
648
|
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, sessionId, created.activeTaskId) };
|
|
632
649
|
}
|
|
633
|
-
const placementReject = await
|
|
650
|
+
const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: freshId }, execution);
|
|
634
651
|
if (placementReject)
|
|
635
|
-
return
|
|
652
|
+
return placementReject;
|
|
636
653
|
taskId = freshId;
|
|
637
654
|
freshRunClaimed = true;
|
|
638
655
|
}
|
|
@@ -643,11 +660,12 @@ export function createResumeLegs(ctx) {
|
|
|
643
660
|
if (deps.toolApproval && taskId) {
|
|
644
661
|
const toolApproval = deps.toolApproval;
|
|
645
662
|
resumeTaskConfig.onAsk = approvalLeg.unattended
|
|
646
|
-
? toolApproval.boundUnattendedAsk({ owner: principal ?? null, taskId, sessionId }, approvalLeg.unattended)
|
|
663
|
+
? toolApproval.boundUnattendedAsk({ owner: principal ?? null, taskId, sessionId, executionLane: execution.lane }, approvalLeg.unattended)
|
|
647
664
|
: toolApproval.boundAsk({
|
|
648
665
|
owner: principal ?? null,
|
|
649
666
|
taskId,
|
|
650
667
|
sessionId,
|
|
668
|
+
executionLane: execution.lane,
|
|
651
669
|
...(approvalLeg.active ? { legKey, ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
|
|
652
670
|
});
|
|
653
671
|
}
|
|
@@ -713,6 +731,11 @@ export function createResumeLegs(ctx) {
|
|
|
713
731
|
claimedRow = freshRunClaimed ? true : await deps.runStore.markResuming(taskId, deps.instanceId ?? "default");
|
|
714
732
|
if (!claimedRow)
|
|
715
733
|
return notResumableAnswer();
|
|
734
|
+
if (!freshRunClaimed) {
|
|
735
|
+
const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId }, execution);
|
|
736
|
+
if (placementReject)
|
|
737
|
+
return placementReject;
|
|
738
|
+
}
|
|
716
739
|
markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, principal);
|
|
717
740
|
fleetPub?.onStart();
|
|
718
741
|
const rs = deps.runStore;
|
|
@@ -827,12 +850,14 @@ export function createResumeLegs(ctx) {
|
|
|
827
850
|
resumeLegLive = true;
|
|
828
851
|
const vrEngine = await resumeWithVerification(legRunner, token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, resumeObjective, verifyRounds, verifyInternals);
|
|
829
852
|
const vrCause = cancelCtrl.cause();
|
|
830
|
-
const
|
|
853
|
+
const vrJudged = atHostBoundary(vrEngine, sessionId);
|
|
854
|
+
const vr = vrCause !== undefined && taskId !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: vrJudged, cause: vrCause }) : vrJudged;
|
|
831
855
|
await commitResumeCtx();
|
|
832
856
|
let safe = sealResultForExit(vr);
|
|
833
|
-
const
|
|
834
|
-
const
|
|
835
|
-
const
|
|
857
|
+
const vrPaused = vr.terminal.kind === "paused" ? vr.terminal : undefined;
|
|
858
|
+
const vrParkWord = vrPaused !== undefined ? outwardPlane(vrPaused).status : undefined;
|
|
859
|
+
const reParkEvent = vrParkWord !== undefined && isParkLedgerEventType(vrParkWord) ? vrParkWord : undefined;
|
|
860
|
+
const reSuspended = reParkEvent !== undefined;
|
|
836
861
|
const vrReopened = await reopenedAfterLeg(vr, vrCause !== undefined);
|
|
837
862
|
if (vrReopened)
|
|
838
863
|
reopenConfirmedPark = true;
|
|
@@ -843,8 +868,8 @@ export function createResumeLegs(ctx) {
|
|
|
843
868
|
await appendPromptManifest(ap, deps.promptManifests, taskId);
|
|
844
869
|
if (reSuspended || vrReopened) {
|
|
845
870
|
await appendModelUsageDelta(ap, deps.modelUsage, taskId);
|
|
846
|
-
const vrParkCallId =
|
|
847
|
-
await ap(
|
|
871
|
+
const vrParkCallId = reSuspended ? await parkToolCallId(vr, deps.checkpointStore) : undefined;
|
|
872
|
+
await ap(reParkEvent ?? reparkStatus, parkEventData({ terminal: vrPaused, ...(vrParkCallId !== undefined ? { toolCallId: vrParkCallId } : {}) }, vrReopened ? (failureCodeOf(vr.terminal) ?? null) : undefined));
|
|
848
873
|
}
|
|
849
874
|
else {
|
|
850
875
|
safe = await attachModelUsage(safe, { append: ap, getEvents: (id, a) => rs2.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
|
|
@@ -856,8 +881,8 @@ export function createResumeLegs(ctx) {
|
|
|
856
881
|
throw e;
|
|
857
882
|
}
|
|
858
883
|
}
|
|
859
|
-
if (
|
|
860
|
-
return
|
|
884
|
+
if (reSuspended)
|
|
885
|
+
return safe;
|
|
861
886
|
if (vr.verification?.verdict)
|
|
862
887
|
deps.metrics?.inc("verifications_total", { verdict: vr.verification.verdict });
|
|
863
888
|
return safe;
|
|
@@ -1140,6 +1165,7 @@ export function createResumeLegs(ctx) {
|
|
|
1140
1165
|
owner: principal ?? null,
|
|
1141
1166
|
abortSignal: cancelCtrl.signal,
|
|
1142
1167
|
sessionId,
|
|
1168
|
+
executionLane: execution.lane,
|
|
1143
1169
|
emitCard: createApprovalCardEmitter({ appendDurable: (f) => approvalEmit(f) }),
|
|
1144
1170
|
emitRevoke: (f) => approvalEmit(f),
|
|
1145
1171
|
legKey,
|
|
@@ -1328,7 +1354,7 @@ export function createResumeLegs(ctx) {
|
|
|
1328
1354
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
1329
1355
|
const verifyRounds = verifyRoundsFromBody(ctx.body);
|
|
1330
1356
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1331
|
-
return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, runner: runnerFor(spec), 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 } : {}) });
|
|
1357
|
+
return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: runnerFor(spec), 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 } : {}) });
|
|
1332
1358
|
}
|
|
1333
1359
|
finally {
|
|
1334
1360
|
resolved.peerLease.release();
|
|
@@ -1367,9 +1393,9 @@ export function createResumeLegs(ctx) {
|
|
|
1367
1393
|
return resolved.answer;
|
|
1368
1394
|
try {
|
|
1369
1395
|
const { spec, engineNotices } = resolved;
|
|
1370
|
-
const hostSpec = { ...spec, objective
|
|
1396
|
+
const hostSpec = { ...spec, objective };
|
|
1371
1397
|
const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
|
|
1372
|
-
prepared: { spec: hostSpec, runner: runnerFor(hostSpec), auth, body: ctx.body, acceptance: createRunAcceptance({}, { objective }), peerLease: resolved.peerLease, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1398
|
+
prepared: { spec: hostSpec, runner: runnerFor(hostSpec), auth, body: ctx.body, acceptance: createRunAcceptance({}, { objective }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1373
1399
|
fleetScope: resumeFleetScope(req, auth),
|
|
1374
1400
|
elicitOwner: principal ?? null,
|
|
1375
1401
|
source: "workflow_parked_decide",
|
|
@@ -1455,6 +1481,7 @@ export function createResumeLegs(ctx) {
|
|
|
1455
1481
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
1456
1482
|
return await driveResumeIntoRunLog({
|
|
1457
1483
|
peerLease: resolved.peerLease,
|
|
1484
|
+
execution: resolved.execution,
|
|
1458
1485
|
runner: runnerFor(spec),
|
|
1459
1486
|
token,
|
|
1460
1487
|
sessionId: cp.sessionId,
|
|
@@ -1581,7 +1608,7 @@ export function createResumeLegs(ctx) {
|
|
|
1581
1608
|
hostDecision,
|
|
1582
1609
|
};
|
|
1583
1610
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1584
|
-
const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, runner: runnerFor(spec), 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 } : {}) });
|
|
1611
|
+
const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: runnerFor(spec), 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 } : {}) });
|
|
1585
1612
|
return out;
|
|
1586
1613
|
}
|
|
1587
1614
|
finally {
|
|
@@ -22,7 +22,7 @@ export interface RetiredServiceDep {
|
|
|
22
22
|
export declare const RETIRED_SERVICE_DEPS: {
|
|
23
23
|
readonly sqlEngineFacts: {
|
|
24
24
|
readonly retiredIn: "7.132.0";
|
|
25
|
-
readonly wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"
|
|
25
|
+
readonly wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"mysql\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store";
|
|
26
26
|
};
|
|
27
27
|
readonly snapshotBlobSqlCapBytes: {
|
|
28
28
|
readonly retiredIn: "7.132.0";
|
|
@@ -2,7 +2,7 @@ const BLOB_CAP_WAY_OUT = "the HTTP surface no longer holds a blob cap of its own
|
|
|
2
2
|
export const RETIRED_SERVICE_DEPS = {
|
|
3
3
|
sqlEngineFacts: {
|
|
4
4
|
retiredIn: "7.132.0",
|
|
5
|
-
wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"
|
|
5
|
+
wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"mysql\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store",
|
|
6
6
|
},
|
|
7
7
|
snapshotBlobSqlCapBytes: { retiredIn: "7.132.0", wayOut: BLOB_CAP_WAY_OUT },
|
|
8
8
|
snapshotBlobSqlCap: { retiredIn: "7.133.0", wayOut: BLOB_CAP_WAY_OUT },
|
package/dist/http/route-ctx.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ import type { VerifyRoundsSpec } from "./verify-rounds.js";
|
|
|
32
32
|
import type { RunAbort } from "../run-cancel-context.js";
|
|
33
33
|
import type { RunIdentity } from "../identity-source.js";
|
|
34
34
|
import type { PeerLease } from "../peer-seat.js";
|
|
35
|
+
import type { RootedTaskSpec } from "./execution-context.js";
|
|
35
36
|
import type { GateCommitment, GateSettlementEvidence } from "../gate-settlement.js";
|
|
36
37
|
/** 跨域可变状态 = lens1 §C2 实测的那 8 条「运行期登记簿」,一个对象。
|
|
37
38
|
* [ref]:`cancelledViaVerb`(按 taskId 键控的「这次是取消动词」旁表)删除 —— 中止成因改挂在每条腿自己的
|
|
@@ -117,11 +118,13 @@ export interface RouteRequestState {
|
|
|
117
118
|
/** B4①(命名化):`prepareSpec` 的返回形(tasks.ts/runs.ts 两域共同消费的属性面)——原为 6 成员内联匿名对象。
|
|
118
119
|
* 命名后好处不只是过 B4 门:两个消费域现在都能对同一个符号做 `import type` 标注,而不是各自重推断结构。 */
|
|
119
120
|
export interface PreparedTaskSubmission {
|
|
120
|
-
spec
|
|
121
|
+
/** 盖过根的 spec(`http/execution-context.ts` `stampSpecRoot` 是唯一写者):`sessionId` 恒在 = 这次提交的根会话。 */
|
|
122
|
+
spec: RootedTaskSpec;
|
|
121
123
|
/** [ref]:本次提交的执行 Runner —— 场景 hands=none 时是无手孪生(不挂 executionEnvFactory)。
|
|
122
124
|
* 两个消费域一律用它,不再直接摸 `deps.runner`(那正是「场景表态了、执行点没听」的缝)。 */
|
|
123
125
|
runner: Runner;
|
|
124
|
-
|
|
126
|
+
/** authorizer 交出的身份与根(必填席,恒在;续跑家族的内部车道交它从 checkpoint 重建的那一只)。 */
|
|
127
|
+
auth: RequestAuth;
|
|
125
128
|
verify?: VerifyRoundsSpec;
|
|
126
129
|
cascade?: boolean;
|
|
127
130
|
jobId?: string;
|
|
@@ -137,13 +140,11 @@ export interface PreparedTaskSubmission {
|
|
|
137
140
|
*/
|
|
138
141
|
warnings?: readonly EntryProblem[];
|
|
139
142
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* ②本腿不是 fresh 根提交(resume 家族根本不经 `prepareSpec`)。在场 ⇒ 每个 `runStore.createRun(`
|
|
144
|
-
* 成功点**必须**把它交给 `commitPlacement`(唯一写入属主;类级机器门钉住每个调用点都接了)。
|
|
143
|
+
* 这次执行的**执行上下文**(唯一解析器 `http/execution-context.ts` `resolveExecutionContext` 的产物:根 · 住客 · 放置态 · 车道 · device 车道的设备意图)。
|
|
144
|
+
* 提交门在装配之前铸(fresh);`/decide` 的宿主新 turn 交续跑折叠器铸的那一只(continuation)。每个 `runStore.createRun(` 成功点**必须**把它交给
|
|
145
|
+
* 认领之后的唯一写口 `commitExecutionContext`(类级机器门钉住每个调用点都接了)。
|
|
145
146
|
*/
|
|
146
|
-
|
|
147
|
+
execution: import("./execution-context.js").RootedExecutionContext;
|
|
147
148
|
/**
|
|
148
149
|
* 这次提交的**受理座**(`run-acceptance.ts`):标题器只在引擎受理之后起。提交门(`prepareSpec`)随 spec 一起铸;
|
|
149
150
|
* 三条提交腿只喂它(持流的形逐帧 `observe`,终局落行之后 `settle` 一次),不再各自判「什么时候起标题」。
|
|
@@ -226,6 +227,11 @@ export interface WorkflowDecisionDelivery {
|
|
|
226
227
|
/** B4①(命名化):`driveResumeIntoRunLog` 的入参形(resume 家族共用)——原为 9 成员内联匿名对象。 */
|
|
227
228
|
export interface DriveResumeArgs {
|
|
228
229
|
token: CheckpointToken;
|
|
230
|
+
/**
|
|
231
|
+
* 这条续跑的执行上下文(续跑折叠器经唯一解析器铸的 continuation 形:根 = checkpoint 的会话)。本腿认领之后(wake 的建行 / `markResuming` CAS 赢)
|
|
232
|
+
* 交给唯一写口 `commitExecutionContext`(按解析器那一读的住客再断言 writer(L) / absent 落格;住客换了 ⇒ 释放 + 404)。
|
|
233
|
+
*/
|
|
234
|
+
execution: import("./execution-context.js").RootedExecutionContext;
|
|
229
235
|
/**
|
|
230
236
|
* 🔴 **[ref] 合并复审 F2 [high] —— 「本次续跑真正用的那个体」,由本腿在赢下 CAS 之后写回耐久层**
|
|
231
237
|
* (验真后修;必填 —— `driveResumeIntoRunLog` 今天恰有**四个**调用点:legacy `/decide`(`resumeCheckpoint`)、
|
|
@@ -69,7 +69,7 @@ export async function handleAdoption(req, res, match, ctx) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
const store = fact.backend.adoptionLog();
|
|
72
|
-
const runner = createAdoptionRunner({ store, dialect: deps.backend?.kind === "pg" ? "pg" : "
|
|
72
|
+
const runner = createAdoptionRunner({ store, dialect: deps.backend?.kind === "pg" ? "pg" : "mysql", now: Date.now, logger: deps.logger });
|
|
73
73
|
switch (match.decl.id) {
|
|
74
74
|
case "adoption-detail": {
|
|
75
75
|
const id = ctx.helpers.safeDecode(match.params.id);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* [ref](core 7.32.0 [ref] 的 server 半场;wire 形 [ref] / [ref] / [ref] 定)—— **会话后台任务的两只读口**:
|
|
3
3
|
*
|
|
4
|
-
* `GET /v1/sessions/:id/background` → 200 `{ rows: [{ id, description?, type, status, createdAt, sessionScoped, retained? }] }`
|
|
4
|
+
* `GET /v1/sessions/:id/background` → 200 `{ rows: [{ id, description?, type, status, createdAt, sessionScoped, retained?, sessionId? }] }`
|
|
5
5
|
* `POST /v1/sessions/:id/background/stop` body `{ includeRetained: boolean }` → 200 `{ receipts: [{ id, outcome }] }`
|
|
6
6
|
*
|
|
7
7
|
* 消费方:cli [ref] ①(删前核登记)/ [ref](退出三选一:「Exit and stop tasks」= `includeRetained:true`,`sema kill` =
|
|
@@ -28,6 +28,16 @@
|
|
|
28
28
|
* oracle);显式 operator 可读可停任何会话(监督动作)。零模型工作 ⇒ 不进 billable、不吃 drain 503;停止口是 mutating ⇒
|
|
29
29
|
* `rateLimited`。能力位 `background: { listFace, exitFaces }` 与两口的 501 从同一个谓词推导(会话属主面在场)。
|
|
30
30
|
*
|
|
31
|
+
* ── 结清口:子代结清只有一只协调器 ─────────────────────────────────────────────────────────────────
|
|
32
|
+
* `POST /v1/sessions/:id/children/retire`(无体)→ 200 `{ children: string[] }`:**显式**结清以本会话为根的后台子代(running 停掉、parked
|
|
33
|
+
* 作废卡并对账翻终态),与 `DELETE /v1/sessions/:id` 同调**一只**预检 `probeSessionChildren` 与**一只**协调器 `retireSessionChildren`
|
|
34
|
+
* (`session-children-retire.ts`)、同一个 scope(`sessionChildrenScope`)。预检有本副本结束不了的 ⇒ 409 `conflict.session_children_alive{remaining}`
|
|
35
|
+
* (与删除门同码同投影,一只都不动);停不净(时序失败)⇒ 与删除门同一失败契约(通用 500,重试收敛)。`children` = 首轮观察到、且已全部
|
|
36
|
+
* 结清的子代,每项经名册的 id 投影 `rosterAgentId`(与换绑 / 导入两门 409 体的 `children` 同形同投影)。它不判根认领(停止口也不判):
|
|
37
|
+
* 根 run 活着时它可再派子代 —— 由换绑 / 导入门写事务内的认领读兜。鉴权 / 限流 / 无凭据写门与停止口同。
|
|
38
|
+
* **停止口的已发语义逐字不动**:它只中止 running 的后台 agent / workflow 并收 shell,停驻子代与待决卡留着 —— 「停别的、留卡待决」与
|
|
39
|
+
* 「把树结清」是两个意图、两只口。
|
|
40
|
+
*
|
|
31
41
|
* 🔴 **停止口在无凭据写门内**(`credentialGated: ["POST"]`;车OL F1 = 7.102.0 合并复审 gpt-6 腿 [high]):门的两个合取项它都中
|
|
32
42
|
* —— ① 授权的唯一输入是 principal 头(属主判 `sessionOwnerOk` 与 operator 臂 `explicitOperatorOk` 读的都是 `gatedPrincipal`,
|
|
33
43
|
* 无 service 凭证的部署上它收调用方自报的头);② 不可撤销、爆炸半径跨租户(知道会话 id + 自报它的属主 ⇒ 停掉那个会话的后台
|
|
@@ -53,12 +63,24 @@ export interface SessionBackgroundRow {
|
|
|
53
63
|
createdAt: number;
|
|
54
64
|
sessionScoped: boolean;
|
|
55
65
|
retained?: true;
|
|
66
|
+
/** 后台 agent 行的子会话 id(引擎绑定之后才有;缺席 ⇒ 键不在)。 */
|
|
67
|
+
sessionId?: string;
|
|
56
68
|
}
|
|
57
69
|
/** 停止口的一条受据(`outcome` 逐字透传 core 闭集)。 */
|
|
58
70
|
export interface SessionBackgroundReceipt {
|
|
59
71
|
id: string;
|
|
60
72
|
outcome: BackgroundShellHardKillReceipt["outcome"];
|
|
61
73
|
}
|
|
74
|
+
/** 结清口的路径(换绑 / 导入两门的子代半 409 以它点名下一步;与执行面拒体带 `forkPath` 同一形)。 */
|
|
75
|
+
export declare function childrenRetirePath(sessionId: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* 子代半命中的拒体两键(换绑 409 `device.rebind_active_run`、导入 409 `session_active` 同一只):`children` = 预检那一次枚举观察到的活子代
|
|
78
|
+
* (`probeSessionChildren` 的 `liveChildren`)经名册 id 投影,`retirePath` = 结清口。
|
|
79
|
+
*/
|
|
80
|
+
export declare function liveChildrenRefusal(sessionId: string, liveChildren: readonly string[]): {
|
|
81
|
+
children: string[];
|
|
82
|
+
retirePath: string;
|
|
83
|
+
};
|
|
62
84
|
export declare function handleBackground(req: IncomingMessage, res: ServerResponse, match: RouteMatch<BackgroundRouteId>, ctx: RouteCtx): Promise<void>;
|
|
63
85
|
export declare const BACKGROUND_ROUTES: readonly [{
|
|
64
86
|
readonly id: "session-background-list";
|
|
@@ -71,6 +93,12 @@ export declare const BACKGROUND_ROUTES: readonly [{
|
|
|
71
93
|
readonly label: "/v1/sessions/:id/background/stop";
|
|
72
94
|
readonly credentialGated: readonly ["POST"];
|
|
73
95
|
readonly methods: readonly ["POST"];
|
|
96
|
+
}, {
|
|
97
|
+
readonly id: "session-children-retire";
|
|
98
|
+
readonly pattern: RegExp;
|
|
99
|
+
readonly label: "/v1/sessions/:id/children/retire";
|
|
100
|
+
readonly credentialGated: readonly ["POST"];
|
|
101
|
+
readonly methods: readonly ["POST"];
|
|
74
102
|
}];
|
|
75
103
|
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
76
104
|
export type BackgroundRouteId = RouteIdsOf<typeof BACKGROUND_ROUTES>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defaultTaskRegistry } from "@sema-agent/core";
|
|
3
3
|
import { reapSessionBackgroundHard } from "../../background-session-reap.js";
|
|
4
|
+
import { probeSessionChildren, retireSessionChildren, sessionChildrenScope, SessionChildrenStopIncompleteError } from "../../session-children-retire.js";
|
|
5
|
+
import { rosterAgentId } from "./agents-roster.js";
|
|
4
6
|
import { redactSecrets } from "../../trace/redact.js";
|
|
5
7
|
import { sendJson, sendError } from "../send.js";
|
|
6
8
|
import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal } from "../principal-gate.js";
|
|
@@ -20,6 +22,7 @@ const ROW_KEY_DISPOSITION = {
|
|
|
20
22
|
description: "keep",
|
|
21
23
|
toolUseId: "strip",
|
|
22
24
|
updatedAt: "strip",
|
|
25
|
+
sessionId: "keep",
|
|
23
26
|
};
|
|
24
27
|
void ROW_KEY_DISPOSITION;
|
|
25
28
|
function projectRow(r) {
|
|
@@ -31,13 +34,20 @@ function projectRow(r) {
|
|
|
31
34
|
createdAt: r.createdAt,
|
|
32
35
|
sessionScoped: r.sessionScoped,
|
|
33
36
|
...(r.retained === true ? { retained: true } : {}),
|
|
37
|
+
...(r.sessionId !== undefined ? { sessionId: r.sessionId } : {}),
|
|
34
38
|
};
|
|
35
39
|
}
|
|
40
|
+
export function childrenRetirePath(sessionId) {
|
|
41
|
+
return `/v1/sessions/${encodeURIComponent(sessionId)}/children/retire`;
|
|
42
|
+
}
|
|
43
|
+
export function liveChildrenRefusal(sessionId, liveChildren) {
|
|
44
|
+
return { children: liveChildren.map((handle) => rosterAgentId({ handle })), retirePath: childrenRetirePath(sessionId) };
|
|
45
|
+
}
|
|
36
46
|
const StopBodySchema = z.object({ includeRetained: z.boolean() }).strict();
|
|
37
47
|
export async function handleBackground(req, res, match, ctx) {
|
|
38
48
|
const { deps } = ctx;
|
|
39
49
|
const id = match.decl.id;
|
|
40
|
-
if (id === "session-background-stop" && ctx.helpers.rateLimited(req, res))
|
|
50
|
+
if ((id === "session-background-stop" || id === "session-children-retire") && ctx.helpers.rateLimited(req, res))
|
|
41
51
|
return;
|
|
42
52
|
const principal = gatedPrincipal(req, deps.config);
|
|
43
53
|
if (deps.config.requirePrincipal && principal === undefined) {
|
|
@@ -71,7 +81,7 @@ export async function handleBackground(req, res, match, ctx) {
|
|
|
71
81
|
const operator = explicitOperatorOk(principal, deps.config);
|
|
72
82
|
if (!operator && !ctx.helpers.sessionOwnerOk(req, res, await sessionOwnerCellOf(owned.sessionStorage, sessionId, owner)))
|
|
73
83
|
return;
|
|
74
|
-
const scope = owner
|
|
84
|
+
const scope = sessionChildrenScope(owner);
|
|
75
85
|
switch (id) {
|
|
76
86
|
case "session-background-list": {
|
|
77
87
|
const rows = defaultTaskRegistry.list({ owner: sessionId, sessionId, scope }, { limit: LIST_LIMIT }).map(projectRow);
|
|
@@ -83,6 +93,22 @@ export async function handleBackground(req, res, match, ctx) {
|
|
|
83
93
|
sendJson(res, 200, { receipts: receipts.map((r) => ({ id: r.taskId, outcome: r.outcome })) });
|
|
84
94
|
return;
|
|
85
95
|
}
|
|
96
|
+
case "session-children-retire": {
|
|
97
|
+
const sources = { agentStore: deps.backgroundAgentStore, checkpointStore: deps.checkpointStore, registry: defaultTaskRegistry };
|
|
98
|
+
const reach = await probeSessionChildren(sources, sessionId, scope);
|
|
99
|
+
if (!reach.reachable) {
|
|
100
|
+
deps.logger?.warn("session_children_retire_unreachable", { sessionId, remaining: reach.unreachableHandles.length, handles: reach.unreachableHandles });
|
|
101
|
+
sendError(res, 409, "conflict.session_children_alive", "this session still has background agents running where this replica cannot stop them (on another replica, for example), so nothing was retired — `remaining` lists their ids (the same ids `GET /v1/agents/roster` shows); retry once they finish, or stop them where they run", { remaining: reach.unreachableHandles.map((handle) => rosterAgentId({ handle })) });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const out = await retireSessionChildren(sources, sessionId, scope);
|
|
105
|
+
if (out.stopped === "incomplete") {
|
|
106
|
+
deps.logger?.warn("session_children_retire_incomplete", { sessionId, remaining: out.remainingHandles.length, handles: out.remainingHandles });
|
|
107
|
+
throw new SessionChildrenStopIncompleteError(sessionId, out.remainingHandles.length);
|
|
108
|
+
}
|
|
109
|
+
sendJson(res, 200, { children: out.observed.map((handle) => rosterAgentId({ handle })) });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
86
112
|
default:
|
|
87
113
|
return assertNever(id);
|
|
88
114
|
}
|
|
@@ -90,5 +116,6 @@ export async function handleBackground(req, res, match, ctx) {
|
|
|
90
116
|
export const BACKGROUND_ROUTES = [
|
|
91
117
|
{ id: "session-background-list", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/background$/, label: "/v1/sessions/:id/background", methods: ["GET"] },
|
|
92
118
|
{ id: "session-background-stop", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/background\/stop$/, label: "/v1/sessions/:id/background/stop", credentialGated: ["POST"], methods: ["POST"] },
|
|
119
|
+
{ id: "session-children-retire", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/children\/retire$/, label: "/v1/sessions/:id/children/retire", credentialGated: ["POST"], methods: ["POST"] },
|
|
93
120
|
];
|
|
94
121
|
//# sourceMappingURL=background.js.map
|
|
@@ -8,19 +8,19 @@
|
|
|
8
8
|
* **hub 在场性**判 —— v1 部署形 = 单副本(基线稿 §4.6),汇聚端的活连接集就是本副本的 presence
|
|
9
9
|
* 真源;`name` = displayName,空串诚实缺席;`lastSeenAt` ISO-8601)。**吊销行不列**:revoked 是
|
|
10
10
|
* 终态(重注册 = 新 deviceId),列出来只会被壳当换绑目标然后撞 404。
|
|
11
|
-
* ·
|
|
12
|
-
* `{
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* 装配缝加一次店读;独立读面把 device wire 族收在一个文件里,户口与门序自洽。
|
|
16
|
-
* · `POST /v1/devices/sessions/:rootSessionId/rebind` —— 显式换绑动词(v2 稿 §2 门序五步,逐字):
|
|
17
|
-
* ① gatedPrincipal + owner 门(非属主 404 反枚举同串,[ref] 纪律)
|
|
11
|
+
* · 绑定读面在会话族:`GET /v1/sessions/:id/execution-placement`(`routes/sessions.ts`;体 = 执行放置格的 wire 投影,
|
|
12
|
+
* device 车道上是 `{ role: "writer", lane: "device", device: { deviceId, rev } }`)。绑定是根会话行上的执行格,读只有会话店的执行席一只。
|
|
13
|
+
* · `POST /v1/devices/sessions/:rootSessionId/rebind` —— 显式换绑动词(v2 稿 §2 门序五步):
|
|
14
|
+
* ① gatedPrincipal + owner 门 —— 一次行读(会话店执行席:住客 + 格),属主门判**格上**两属主列(非属主 404 反枚举同串,[ref] 纪律)
|
|
18
15
|
* ② 目标设备在场门(不存在 / 不是该域的 / 已吊销 ⇒ 404 **同串** —— 设备 id 也是不可枚举面)
|
|
19
|
-
* ③ 无活跃 run
|
|
20
|
-
* `
|
|
21
|
-
* `device.rebind_active_run` 体带 `activeTaskId`
|
|
22
|
-
*
|
|
23
|
-
* `
|
|
16
|
+
* ③ 无活跃 run 门:池级 `getActiveTaskId` 读一次作**早拒**(零审计行);**保证**在设备店的换绑事务里 —— 同一连接先锁根会话行、
|
|
17
|
+
* 再锁定读 `task_active`,有认领 ⇒ 不写(读写序律;hub 内存在途计数不作门 —— 内存态跨副本不可见);两处同拒 409
|
|
18
|
+
* `device.rebind_active_run` 体带 `activeTaskId`
|
|
19
|
+
* ③′ 子代半(写前一次观察):以根为根的活后台子代(running / parked;`probeSessionChildren` 那一次枚举,scope = 会话属主 `sessionChildrenScope`,
|
|
20
|
+
* 与删除门同读)⇒ 同码 409,体 `children`(名册 id)+ `retirePath`(显式结清口 —— 先结清、再换绑)
|
|
21
|
+
* ④ 前态 CAS(店内单事务:按门那一读的住客 ∧ 格上两属主列 ∧ rev 定址,`execution_rev` 恒变列 + `session_rebound` 审计行;输 = 409
|
|
22
|
+
* `device.rebind_rev_conflict` 体带 `currentRev` —— [ref] currentPending 哲学,壳一跳重定位;门后会话被删并同 id 重登记 ⇒ 住客不符 ⇒ 设备 404,
|
|
23
|
+
* 永不写到新住客的格上)
|
|
24
24
|
* ⑤ 赢 = 200 `{ rootSessionId, deviceId, rev, workspaceCarryover: "none" }`。
|
|
25
25
|
* 幂等形:toDeviceId ≡ 当前 ∧ expectedRev ≡ 当前 rev ⇒ 200 回显不加 rev(真幂等,不写审计)。
|
|
26
26
|
* `workspaceCarryover: "none"` 是 **wire 冻结字面**(v2 稿 §5):换绑只改路由,不搬字节 —— 壳据
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* 才构成一个 device 域;缺 tenant claim 的凭据(纯 principal 头 / 静态 token 直连)**判不出域** ⇒
|
|
35
35
|
* 非 operator 一律响亮 403(fail-closed + loud,[ref]:静默空列表是假健康)——基线稿对 enrollment 的
|
|
36
36
|
* 同向裁定是「缺 tenant/global scope 明确拒注册」。enrollment/管理端点与**首绑写协议**都从
|
|
37
|
-
* 这同一个函数取域(
|
|
37
|
+
* 这同一个函数取域(它住在 `http/execution-context.ts` —— 提交腿的设备准入也要用,放在路由域里是层序倒挂),
|
|
38
38
|
* 不得手抄第二份派生。
|
|
39
39
|
*
|
|
40
40
|
* ── 反枚举 404 的单一铸造点 ──────────────────────────────────────────────────────────────────────
|
|
@@ -81,12 +81,6 @@ export declare const DEVICES_ROUTES: readonly [{
|
|
|
81
81
|
readonly pattern: RegExp;
|
|
82
82
|
readonly label: "/v1/devices/sessions/:id/rebind";
|
|
83
83
|
readonly methods: readonly ["POST"];
|
|
84
|
-
}, {
|
|
85
|
-
readonly id: "device-session";
|
|
86
|
-
readonly pattern: RegExp;
|
|
87
|
-
readonly label: "/v1/devices/sessions/:id";
|
|
88
|
-
readonly credentialGated: readonly ["GET"];
|
|
89
|
-
readonly methods: readonly ["GET"];
|
|
90
84
|
}, {
|
|
91
85
|
readonly prefix: "/v1/devices/";
|
|
92
86
|
readonly credentialGated: readonly ["POST"];
|