@sema-agent/server 7.148.0 → 7.150.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 +551 -9
- package/README.md +17 -2
- package/README.zh-CN.md +5 -1
- package/USAGE.md +126 -68
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +33 -33
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +66 -28
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +4 -4
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +35 -2
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +70 -60
- package/dist/capability-facts.js +45 -49
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +37 -33
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +49 -16
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +5 -5
- package/dist/http/approval-sweeps.js +5 -3
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +6 -6
- package/dist/http/claim-heartbeat.js +6 -6
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +7 -5
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +34 -15
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +246 -21
- package/dist/http/owner-access.js +186 -8
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +24 -3
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +262 -106
- package/dist/http/route-ctx.d.ts +29 -11
- package/dist/http/routes/a2a-serve.js +17 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +11 -11
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +33 -37
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +45 -37
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +136 -101
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +12 -9
- package/dist/http/server.js +35 -6
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +2 -2
- package/dist/http/submit-ctx.js +5 -5
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +13 -2
- package/dist/leg-facts.js +2 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +30 -5
- package/dist/owner-faces.js +2 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +51 -23
- package/dist/plugins/local-checkpoint-store.d.ts +8 -1
- package/dist/plugins/local-checkpoint-store.js +5 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +48 -22
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +110 -59
- package/dist/plugins/one-time-migrations.js +224 -136
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +14 -12
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +4 -8
- package/dist/plugins/remote-env-e2b.js +21 -15
- package/dist/plugins/remote-env-host.d.ts +51 -10
- package/dist/plugins/remote-env-host.js +97 -31
- package/dist/plugins/remote-env-k8s.js +7 -4
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +11 -25
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +27 -8
- package/dist/plugins/run-store-sql.js +46 -18
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
- package/dist/plugins/schema-consistency.d.ts +91 -5
- package/dist/plugins/schema-consistency.js +189 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
- package/dist/plugins/stop-then-start-sentence.js +51 -0
- package/dist/plugins/store-backend.d.ts +23 -9
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +45 -5
- package/dist/plugins/store-contracts.js +19 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +22 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +20 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +3 -3
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +4 -12
- package/dist/session-agent.js +0 -6
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
- package/dist/stores-sql/checkpoint-store-sql.js +109 -23
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +27 -10
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +14 -7
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +50 -41
- package/dist/tool-approval.js +96 -73
- package/dist/trace/engine-notice-wire.d.ts +38 -21
- package/dist/trace/engine-notice-wire.js +25 -4
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +8 -5
- package/dist/trace/project.js +11 -9
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +268 -56
- package/dist/trace/self-minted-wire.js +110 -40
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +4 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/wire-changes/server@7.150.0.json +335 -0
- package/dist/plain-string-record.js +0 -70
|
@@ -5,24 +5,38 @@ import { recheckClaimBeforeLaunch, refusalAfterLostClaim, startClaimHeartbeat }
|
|
|
5
5
|
import { heldFor } from "../peer-seat.js";
|
|
6
6
|
import { fleetRunPublisher, fleetRunLabels, nameFleetRowOnDelivery } from "../fleet/fleet-bus.js";
|
|
7
7
|
import { cascadeConfig, fillRunPreviewOnDelivery, runMeta } from "./run-meta.js";
|
|
8
|
+
import { approvalLegOriginOf } from "../approval-leg-origin.js";
|
|
8
9
|
import { declaredApprovalFrameFamilies, resolveStreamApprovalGate } from "../tool-approval.js";
|
|
9
10
|
import { buildActiveRunConflict } from "./active-run-conflict.js";
|
|
10
|
-
import { commitExecutionContext } from "./execution-context.js";
|
|
11
|
+
import { commitExecutionContext, faultedAnswerOf } from "./execution-context.js";
|
|
11
12
|
import { rootSessionAbsentAnswer } from "./execution-context.js";
|
|
12
13
|
import { timeClaim } from "./claim-latency.js";
|
|
13
14
|
import { commitSessionInheritEnv } from "./session-inherit-env.js";
|
|
14
15
|
import { clearTurnActivity, readTurnActivityMs } from "../turn-activity.js";
|
|
15
16
|
import { recordResourceWindow } from "../resource-window.js";
|
|
16
17
|
import { persistSubmissionCtx, SUBMIT_CTX_CLAIM_LOST } from "./submit-ctx.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { withdrawClaimedRun } from "./claimed-run.js";
|
|
19
|
+
import { sessionFactsReadOf } from "./owner-access.js";
|
|
19
20
|
import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
|
|
20
21
|
export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
21
22
|
const { deps } = ctx;
|
|
22
|
-
const { inflightRuns, preemptableRuns, steerableRuns } = ctx.registry;
|
|
23
23
|
const sessionId = args.prepared.spec.sessionId;
|
|
24
24
|
const taskId = args.clientTaskId ?? uuidv7();
|
|
25
25
|
const trustedInternals = await heldWorkflowParkDecisions(deps, sessionId, args.workflowDecision?.carried);
|
|
26
|
+
let legId;
|
|
27
|
+
try {
|
|
28
|
+
const claimed = await claimAndCommit(ctx, runStore, args, sessionId, taskId);
|
|
29
|
+
if (!("holdingLeg" in claimed))
|
|
30
|
+
return claimed;
|
|
31
|
+
legId = claimed.holdingLeg;
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
return faultedAnswerOf(e, args.face.faulted);
|
|
35
|
+
}
|
|
36
|
+
return launchDurableRun(ctx, runStore, args, sessionId, taskId, trustedInternals, legId);
|
|
37
|
+
}
|
|
38
|
+
async function claimAndCommit(ctx, runStore, args, sessionId, taskId) {
|
|
39
|
+
const { deps } = ctx;
|
|
26
40
|
const created = await timeClaim(deps.metrics, "run_claim", runStore.createRun(taskId, sessionId, args.prepared.auth?.subject ?? null, deps.instanceId ?? "default", { ...runMeta(args.prepared, args.source), identity: args.identity, idem: args.idem ?? null }));
|
|
27
41
|
if (created.ok)
|
|
28
42
|
clearTurnActivity(taskId);
|
|
@@ -40,11 +54,11 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
40
54
|
const owner = args.prepared.auth?.subject ?? null;
|
|
41
55
|
const stopPreLaunchHeartbeat = startClaimHeartbeat(runStore, taskId, owner, deps.metrics);
|
|
42
56
|
try {
|
|
43
|
-
const placementReject = await commitExecutionContext(deps, { kind: "run", runStore, taskId }, args.prepared.execution);
|
|
57
|
+
const placementReject = await commitExecutionContext(deps, { kind: "run", runStore, taskId, legId: created.legId }, args.prepared.execution);
|
|
44
58
|
if (placementReject)
|
|
45
|
-
return placementReject;
|
|
59
|
+
return args.face.refused(placementReject);
|
|
46
60
|
if (deps.checkpointStore) {
|
|
47
|
-
const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, { runStore, taskId }, args.prepared);
|
|
61
|
+
const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, { runStore, taskId, legId: created.legId }, args.prepared);
|
|
48
62
|
if (ctxRefusal === SUBMIT_CTX_CLAIM_LOST)
|
|
49
63
|
return await refusalAfterLostClaim(deps, runStore, sessionId, taskId);
|
|
50
64
|
if (ctxRefusal)
|
|
@@ -55,13 +69,13 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
55
69
|
await args.workflowDecision.commitBeforeLaunch(taskId);
|
|
56
70
|
}
|
|
57
71
|
catch (err) {
|
|
58
|
-
await
|
|
72
|
+
await withdrawClaimedRun(runStore, taskId, created.legId, (releaseErr, step) => {
|
|
59
73
|
deps.logger?.warn?.("workflow_decision_run_release_failed", { taskId, sessionId, step, err: releaseErr instanceof Error ? releaseErr.message : String(releaseErr) });
|
|
60
74
|
});
|
|
61
75
|
throw err;
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
|
-
const lostClaim = await recheckClaimBeforeLaunch(deps, runStore, sessionId, taskId);
|
|
78
|
+
const lostClaim = await recheckClaimBeforeLaunch(deps, runStore, sessionId, taskId, created.legId);
|
|
65
79
|
if (lostClaim !== undefined)
|
|
66
80
|
return lostClaim;
|
|
67
81
|
}
|
|
@@ -69,11 +83,16 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
69
83
|
stopPreLaunchHeartbeat();
|
|
70
84
|
}
|
|
71
85
|
commitSessionInheritEnv(deps, args.prepared.spec.sessionId, args.prepared.body);
|
|
86
|
+
return { holdingLeg: created.legId };
|
|
87
|
+
}
|
|
88
|
+
function launchDurableRun(ctx, runStore, args, sessionId, taskId, trustedInternals, legId) {
|
|
89
|
+
const { deps } = ctx;
|
|
90
|
+
const { inflightRuns, preemptableRuns, steerableRuns } = ctx.registry;
|
|
72
91
|
const anchorOwner = args.prepared.auth?.subject ?? null;
|
|
73
|
-
const
|
|
74
|
-
const captureTurnAnchor = deps.resumeAnchorStore &&
|
|
92
|
+
const sessionFactsOf = sessionFactsReadOf(deps.sessionStorage);
|
|
93
|
+
const captureTurnAnchor = deps.resumeAnchorStore && sessionFactsOf
|
|
75
94
|
? async (eventId) => {
|
|
76
|
-
const leaf = (await
|
|
95
|
+
const leaf = (await sessionFactsOf(sessionId))?.leafId;
|
|
77
96
|
if (leaf)
|
|
78
97
|
await deps.resumeAnchorStore.put(sessionId, eventId, leaf, anchorOwner);
|
|
79
98
|
}
|
|
@@ -89,7 +108,7 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
89
108
|
...fleetRunLabels(args.prepared.acceptance.objectiveAtSubmit),
|
|
90
109
|
});
|
|
91
110
|
nameFleetRowOnDelivery(args.prepared.acceptance, fleetPub);
|
|
92
|
-
void heldFor(args.prepared.peerLease, () => runInBackground(args.prepared.runner, args.prepared.spec, runStore, taskId, deps.metrics, args.prepared.auth?.subject, args.prepared.verify, args.prepared.cascade ? cascadeConfig(deps.config.cascadeLadder, args.prepared.spec.limits?.maxCostUsd) : undefined, deps.instrumentDegenerate, deps.planCacheProbe, deps.config.traceThinking, inflightRuns, preemptableRuns, steerableRuns, deps.modelUsage, deps.elicitation, args.elicitOwner, captureTurnAnchor, fleetPub, captureUserMessageAnchor, deps.question, deps.workflowCompletionInbox, deps.subagentSteerRegistry, (m, x) => deps.logger?.info?.(m, x), deps.sendUserFile, deps.promptManifests, deps.toolApproval
|
|
111
|
+
void heldFor(args.prepared.peerLease, () => runInBackground(args.prepared.runner, args.prepared.spec, runStore, taskId, { legId, runStaleSec: deps.config.runStaleSec }, deps.metrics, args.prepared.auth?.subject, args.prepared.verify, args.prepared.cascade ? cascadeConfig(deps.config.cascadeLadder, args.prepared.spec.limits?.maxCostUsd) : undefined, deps.instrumentDegenerate, deps.planCacheProbe, deps.config.traceThinking, inflightRuns, preemptableRuns, steerableRuns, deps.modelUsage, deps.elicitation, args.elicitOwner, captureTurnAnchor, fleetPub, captureUserMessageAnchor, deps.question, deps.workflowCompletionInbox, deps.subagentSteerRegistry, (m, x) => deps.logger?.info?.(m, x), deps.sendUserFile, deps.promptManifests, deps.toolApproval
|
|
93
112
|
? {
|
|
94
113
|
coordinator: deps.toolApproval,
|
|
95
114
|
streamApprovalOn: resolveStreamApprovalGate({
|
|
@@ -101,9 +120,9 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
101
120
|
windowMs: deps.config.streamApproval?.windowMs,
|
|
102
121
|
windowMarginMs: deps.config.streamAskWindowMarginMs,
|
|
103
122
|
declaredFamilies: declaredApprovalFrameFamilies(args.prepared.body.settings),
|
|
104
|
-
|
|
123
|
+
origin: approvalLegOriginOf(args.prepared.execution),
|
|
105
124
|
}
|
|
106
|
-
: undefined, deps.checkpointStore, args.prepared.engineNotices, trustedInternals, deps.userInputLedger, args.prepared.acceptance, createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), args.prepared.legFacts?.sessionWitness), args.prepared.legFacts?.skills));
|
|
125
|
+
: undefined, deps.checkpointStore, args.prepared.engineNotices, trustedInternals, deps.userInputLedger, args.prepared.acceptance, createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), args.prepared.legFacts?.sessionWitness), args.prepared.legFacts?.skills, args.prepared.legFacts?.registeredCwd));
|
|
107
126
|
args.runSlot?.release();
|
|
108
127
|
args.prepared.seat.markRecord();
|
|
109
128
|
return { status: 202, body: { taskId, sessionId, status: "running", ...(args.prepared.warnings !== undefined ? { warnings: args.prepared.warnings } : {}) } };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
2
|
import type { SessionHead, TaskSpec } from "@sema-agent/core";
|
|
3
|
+
import { HttpError } from "../security.js";
|
|
3
4
|
import { type DeviceOwner, type DeviceStore } from "../device-store.js";
|
|
4
5
|
import { type DeviceEnrollment, type DeviceRejection } from "../device-enrollment.js";
|
|
5
6
|
import type { ServiceConfig } from "../config.js";
|
|
@@ -123,19 +124,30 @@ export type RootedTaskSpec = TaskSpec & {
|
|
|
123
124
|
* 走到这里只能是擦型或 JS 形;拒在建任何行之前)。续跑家族照它自己的折叠律把这只拒答成 409 `resume_blocked_by_policy`(`blockedBy` = 这只码,
|
|
124
125
|
* `http/resume-legs.ts` 的 `resolveResumeSpecOrBlocked`:装配期的每一只 `HttpError` 在续跑腿上都这么折),同样什么都没续。
|
|
125
126
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
127
|
+
* **根「必须已在」(`requireExistingSession`)的唯一写者也是这里**(装配器不写它),按调用方交来的 {@link RootUse} 穷举 —— 用法由**选引擎入口的那条腿**交
|
|
128
|
+
* (受理漏斗:与它交给提交腿的 `cascade` 同一个值;续跑重建:`session`;续跑的梯子臂:`ladder_host`),不从提交体再读一遍:
|
|
129
|
+
* · `session` —— 它是引擎在根上取会话时的「只接、不建」:解析器步 ① 读到过这一行(`occupant` 在场),或调用方自己要求了它(`requireExistingSession: true`;
|
|
130
|
+
* 店不带执行席时这是唯一的来源)⇒ 盖 `true`:门与引擎取会话之间这一行被删(属主删除 / 受理前拒的撤回),引擎答 `resume.session_not_found`,不在原 id 上重建一只
|
|
131
|
+
* 无主的空根;没读到行、调用方也没要求 ⇒ 不盖(只加不减:装配器交来的那一位原样留着);
|
|
132
|
+
* · `ladder_host` —— 引擎在梯子上不取根,没有可盖的取会话 ⇒ 盖出的 spec 上**没有**这一位(交来的 spec 带着也剥掉:续跑的梯子臂从重建的那一份再盖);
|
|
133
|
+
* 根在不在、门后被删由宿主判 —— 受理口的属主门(调用方要求了它而行不在 ⇒ 404)与执行起点的认领(带 run 店的部署:根行锁之后判在不在 / 放置提交判行在 ⇒ 404)。
|
|
132
134
|
*/
|
|
133
135
|
export declare function stampSpecRoot(spec: ResolvedTaskSpec, ctx: ExecutionRoot, submission: SpecRootSubmission): RootedTaskSpec;
|
|
134
|
-
/**
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
/**
|
|
137
|
+
* 引擎拿这次提交的根做什么(闭集;{@link stampSpecRoot} 按它穷举 —— 加一种用法 ⇒ 那只 `switch` 编译红):
|
|
138
|
+
* · `session` —— 引擎在根上取会话跑(单腿;验证门的实现腿与修复腿;续跑家族 —— 续跑、wake、宿主会话上新铸的一跑);
|
|
139
|
+
* · `ladder_host` —— 根是梯子的宿主(`cascade: true` 的组合入口):每一级在引擎为它现铸的会话里冷跑,引擎不取根;根只是这条梯子停驻卡的归属(组合腿的 `hostSessionId`)。
|
|
140
|
+
*/
|
|
141
|
+
export type RootUse = "session" | "ladder_host";
|
|
142
|
+
/**
|
|
143
|
+
* {@link stampSpecRoot} 的第三参:选引擎入口的那条腿交来的用法;调用方「根必须已在」的要求只属于 `session` 用法(梯子上它由宿主的门与认领判,型上没有这一键)。
|
|
144
|
+
*/
|
|
145
|
+
export type SpecRootSubmission = {
|
|
146
|
+
readonly use: "session";
|
|
137
147
|
readonly requireExistingSession?: unknown;
|
|
138
|
-
}
|
|
148
|
+
} | {
|
|
149
|
+
readonly use: "ladder_host";
|
|
150
|
+
};
|
|
139
151
|
/**
|
|
140
152
|
* run 店建行时根会话行已经不在(`CreateRunOutcome.sessionAbsent`:受理之后、认领之前会话被删)的**唯一**答复 ——
|
|
141
153
|
* 四个建行点(同步 / 流式 / durable / wake)、解析期的「行不在 / 住客换了」与提交期的 `gone` 同答 404 `resume.session_not_found`,什么都没建、什么都没跑。
|
|
@@ -150,19 +162,100 @@ export interface ExecutionRefusal {
|
|
|
150
162
|
readonly body: RefusalBody;
|
|
151
163
|
}
|
|
152
164
|
/**
|
|
153
|
-
* 本次认领 ——
|
|
154
|
-
* `
|
|
165
|
+
* 本次认领 —— 提交没放行时要撤回的东西。撤回只有一张表({@link withdrawClaim}),按认领种类把认领撤回到**它取来时的样子**:
|
|
166
|
+
* · `run` = 本请求铸的行(四个建行点 / wake 的现建行 / workflow 决定在宿主会话上的新一跑;`legId` = 建行交回的持有腿):取来之前没有这一行 ⇒ 每一种收场都删掉它
|
|
167
|
+
* (唯一写法 `withdrawClaimedRun`:只认本腿持有的那一行,行仍在跑才删,认领与幂等键随行去;已被收割 / 终局 ⇒ 零删)—— 同一个 `taskId` / 同一把幂等键的重发是一次新提交;
|
|
168
|
+
* · `resumed` = 续跑家族 `markResuming` 认领的停驻行:取来之前它停在等一张待决的卡 ⇒ 放回停驻(`restore`:认领方的写法 = 停驻的唯一提交点 `park-row-commit.ts` 的 `commitParkRow`;
|
|
169
|
+
* 认领与幂等键留着,卡仍待决,同一个决定可以再发;认领窗里落下的取消由认领方按取消收场 —— 停驻态会让下一次认领重置取消旗)。
|
|
170
|
+
* 唯一的例外是 `gone`:店答出这条 run 的会话已经不在,它再也续不了 ⇒ 终结(同 `run` 那一只写法);
|
|
171
|
+
* · `parked` = 停驻赎回的认领:每一种收场都回滚认领。
|
|
172
|
+
* 答复不在认领上:写口交回店的拒答,各面经自己的 {@link ClaimFace} 答它。
|
|
155
173
|
*/
|
|
156
174
|
export type ExecutionClaim = {
|
|
157
175
|
readonly kind: "run";
|
|
158
176
|
readonly runStore: RunStore;
|
|
159
177
|
readonly taskId: string;
|
|
178
|
+
readonly legId: string;
|
|
179
|
+
} | {
|
|
180
|
+
readonly kind: "resumed";
|
|
181
|
+
readonly runStore: RunStore;
|
|
182
|
+
readonly taskId: string;
|
|
183
|
+
readonly restore: () => Promise<void>;
|
|
160
184
|
} | {
|
|
161
185
|
readonly kind: "parked";
|
|
162
186
|
readonly taskId: string;
|
|
163
187
|
readonly rollback: (why: string) => Promise<unknown>;
|
|
164
|
-
readonly goneAnswer: ExecutionRefusal;
|
|
165
188
|
};
|
|
189
|
+
/**
|
|
190
|
+
* 认领之后、交给引擎之前那一段没放行的收场 —— **唯一**的类别判定。规则一句:**店答出的拒是答案,店的故障不是**。判在 {@link commitExecutionContext} 的两只出口上
|
|
191
|
+
* (结构判:交回拒答 vs 抛,不读错误文案);续跑腿「提交放行之后、交给引擎之前」那一段的抛同属 `faulted`(`resume-legs.ts`,经同一张撤回表):
|
|
192
|
+
* · `gone` —— 店答出这条会话已经不在(行没了 / 住客换了,{@link isRootSessionGoneRefusal}):确定的答案,这条会话上什么都再也续不了;
|
|
193
|
+
* · `refused` —— 店答出这条会话此刻不能在本处执行(已放在别的车道、写者在别处、设备拒):确定的答案,但会话还在 —— 与认领之前解析器读出同一个事实是同一个命运;
|
|
194
|
+
* · `faulted` —— 店没答出来(故障 / 超时 / 程序错):证不出这条会话不能执行,不当答案用。答复只看(这一面 × 店有没有答出来):各面的瞬时答复({@link faultedAnswerOf}),
|
|
195
|
+
* 本服务自己的程序错照旧响亮 500。
|
|
196
|
+
*/
|
|
197
|
+
export type CommitEnding = "gone" | "refused" | "faulted";
|
|
198
|
+
/**
|
|
199
|
+
* 提交点的拒答是不是「会话不在」那一只({@link rootSessionAbsentAnswer};唯一读者 —— 撤回表据它分 `gone` / `refused`,续跑家族与停驻赎回的 {@link ClaimFace} 据它决定那一只拒怎么答)。
|
|
200
|
+
* 只认这一只答复的码(与 {@link isRootSessionGoneError} 同一个判据,一个读拒答、一个读解析器的抛)。
|
|
201
|
+
*/
|
|
202
|
+
export declare function isRootSessionGoneRefusal(refusal: ExecutionRefusal): boolean;
|
|
203
|
+
/**
|
|
204
|
+
* `faulted` 那一形的答复 —— 认领这一段(认领那一笔、认领之后的提交、续跑腿交给引擎之前的店往返、新提交起跑之前的店写)的一抛**只在这里**分两种:
|
|
205
|
+
* 店没答出来(判官的 `corrupt` / `connection` / `deployment` / `unclassified`)⇒ 这一面的瞬时答复(`answer`:新提交 {@link runStoreUnavailableAnswer} · 续跑家族
|
|
206
|
+
* `resume-ctx-read.ts` 的 `resumeClaimFaultAnswer` · 停驻赎回 `decide.store_unreachable`;每一面与它认领那一笔撞店故障同答);本服务自己的程序错(`defect`)⇒ 原样上抛,响亮成 500。
|
|
207
|
+
* 两种都不改撤回:认领已按 `faulted` 撤回(调用方在调本函数之前撤,或写口在抛之前撤)。判官加词而这里不表态 = 编译错。
|
|
208
|
+
* 设备注册簿那一次往返(设备店 / 准入链)也只经这里读:店没答出来 ⇒ 设备闭集的 {@link registryUnavailable},认领之前的准入与认领之后的首绑 / 再断言同答。
|
|
209
|
+
*/
|
|
210
|
+
export declare function faultedAnswerOf<A>(e: unknown, answer: () => A): A;
|
|
211
|
+
/**
|
|
212
|
+
* 新提交(`POST /v1/tasks` 两腿、`POST /v1/runs` 与 A2A)撞店故障的**唯一**答复({@link SUBMISSION_CLAIM_FACE} 的 `faulted`)—— 503 `state.run_store_unavailable`:
|
|
213
|
+
* 认领之前那一次执行席读、认领那一笔(`createRun`)、认领之后的执行放置、续跑输入的写或起跑之前的认领复核,有一次店往返没答出来;本请求铸的行已撤回(删掉,认领与幂等键随行去),
|
|
214
|
+
* 什么都没起跑。稍后原样再发(同一个自带 `taskId` 也行);一直如此 ⇒ 请运维查库。句子不带店层 detail。🔴 形是给冻结门看的:`status: <三位数>, body: refusalBody({ errorCode: "<码>", message: "<整句双引号字面>"`,中间只许有空白。
|
|
215
|
+
*/
|
|
216
|
+
export declare function runStoreUnavailableAnswer(): {
|
|
217
|
+
status: 503;
|
|
218
|
+
body: RefusalBody;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* **一面的两只答法**(规则一句见文件头「一面一只答法」):这一面在认领之前那一读(解析器)、认领那一笔、认领之后每一笔、交给引擎之前的店往返上,
|
|
222
|
+
* 店答出的拒与店的故障各怎么答 —— 每一面只声明一次,各调用点只经它答,不各自选码:
|
|
223
|
+
* · `refused` —— 写口交回的店的拒答(会话不在 / 本处此刻不能执行)在这一面的答复:与这一面认领之前解析器读出同一个事实同一只答;
|
|
224
|
+
* · `faulted` —— 店没答出来在这一面的瞬时答复(经 {@link faultedAnswerOf} 读;本服务的程序错照旧上抛)。
|
|
225
|
+
* 三面:{@link SUBMISSION_CLAIM_FACE}(新提交)· {@link CONTINUATION_CLAIM_FACE}(续跑家族:决断 / `/resume` / `plan_review` / `/wake` / `/decide` 在宿主会话上起的新一跑)·
|
|
226
|
+
* 停驻赎回(`parked-decide.ts` 的 `parkedRedeemFace`,按子代句柄铸)。
|
|
227
|
+
*/
|
|
228
|
+
export interface ClaimFace {
|
|
229
|
+
readonly refused: (refusal: ExecutionRefusal) => ExecutionRefusal;
|
|
230
|
+
readonly faulted: () => ExecutionRefusal;
|
|
231
|
+
}
|
|
232
|
+
/** 新提交这一面:店答出的拒原样答(认领之前解析器那一只 typed 拒同码同体);店没答出来 ⇒ {@link runStoreUnavailableAnswer}。 */
|
|
233
|
+
export declare const SUBMISSION_CLAIM_FACE: ClaimFace;
|
|
234
|
+
/**
|
|
235
|
+
* 续跑家族这一面:会话不在({@link isRootSessionGoneRefusal})⇒ 原答 404 `resume.session_not_found`;其余店答出的拒 ⇒ {@link cardWaitingRefusalAnswer}(与认领之前同一只折法);
|
|
236
|
+
* 店没答出来 ⇒ `resume-ctx-read.ts` 的 `resumeClaimFaultAnswer`(503 `state.resume_context_unreadable`,卡仍待决)。
|
|
237
|
+
*/
|
|
238
|
+
export declare const CONTINUATION_CLAIM_FACE: ClaimFace;
|
|
239
|
+
/**
|
|
240
|
+
* 一只拒在「有一张卡仍在等」的那几面上的答复(续跑家族与停驻赎回;认领之前的解析器拒与认领之后写口交回的拒同经这里)—— 认领之前那一只折法
|
|
241
|
+
* (`checkpoint-ctx.ts` 的 `resumeAssemblyRefusalAnswer`:409 `resume_blocked_by_policy`,`blockedBy` = 原码,原事实随体;自报瞬时的拒原码原状态)+ `retriable`(卡仍待决)。
|
|
242
|
+
*/
|
|
243
|
+
export declare function cardWaitingRefusalAnswer(refusal: ExecutionRefusal): ExecutionRefusal;
|
|
244
|
+
/** 一只拒答 → typed 拒(`HttpError`;体经 `httpErrorRefusal` 读回同一份:码、句、机读事实)。解析器的拒与提交门认领之前的拒只认这一种载体。 */
|
|
245
|
+
export declare function refusalHttpError(refusal: ExecutionRefusal): HttpError;
|
|
246
|
+
/**
|
|
247
|
+
* **认领之前那一读**在一面上的唯一读法(提交门 / 续跑家族的重建 / 停驻赎回同调唯一的解析器 {@link resolveExecutionContext}):解析器的拒(typed `HttpError`)是答案,
|
|
248
|
+
* 原样上抛给这一面自己的折法;店没答出来 ⇒ 抛这一面的瞬时答复(`face.faulted`,载体 {@link refusalHttpError} 外套 {@link ClaimFaultAnswer} —— 与这一面认领那一笔撞店故障同答,
|
|
249
|
+
* 续跑家族的折叠口认它、不折);本服务的程序错原样上抛(响亮 500)。认领之前没有认领可撤,状态零改动。
|
|
250
|
+
*/
|
|
251
|
+
export declare function resolveBeforeClaim(deps: ExecutionContextDeps, entry: Extract<ExecutionEntry, {
|
|
252
|
+
readonly root: string;
|
|
253
|
+
}>, face: ClaimFace): Promise<RootedExecutionContext>;
|
|
254
|
+
/** {@link resolveBeforeClaim} 抛出的「店没答出来」答复(typed 拒;`answer` = 这一面的瞬时答复原体)。只有折叠口要认它(续跑家族不把它折成 409);提交门按 typed 拒原样答。 */
|
|
255
|
+
export declare class ClaimFaultAnswer extends HttpError {
|
|
256
|
+
readonly answer: ExecutionRefusal;
|
|
257
|
+
constructor(answer: ExecutionRefusal);
|
|
258
|
+
}
|
|
166
259
|
/** {@link commitExecutionContext} 的依赖 —— 逐字取自 `ServiceDeps` 的同名键(同一只 deps 对象喂进来)。 */
|
|
167
260
|
export interface ExecutionCommitDeps {
|
|
168
261
|
readonly sessionStorage?: {
|
|
@@ -189,10 +282,18 @@ export declare function placementWriteDeadlineMs(runStaleSec: number | undefined
|
|
|
189
282
|
export declare function devicePlacementErrorBody(rej: DeviceRejection): RefusalBody;
|
|
190
283
|
/**
|
|
191
284
|
* **认领之后的唯一写口**(四个 `createRun` 点、续跑家族 `markResuming` 之后、停驻赎回 `claimParkedAgent` 之后)。返回 `null` = 放行;
|
|
192
|
-
*
|
|
285
|
+
* 否则本次认领已按 {@link withdrawClaim} 撤回(店答出的拒 = `gone` / `refused`),调用方交回拒答。店故障 / 超时 ⇒ 认领按 `faulted` 撤回后原样上抛
|
|
286
|
+
* (响亮,不当答案:各调用方经 {@link faultedAnswerOf} 落自己这一面的瞬时码);设备意图那一支的注册簿往返(首绑 / 再断言)撞故障 ⇒ 交回设备闭集的 {@link registryUnavailable}
|
|
287
|
+
* (经 {@link faultedAnswerOf},与认领之前的准入同一只读法;程序错照旧上抛),执行席那一读撞故障与认领之前那一读同答(上抛)。
|
|
193
288
|
*
|
|
194
289
|
* 不变量(一句):**离开本函数的那一刻,这条会话(解析器那一位住客)的格就是这条执行的车道(device 车道:准入批准的那台设备);否则本次认领已释放、调用方拿到拒答。**
|
|
195
290
|
* 它不说「此后不变」:认领持有期间根行住客与放置不被换绑 / 导入改动,那是各写者写事务内锁根行后读认领的保证(规则句),不在本函数重复判。
|
|
196
291
|
*/
|
|
197
292
|
export declare function commitExecutionContext(deps: ExecutionCommitDeps, claim: ExecutionClaim, ctx: RootedExecutionContext): Promise<ExecutionRefusal | null>;
|
|
293
|
+
/**
|
|
294
|
+
* **撤回本次认领的唯一一张表**(规则与各种类的落点见 {@link ExecutionClaim};类别见 {@link CommitEnding})。两个调用处:{@link commitExecutionContext} 的两只出口,
|
|
295
|
+
* 与续跑腿「提交放行之后、交给引擎之前」那一段的抛(`resume-legs.ts`,`faulted`)。`ending` 只在 `resumed` 上分叉(会话不在 ⇒ 终结;其余 ⇒ 放回停驻),另两种认领取来时就只有一个去处。
|
|
296
|
+
* 认领之后的其余几笔(续跑输入、决定落行、起跑之前的复核)撤本请求铸的行用 `run` 那一臂的同一只写法(`withdrawClaimedRun`)。
|
|
297
|
+
*/
|
|
298
|
+
export declare function withdrawClaim(deps: ExecutionCommitDeps, claim: ExecutionClaim, why: string, ending: CommitEnding): Promise<void>;
|
|
198
299
|
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -3,13 +3,16 @@ import { HttpError, createCodedHttpError, ssoVerifiedScope } from "../security.j
|
|
|
3
3
|
import { gatedPerson } from "./principal-gate.js";
|
|
4
4
|
import { DEVICE_ERROR_CODES, assertDeviceIdShape } from "../device-store.js";
|
|
5
5
|
import { buildDeviceRejection } from "../device-enrollment.js";
|
|
6
|
-
import { sameOccupant } from "../execution-placement.js";
|
|
6
|
+
import { SessionForkInProgressError, sameOccupant } from "../execution-placement.js";
|
|
7
7
|
import { deployedExecutionLanes } from "../execution-lane-caps.js";
|
|
8
8
|
import { gateExecutionLane } from "../runtime-caps-resolver.js";
|
|
9
|
-
import { releaseClaimedRun } from "./claimed-run.js";
|
|
9
|
+
import { releaseClaimedRun, withdrawClaimedRun } from "./claimed-run.js";
|
|
10
10
|
import { sessionIdRetiredFor } from "../deleted-session-ids.js";
|
|
11
11
|
import { refusalBody } from "./refusal-body.js";
|
|
12
12
|
import { timeClaim } from "./claim-latency.js";
|
|
13
|
+
import { storeFaultClassOf } from "../plugins/store-fault.js";
|
|
14
|
+
import { resumeClaimFaultAnswer } from "./resume-ctx-read.js";
|
|
15
|
+
import { resumeAssemblyRefusalAnswer, resumeRefusalWithCard } from "./checkpoint-ctx.js";
|
|
13
16
|
export async function resolveExecutionContext(deps, entry) {
|
|
14
17
|
const lanes = deployedExecutionLanes(deps.config);
|
|
15
18
|
switch (entry.kind) {
|
|
@@ -70,8 +73,7 @@ function laneOf(root, cell, lanes) {
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
function sessionMirrorError(root) {
|
|
73
|
-
|
|
74
|
-
return createCodedHttpError(answer.status, answer.body.errorCode, answer.body.error, { forkPath: forkPathOf(root) });
|
|
76
|
+
return refusalHttpError(sessionMirrorAnswer(root));
|
|
75
77
|
}
|
|
76
78
|
export function forkPathOf(root) {
|
|
77
79
|
return `/v1/sessions/${encodeURIComponent(root)}/fork`;
|
|
@@ -87,8 +89,7 @@ function sessionMirrorAnswer(root) {
|
|
|
87
89
|
};
|
|
88
90
|
}
|
|
89
91
|
function rootSessionGoneError() {
|
|
90
|
-
|
|
91
|
-
return createCodedHttpError(absent.status, absent.body.errorCode, absent.body.error);
|
|
92
|
+
return refusalHttpError(rootSessionAbsentAnswer());
|
|
92
93
|
}
|
|
93
94
|
export function isRootSessionGoneError(err) {
|
|
94
95
|
return err instanceof HttpError && err.code === rootSessionAbsentAnswer().body.errorCode;
|
|
@@ -142,8 +143,8 @@ async function admitDevicePlacement(deps, entry, lane, seat, reading) {
|
|
|
142
143
|
try {
|
|
143
144
|
admitted = await deps.deviceEnrollment.admitSession({ rootSessionId: entry.root, placement: reading, requester: owner, ...(requestedDeviceId === undefined ? {} : { requestedDeviceId }) });
|
|
144
145
|
}
|
|
145
|
-
catch {
|
|
146
|
-
throw asHttpError(registryUnavailable
|
|
146
|
+
catch (e) {
|
|
147
|
+
throw asHttpError(faultedAnswerOf(e, registryUnavailable));
|
|
147
148
|
}
|
|
148
149
|
if (admitted.ok)
|
|
149
150
|
return { rootSessionId: entry.root, occupant: reading.occupant, owner, admittedDeviceId: admitted.value.deviceId, firstBind: false };
|
|
@@ -153,8 +154,8 @@ async function admitDevicePlacement(deps, entry, lane, seat, reading) {
|
|
|
153
154
|
try {
|
|
154
155
|
view = await deps.deviceStore.readDeviceForAdmission(requestedDeviceId, owner);
|
|
155
156
|
}
|
|
156
|
-
catch {
|
|
157
|
-
throw asHttpError(registryUnavailable
|
|
157
|
+
catch (e) {
|
|
158
|
+
throw asHttpError(faultedAnswerOf(e, registryUnavailable));
|
|
158
159
|
}
|
|
159
160
|
if (!view)
|
|
160
161
|
throw asHttpError(buildDeviceRejection(DEVICE_ERROR_CODES.NOT_FOUND, "device not found"));
|
|
@@ -169,8 +170,20 @@ export function stampSpecRoot(spec, ctx, submission) {
|
|
|
169
170
|
if (named !== undefined && named !== ctx.root) {
|
|
170
171
|
throw createCodedHttpError(400, "request.precondition_unmet", "the deployment's spec resolver named a session other than the one this submission was authorized for — a submission's root session comes only from the authorizer, so resolveSpec must not set sessionId (read opts.execution.root instead)");
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
switch (submission.use) {
|
|
174
|
+
case "session": {
|
|
175
|
+
const mustExist = ctx.occupant !== undefined || submission.requireExistingSession === true;
|
|
176
|
+
return mustExist ? { ...spec, sessionId: ctx.root, requireExistingSession: true } : { ...spec, sessionId: ctx.root };
|
|
177
|
+
}
|
|
178
|
+
case "ladder_host": {
|
|
179
|
+
const { requireExistingSession: _noAcquireOnALadder, ...ladderSpec } = spec;
|
|
180
|
+
return { ...ladderSpec, sessionId: ctx.root };
|
|
181
|
+
}
|
|
182
|
+
default: {
|
|
183
|
+
const unhandled = submission;
|
|
184
|
+
throw new Error(`stampSpecRoot: unhandled root use ${JSON.stringify(unhandled)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
174
187
|
}
|
|
175
188
|
export function rootSessionAbsentAnswer() {
|
|
176
189
|
return {
|
|
@@ -181,6 +194,62 @@ export function rootSessionAbsentAnswer() {
|
|
|
181
194
|
}),
|
|
182
195
|
};
|
|
183
196
|
}
|
|
197
|
+
export function isRootSessionGoneRefusal(refusal) {
|
|
198
|
+
return refusal.body.errorCode === rootSessionAbsentAnswer().body.errorCode;
|
|
199
|
+
}
|
|
200
|
+
export function faultedAnswerOf(e, answer) {
|
|
201
|
+
const fault = storeFaultClassOf(e);
|
|
202
|
+
switch (fault) {
|
|
203
|
+
case "corrupt":
|
|
204
|
+
case "connection":
|
|
205
|
+
case "deployment":
|
|
206
|
+
case "unclassified":
|
|
207
|
+
return answer();
|
|
208
|
+
case "defect":
|
|
209
|
+
throw e;
|
|
210
|
+
default: {
|
|
211
|
+
const unhandled = fault;
|
|
212
|
+
throw new Error(`faultedAnswerOf: the store-fault judge answered a class this reader does not place: ${String(unhandled)}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export function runStoreUnavailableAnswer() {
|
|
217
|
+
return {
|
|
218
|
+
status: 503,
|
|
219
|
+
body: refusalBody({ errorCode: "state.run_store_unavailable", message: "this task could not be recorded just now (the store did not answer), so nothing was started. Send it again later; if this keeps happening, ask whoever operates this deployment to check its database." }),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
export const SUBMISSION_CLAIM_FACE = { refused: (refusal) => refusal, faulted: runStoreUnavailableAnswer };
|
|
223
|
+
export const CONTINUATION_CLAIM_FACE = {
|
|
224
|
+
refused: (refusal) => (isRootSessionGoneRefusal(refusal) ? refusal : cardWaitingRefusalAnswer(refusal)),
|
|
225
|
+
faulted: resumeClaimFaultAnswer,
|
|
226
|
+
};
|
|
227
|
+
export function cardWaitingRefusalAnswer(refusal) {
|
|
228
|
+
const { error, errorCode, ...facts } = refusal.body;
|
|
229
|
+
return resumeRefusalWithCard(resumeAssemblyRefusalAnswer(refusal.status, { errorCode, message: error, facts }), true);
|
|
230
|
+
}
|
|
231
|
+
export function refusalHttpError(refusal) {
|
|
232
|
+
const { error, errorCode, ...facts } = refusal.body;
|
|
233
|
+
return createCodedHttpError(refusal.status, errorCode, error, Object.keys(facts).length > 0 ? facts : undefined);
|
|
234
|
+
}
|
|
235
|
+
export async function resolveBeforeClaim(deps, entry, face) {
|
|
236
|
+
try {
|
|
237
|
+
return await resolveExecutionContext(deps, entry);
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
if (e instanceof HttpError)
|
|
241
|
+
throw e;
|
|
242
|
+
throw new ClaimFaultAnswer(faultedAnswerOf(e, face.faulted));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export class ClaimFaultAnswer extends HttpError {
|
|
246
|
+
answer;
|
|
247
|
+
constructor(answer) {
|
|
248
|
+
const { error, errorCode: code, ...facts } = answer.body;
|
|
249
|
+
super(answer.status, error, Object.keys(facts).length > 0 ? { code, extra: facts } : { code });
|
|
250
|
+
this.answer = answer;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
184
253
|
export function placementWriteDeadlineMs(runStaleSec) {
|
|
185
254
|
const stale = typeof runStaleSec === "number" && Number.isFinite(runStaleSec) && runStaleSec > 0 ? runStaleSec : RUN_STALE_SEC_DEFAULT;
|
|
186
255
|
return Math.min(15_000, Math.max(1_000, Math.floor((stale * 1000) / 4)));
|
|
@@ -209,7 +278,7 @@ export async function commitExecutionContext(deps, claim, ctx) {
|
|
|
209
278
|
return timeClaim(deps.metrics, "placement_commit", commitPlacement(deps, claim, ctx, seat, occupant));
|
|
210
279
|
}
|
|
211
280
|
async function commitPlacement(deps, claim, ctx, seat, occupant) {
|
|
212
|
-
const release = (why) =>
|
|
281
|
+
const release = (why, ending) => withdrawClaim(deps, claim, why, ending);
|
|
213
282
|
const deadlineMs = placementWriteDeadlineMs(deps.config?.runStaleSec);
|
|
214
283
|
const withDeadline = async (work) => {
|
|
215
284
|
let timer;
|
|
@@ -227,56 +296,64 @@ async function commitPlacement(deps, claim, ctx, seat, occupant) {
|
|
|
227
296
|
clearTimeout(timer);
|
|
228
297
|
}
|
|
229
298
|
};
|
|
230
|
-
const goneAnswer = () => (claim.kind === "parked" ? claim.goneAnswer : rootSessionAbsentAnswer());
|
|
231
299
|
let refusal;
|
|
232
300
|
try {
|
|
233
301
|
refusal =
|
|
234
302
|
ctx.device !== undefined
|
|
235
|
-
? await commitDevice(deps, seat, ctx.device, withDeadline
|
|
303
|
+
? await commitDevice(deps, seat, ctx.device, withDeadline)
|
|
236
304
|
: ctx.placement === "absent"
|
|
237
|
-
? await commitPlace(seat, ctx, occupant, withDeadline
|
|
238
|
-
: await reassertWriter(seat, ctx, occupant, withDeadline
|
|
305
|
+
? await commitPlace(seat, ctx, occupant, withDeadline)
|
|
306
|
+
: await reassertWriter(seat, ctx, occupant, withDeadline);
|
|
239
307
|
}
|
|
240
308
|
catch (err) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (ctx.device !== undefined) {
|
|
244
|
-
refusal = deviceRefusal(registryUnavailable());
|
|
309
|
+
if (err instanceof SessionForkInProgressError) {
|
|
310
|
+
refusal = { status: 409, body: refusalBody({ errorCode: err.code, message: err.message }) };
|
|
245
311
|
deps.metrics?.inc("execution_placement_rejects_total", { errorCode: refusal.body.errorCode });
|
|
312
|
+
await release(`execution placement rejected: [${refusal.body.errorCode}] ${refusal.body.error}`, "refused");
|
|
246
313
|
return refusal;
|
|
247
314
|
}
|
|
315
|
+
deps.logger?.warn("execution_placement_commit_failed", { root: ctx.root, lane: ctx.lane, placement: ctx.placement, deadlineMs, err: err instanceof Error ? err.message : String(err) });
|
|
316
|
+
await release(`execution placement could not be committed: ${err instanceof Error ? err.message : String(err)}`, "faulted");
|
|
248
317
|
throw err;
|
|
249
318
|
}
|
|
250
319
|
if (refusal === null)
|
|
251
320
|
return null;
|
|
252
321
|
deps.metrics?.inc("execution_placement_rejects_total", { errorCode: refusal.body.errorCode });
|
|
253
|
-
await release(`execution placement rejected: [${refusal.body.errorCode}] ${refusal.body.error}
|
|
322
|
+
await release(`execution placement rejected: [${refusal.body.errorCode}] ${refusal.body.error}`, isRootSessionGoneRefusal(refusal) ? "gone" : "refused");
|
|
254
323
|
return refusal;
|
|
255
324
|
}
|
|
256
|
-
async function
|
|
325
|
+
export async function withdrawClaim(deps, claim, why, ending) {
|
|
326
|
+
const loud = (taskId, step, err) => {
|
|
327
|
+
deps.logger?.warn("execution_placement_run_release_failed", { taskId, step, err: err instanceof Error ? err.message : String(err) });
|
|
328
|
+
deps.metrics?.inc("execution_placement_run_release_failed_total");
|
|
329
|
+
};
|
|
257
330
|
switch (claim.kind) {
|
|
258
331
|
case "run":
|
|
259
|
-
await
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
332
|
+
await withdrawClaimedRun(claim.runStore, claim.taskId, claim.legId, (err, step) => loud(claim.taskId, step, err));
|
|
333
|
+
return;
|
|
334
|
+
case "resumed":
|
|
335
|
+
if (ending !== "gone") {
|
|
336
|
+
await claim.restore();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
await releaseClaimedRun(claim.runStore, claim.taskId, why, (err, step) => loud(claim.taskId, step, err));
|
|
263
340
|
return;
|
|
264
341
|
case "parked":
|
|
265
342
|
await claim.rollback(why);
|
|
266
343
|
return;
|
|
267
344
|
default: {
|
|
268
345
|
const unhandled = claim;
|
|
269
|
-
throw new Error(`
|
|
346
|
+
throw new Error(`withdrawClaim: unknown claim ${JSON.stringify(unhandled)}`);
|
|
270
347
|
}
|
|
271
348
|
}
|
|
272
349
|
}
|
|
273
|
-
async function commitPlace(seat, ctx, occupant, withDeadline
|
|
350
|
+
async function commitPlace(seat, ctx, occupant, withDeadline) {
|
|
274
351
|
if (ctx.lane === "device") {
|
|
275
352
|
return deviceRefusal(buildDeviceRejection(DEVICE_ERROR_CODES.NOT_BOUND, "this session has no device binding — nothing was started"));
|
|
276
353
|
}
|
|
277
|
-
return placeOutcomeAnswer(ctx.root, await withDeadline(seat.place(ctx.root, occupant, { role: "writer", lane: ctx.lane }))
|
|
354
|
+
return placeOutcomeAnswer(ctx.root, await withDeadline(seat.place(ctx.root, occupant, { role: "writer", lane: ctx.lane })));
|
|
278
355
|
}
|
|
279
|
-
function placeOutcomeAnswer(root, outcome
|
|
356
|
+
function placeOutcomeAnswer(root, outcome) {
|
|
280
357
|
switch (outcome.outcome) {
|
|
281
358
|
case "placed":
|
|
282
359
|
case "same":
|
|
@@ -286,17 +363,17 @@ function placeOutcomeAnswer(root, outcome, goneAnswer) {
|
|
|
286
363
|
case "mirror":
|
|
287
364
|
return sessionMirrorAnswer(root);
|
|
288
365
|
case "gone":
|
|
289
|
-
return
|
|
366
|
+
return rootSessionAbsentAnswer();
|
|
290
367
|
default: {
|
|
291
368
|
const unhandled = outcome;
|
|
292
369
|
throw new Error(`commitExecutionContext: no answer for ${JSON.stringify(unhandled)}`);
|
|
293
370
|
}
|
|
294
371
|
}
|
|
295
372
|
}
|
|
296
|
-
async function reassertWriter(seat, ctx, occupant, withDeadline
|
|
373
|
+
async function reassertWriter(seat, ctx, occupant, withDeadline) {
|
|
297
374
|
const now = await withDeadline(seat.read(ctx.root));
|
|
298
375
|
if (now === undefined || !sameOccupant(now.occupant, occupant))
|
|
299
|
-
return
|
|
376
|
+
return rootSessionAbsentAnswer();
|
|
300
377
|
const cell = now.cell;
|
|
301
378
|
switch (cell.role) {
|
|
302
379
|
case "writer":
|
|
@@ -312,20 +389,31 @@ async function reassertWriter(seat, ctx, occupant, withDeadline, goneAnswer) {
|
|
|
312
389
|
}
|
|
313
390
|
}
|
|
314
391
|
}
|
|
315
|
-
async function commitDevice(deps, seat, intent, withDeadline
|
|
392
|
+
async function commitDevice(deps, seat, intent, withDeadline) {
|
|
316
393
|
const enrollment = deps.deviceEnrollment;
|
|
317
394
|
if (!enrollment) {
|
|
318
395
|
throw new Error("commitExecutionContext: a device placement intent was minted without a DeviceEnrollment — assembly bug (both are read from the same ServiceDeps)");
|
|
319
396
|
}
|
|
397
|
+
const registry = async (work) => {
|
|
398
|
+
try {
|
|
399
|
+
return { ok: true, value: await withDeadline(work) };
|
|
400
|
+
}
|
|
401
|
+
catch (e) {
|
|
402
|
+
return { ok: false, refusal: deviceRefusal(faultedAnswerOf(e, registryUnavailable)) };
|
|
403
|
+
}
|
|
404
|
+
};
|
|
320
405
|
if (intent.firstBind) {
|
|
321
|
-
const
|
|
406
|
+
const binding = await registry(enrollment.bindPlacement({ rootSessionId: intent.rootSessionId, occupant: intent.occupant, deviceId: intent.admittedDeviceId, requester: intent.owner }));
|
|
407
|
+
if (!binding.ok)
|
|
408
|
+
return binding.refusal;
|
|
409
|
+
const bound = binding.value;
|
|
322
410
|
if (bound.ok)
|
|
323
411
|
return null;
|
|
324
412
|
if ("reject" in bound)
|
|
325
413
|
return deviceRefusal(bound.reject);
|
|
326
414
|
switch (bound.placement) {
|
|
327
415
|
case "gone":
|
|
328
|
-
return
|
|
416
|
+
return rootSessionAbsentAnswer();
|
|
329
417
|
case "mirror":
|
|
330
418
|
return sessionMirrorAnswer(intent.rootSessionId);
|
|
331
419
|
case "tree_bound":
|
|
@@ -338,8 +426,10 @@ async function commitDevice(deps, seat, intent, withDeadline, goneAnswer) {
|
|
|
338
426
|
}
|
|
339
427
|
const placement = await withDeadline(seat.read(intent.rootSessionId));
|
|
340
428
|
if (placement === undefined || !sameOccupant(placement.occupant, intent.occupant))
|
|
341
|
-
return
|
|
342
|
-
const
|
|
343
|
-
|
|
429
|
+
return rootSessionAbsentAnswer();
|
|
430
|
+
const readmission = await registry(enrollment.admitSession({ rootSessionId: intent.rootSessionId, placement, requester: intent.owner, requestedDeviceId: intent.admittedDeviceId }));
|
|
431
|
+
if (!readmission.ok)
|
|
432
|
+
return readmission.refusal;
|
|
433
|
+
return readmission.value.ok ? null : deviceRefusal(readmission.value.reject);
|
|
344
434
|
}
|
|
345
435
|
//# sourceMappingURL=execution-context.js.map
|