@astrosheep/keiyaku 2.9.3 → 2.9.5
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/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +14 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +26 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +68 -5
- package/build/agents/harness/projection.js +179 -124
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +82 -53
- package/build/agents/providers/codex-app-server/events.js +90 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +10 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +8 -2
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +44 -8
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +5 -8
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +6 -5
- package/build/cli/commands/metadata.js +59 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +8 -3
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +7 -15
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +12 -8
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +6 -11
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +37 -6
- package/build/cli/help.js +7 -14
- package/build/cli/index.js +112 -154
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +33 -7
- package/build/cli/parse-metadata.js +3 -9
- package/build/cli/parse-selectors.js +2 -1
- package/build/cli/parse.js +35 -5
- package/build/cli/projection-address.js +12 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +58 -13
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +15 -6
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +56 -23
- package/build/cli/render/success-response.js +78 -0
- package/build/cli/render/task.js +66 -57
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +63 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +68 -38
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +3 -0
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +61 -18
- package/build/core/arc.js +33 -73
- package/build/core/audit.js +650 -0
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +22 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +22 -6
- package/build/core/draft.js +139 -19
- package/build/core/entry.js +3 -4
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/lex.js +2 -1
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +41 -52
- package/build/core/projection/generation/model.js +63 -2
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
- package/build/core/projection/generation/store.js +3 -3
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
- package/build/core/projection/projection-terminal-failure.js +106 -0
- package/build/core/projection/projection-wait.js +275 -0
- package/build/core/projection/projection-wake.js +227 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +448 -102
- package/build/core/scope.js +272 -68
- package/build/core/seal.js +165 -40
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
- package/build/core/{petition.js → settlement/petition.js} +21 -12
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +288 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +62 -41
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +6 -2
- package/build/core/task/board.js +41 -4
- package/build/core/task/commands.js +45 -28
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +12 -0
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +172 -0
- package/build/core/task/settlement-git.js +265 -74
- package/build/core/task/settlement-policy.js +67 -29
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +444 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +7 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +83 -39
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +9 -9
- package/build/keiyaku.js +2 -36
- package/build/telemetry/logger.js +4 -2
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +5 -4
- package/skills/keiyaku-akuma/SKILL.md +25 -11
- package/skills/keiyaku-task/SKILL.md +17 -8
- package/skills/keiyaku-workflow/SKILL.md +58 -9
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StringTailBuffer } from "../string-tail-buffer.js";
|
|
2
2
|
import { SUBAGENT_SESSION_VERSION, } from "../session.js";
|
|
3
|
-
import { SubagentFailure, } from "../types.js";
|
|
3
|
+
import { OUTCOME_ERROR_VERSION, SubagentFailure, } from "../types.js";
|
|
4
|
+
import { isProviderTerminalError, } from "./provider-adapter.js";
|
|
4
5
|
import { renderCapturedText } from "./runtime.js";
|
|
5
6
|
export function createOutcomeState(maxCaptureChars) {
|
|
6
7
|
return {
|
|
@@ -63,7 +64,15 @@ export function failFromFailEvent(shared, state, failEvent) {
|
|
|
63
64
|
exitCode: failEvent.exitCode ?? null,
|
|
64
65
|
}, state.finalMessageCandidate, failEvent.diagnostics ?? diagnostics);
|
|
65
66
|
}
|
|
66
|
-
export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
67
|
+
export function classifyFailure(shared, state, error, idleTimedOut, transportFailure, policyBudgetExceeded = false) {
|
|
68
|
+
if (policyBudgetExceeded) {
|
|
69
|
+
return failWithError(shared, state, {
|
|
70
|
+
code: "SUBAGENT_POLICY_BUDGET",
|
|
71
|
+
message: `${shared.terms.provider} execution policy budget expired`,
|
|
72
|
+
timeoutMs: shared.terms.executionTimeoutMs,
|
|
73
|
+
exitCode: null,
|
|
74
|
+
}, state.finalMessageCandidate);
|
|
75
|
+
}
|
|
67
76
|
if (shared.dismissed || shared.externallyAborted) {
|
|
68
77
|
return mintOutcome({
|
|
69
78
|
status: "dismissed",
|
|
@@ -74,6 +83,18 @@ export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
|
74
83
|
warnings: [...state.warnings],
|
|
75
84
|
});
|
|
76
85
|
}
|
|
86
|
+
if (transportFailure) {
|
|
87
|
+
const message = transportFailure instanceof Error ? transportFailure.message : `${shared.terms.provider} session transport probe failed`;
|
|
88
|
+
const timeoutMs = isProviderTerminalError(transportFailure) && transportFailure.fact.kind === "failed"
|
|
89
|
+
? transportFailure.fact.timeoutMs
|
|
90
|
+
: shared.terms.idleTimeoutMs;
|
|
91
|
+
return failWithError(shared, state, {
|
|
92
|
+
code: "SUBAGENT_TRANSPORT_ERROR",
|
|
93
|
+
message,
|
|
94
|
+
timeoutMs,
|
|
95
|
+
exitCode: null,
|
|
96
|
+
}, state.finalMessageCandidate);
|
|
97
|
+
}
|
|
77
98
|
if (idleTimedOut) {
|
|
78
99
|
return failWithError(shared, state, {
|
|
79
100
|
code: "SUBAGENT_TIMEOUT",
|
|
@@ -82,13 +103,55 @@ export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
|
82
103
|
exitCode: null,
|
|
83
104
|
}, state.finalMessageCandidate);
|
|
84
105
|
}
|
|
106
|
+
return classifyExecutionFailure(shared, state, error);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A rejected graceful settlement is terminal evidence, not an outcome intent.
|
|
110
|
+
* In particular, dismiss/external-cancel intent must not downgrade it to a
|
|
111
|
+
* clean dismissed result.
|
|
112
|
+
*/
|
|
113
|
+
export function classifySettlementFailure(shared, state, error) {
|
|
114
|
+
return classifyExecutionFailure(shared, state, error);
|
|
115
|
+
}
|
|
116
|
+
function classifyFromFailureFact(shared, state, fact) {
|
|
117
|
+
return failWithError(shared, state, {
|
|
118
|
+
code: fact.code,
|
|
119
|
+
message: fact.message,
|
|
120
|
+
timeoutMs: fact.timeoutMs,
|
|
121
|
+
exitCode: fact.exitCode,
|
|
122
|
+
...(fact.publicCause ? { publicCause: fact.publicCause } : {}),
|
|
123
|
+
}, state.finalMessageCandidate ?? fact.message, fact.diagnostics || renderCapturedText(state.diagnosticsBuffer), fact.output || renderCapturedText(state.outputBuffer));
|
|
124
|
+
}
|
|
125
|
+
function classifyFromAbortFact(shared, state, fact) {
|
|
126
|
+
// Abort without dismiss/external-cancel remains failed truth (historical bytes).
|
|
127
|
+
appendThrownMessage(state.diagnosticsBuffer, fact.message);
|
|
128
|
+
return failWithError(shared, state, {
|
|
129
|
+
code: "SUBAGENT_EXEC_ERROR",
|
|
130
|
+
message: fact.message,
|
|
131
|
+
timeoutMs: null,
|
|
132
|
+
exitCode: null,
|
|
133
|
+
}, state.finalMessageCandidate ?? fact.message);
|
|
134
|
+
}
|
|
135
|
+
function classifyExecutionFailure(shared, state, error) {
|
|
136
|
+
if (isProviderTerminalError(error)) {
|
|
137
|
+
if (error.fact.kind === "aborted") {
|
|
138
|
+
return classifyFromAbortFact(shared, state, error.fact);
|
|
139
|
+
}
|
|
140
|
+
return classifyFromFailureFact(shared, state, error.fact);
|
|
141
|
+
}
|
|
85
142
|
if (error instanceof SubagentFailure) {
|
|
86
|
-
return
|
|
143
|
+
return classifyFromFailureFact(shared, state, {
|
|
144
|
+
kind: "failed",
|
|
87
145
|
code: error.code,
|
|
88
146
|
message: error.message,
|
|
89
147
|
timeoutMs: error.timeoutMs,
|
|
90
148
|
exitCode: error.exitCode,
|
|
91
|
-
|
|
149
|
+
diagnostics: error.diagnostics,
|
|
150
|
+
output: error.output,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
154
|
+
return classifyFromAbortFact(shared, state, { kind: "aborted", message: error.message });
|
|
92
155
|
}
|
|
93
156
|
const message = error instanceof Error ? error.message : `Unknown ${shared.terms.provider} exec error`;
|
|
94
157
|
appendThrownMessage(state.diagnosticsBuffer, message);
|
|
@@ -102,7 +165,7 @@ export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
|
102
165
|
export function failWithError(shared, state, error, finalMessage, diagnostics = renderCapturedText(state.diagnosticsBuffer), output = renderCapturedText(state.outputBuffer)) {
|
|
103
166
|
return mintOutcome({
|
|
104
167
|
status: "failed",
|
|
105
|
-
error,
|
|
168
|
+
error: { version: OUTCOME_ERROR_VERSION, ...error },
|
|
106
169
|
finalMessage: finalMessage ?? error.message,
|
|
107
170
|
output,
|
|
108
171
|
diagnostics,
|
|
@@ -2,9 +2,10 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { FlowError } from "../../flow-error.js";
|
|
3
3
|
import { createEventChannel } from "./event-channel.js";
|
|
4
4
|
import { overflowMarkerFromDropped, prepareAgentEventForPersistence, } from "./execution-handle.js";
|
|
5
|
-
import { classifyFailure, completeOutcome, createOutcomeState, failFromFailEvent, failWithError, processEvent, renderOutcomeCapturedText, } from "./outcome.js";
|
|
5
|
+
import { classifyFailure, classifySettlementFailure, completeOutcome, createOutcomeState, failFromFailEvent, failWithError, processEvent, renderOutcomeCapturedText, } from "./outcome.js";
|
|
6
6
|
import { startLiveProjection } from "./router.js";
|
|
7
7
|
import { createAbortError } from "./runtime.js";
|
|
8
|
+
const POLICY_BUDGET_CLEANUP_GRACE_MS = 5_000;
|
|
8
9
|
export function call(terms, options) {
|
|
9
10
|
return createProjection(terms, undefined, options);
|
|
10
11
|
}
|
|
@@ -12,17 +13,7 @@ export function revive(terms, options) {
|
|
|
12
13
|
return createProjection(terms, terms, options);
|
|
13
14
|
}
|
|
14
15
|
function createProjection(terms, reviveTerms, options) {
|
|
15
|
-
|
|
16
|
-
case "pi":
|
|
17
|
-
case "claude-agent-sdk":
|
|
18
|
-
case "codex-app-server":
|
|
19
|
-
case "opencode-sdk":
|
|
20
|
-
return createSteerableProjection(terms, reviveTerms, options);
|
|
21
|
-
case "codex-sdk":
|
|
22
|
-
return createReplayProjection(terms, reviveTerms, options);
|
|
23
|
-
default:
|
|
24
|
-
return assertNever(terms);
|
|
25
|
-
}
|
|
16
|
+
return createSteerableProjection(terms, reviveTerms, options);
|
|
26
17
|
}
|
|
27
18
|
function createSteerableProjection(terms, reviveTerms, options) {
|
|
28
19
|
const shared = createProjectionState(terms, reviveTerms, options);
|
|
@@ -84,31 +75,6 @@ function createSteerableProjection(terms, reviveTerms, options) {
|
|
|
84
75
|
},
|
|
85
76
|
};
|
|
86
77
|
}
|
|
87
|
-
function createReplayProjection(terms, reviveTerms, options) {
|
|
88
|
-
const shared = createProjectionState(terms, reviveTerms, options);
|
|
89
|
-
shared.onLive = (live) => {
|
|
90
|
-
shared.live = live;
|
|
91
|
-
};
|
|
92
|
-
const outcome = settleProjection(shared);
|
|
93
|
-
return {
|
|
94
|
-
mode: "replay",
|
|
95
|
-
get id() {
|
|
96
|
-
return shared.id;
|
|
97
|
-
},
|
|
98
|
-
get events() {
|
|
99
|
-
return shared.publicEvents.iterable;
|
|
100
|
-
},
|
|
101
|
-
get outcome() {
|
|
102
|
-
return outcome;
|
|
103
|
-
},
|
|
104
|
-
abort(mode) {
|
|
105
|
-
return abortProjection(shared, mode);
|
|
106
|
-
},
|
|
107
|
-
dismiss() {
|
|
108
|
-
dismissProjection(shared);
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
78
|
function createProjectionState(terms, reviveTerms, options) {
|
|
113
79
|
const shared = {
|
|
114
80
|
id: randomUUID(),
|
|
@@ -129,9 +95,7 @@ function createProjectionState(terms, reviveTerms, options) {
|
|
|
129
95
|
if (terms.signal) {
|
|
130
96
|
const listener = () => {
|
|
131
97
|
shared.externallyAborted = true;
|
|
132
|
-
|
|
133
|
-
shared.lifecycleAbort.abort(terms.signal?.reason);
|
|
134
|
-
}
|
|
98
|
+
requestControlledGracefulAbort(shared, terms.signal?.reason);
|
|
135
99
|
};
|
|
136
100
|
terms.signal.addEventListener("abort", listener, { once: true });
|
|
137
101
|
if (terms.signal.aborted) {
|
|
@@ -144,20 +108,17 @@ function dismissProjection(shared) {
|
|
|
144
108
|
if (shared.dismissed || shared.terminal)
|
|
145
109
|
return;
|
|
146
110
|
shared.dismissed = true;
|
|
147
|
-
|
|
148
|
-
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec dismissed`));
|
|
149
|
-
}
|
|
150
|
-
requestDismissAbort(shared.live);
|
|
111
|
+
requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec dismissed`));
|
|
151
112
|
}
|
|
152
113
|
async function abortProjection(shared, mode = "graceful") {
|
|
153
114
|
shared.explicitlyAborted = true;
|
|
154
|
-
if (!shared.lifecycleAbort.signal.aborted) {
|
|
155
|
-
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
156
|
-
}
|
|
157
115
|
if (mode !== "force") {
|
|
158
|
-
await shared.
|
|
116
|
+
await requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
159
117
|
return;
|
|
160
118
|
}
|
|
119
|
+
if (!shared.lifecycleAbort.signal.aborted) {
|
|
120
|
+
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
121
|
+
}
|
|
161
122
|
shared.forceAbort ??= (async () => {
|
|
162
123
|
const live = shared.live ?? (shared.terminal ? undefined : await new Promise((resolve) => {
|
|
163
124
|
shared.forceWaiters.add(resolve);
|
|
@@ -171,14 +132,44 @@ function resolveForceWaiters(shared, live) {
|
|
|
171
132
|
resolve(live);
|
|
172
133
|
shared.forceWaiters.clear();
|
|
173
134
|
}
|
|
174
|
-
function
|
|
175
|
-
if (
|
|
176
|
-
return;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.
|
|
135
|
+
function requestControlledGracefulAbort(shared, reason) {
|
|
136
|
+
if (shared.gracefulAbort)
|
|
137
|
+
return shared.gracefulAbort;
|
|
138
|
+
const live = shared.live;
|
|
139
|
+
if (!live) {
|
|
140
|
+
if (!shared.lifecycleAbort.signal.aborted)
|
|
141
|
+
shared.lifecycleAbort.abort(reason);
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
shared.gracefulAbort = (async () => {
|
|
145
|
+
try {
|
|
146
|
+
await live.abort("graceful");
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
if (!shared.lifecycleAbort.signal.aborted)
|
|
150
|
+
shared.lifecycleAbort.abort(reason);
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
// Dismiss, timeout, and external cancellation are outcome-driven controls;
|
|
154
|
+
// keep their rejection observed while explicit abort still receives it.
|
|
155
|
+
shared.gracefulAbort.catch(() => undefined);
|
|
156
|
+
return shared.gracefulAbort;
|
|
180
157
|
}
|
|
181
|
-
function
|
|
158
|
+
function requestPolicyBudgetCleanup(shared, reason) {
|
|
159
|
+
const graceful = requestControlledGracefulAbort(shared, reason);
|
|
160
|
+
const force = () => {
|
|
161
|
+
void shared.live?.abort("force").catch(() => undefined);
|
|
162
|
+
};
|
|
163
|
+
const cleanupTimeout = setTimeout(force, POLICY_BUDGET_CLEANUP_GRACE_MS);
|
|
164
|
+
cleanupTimeout.unref?.();
|
|
165
|
+
void graceful.then(() => clearTimeout(cleanupTimeout), () => {
|
|
166
|
+
clearTimeout(cleanupTimeout);
|
|
167
|
+
force();
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, knownActiveTools, observerEnabled) {
|
|
171
|
+
if (shared.terminal)
|
|
172
|
+
return;
|
|
182
173
|
const prepared = prepareAgentEventForPersistence(event);
|
|
183
174
|
if (observerEnabled.value && shared.observer) {
|
|
184
175
|
try {
|
|
@@ -197,24 +188,63 @@ function deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, obse
|
|
|
197
188
|
}
|
|
198
189
|
}
|
|
199
190
|
shared.publicEvents.push(event);
|
|
191
|
+
if (event.type === "activity") {
|
|
192
|
+
if (event.phase === "started")
|
|
193
|
+
knownActiveTools.add(event.id);
|
|
194
|
+
if (event.phase === "completed")
|
|
195
|
+
knownActiveTools.delete(event.id);
|
|
196
|
+
}
|
|
200
197
|
refreshIdleTimeout();
|
|
201
198
|
processEvent(state, event);
|
|
202
199
|
}
|
|
203
200
|
async function settleProjection(shared) {
|
|
204
201
|
const state = createOutcomeState(shared.terms.maxCaptureChars);
|
|
205
202
|
let idleTimedOut = false;
|
|
203
|
+
let transportFailure;
|
|
204
|
+
let policyBudgetExceeded = false;
|
|
205
|
+
const knownActiveTools = new Set();
|
|
206
206
|
let abortRequested = false;
|
|
207
207
|
const observerEnabled = { value: shared.observer !== undefined };
|
|
208
208
|
let idleTimeout;
|
|
209
|
+
let executionTimeout;
|
|
210
|
+
let liveDriver;
|
|
211
|
+
let probeInFlight;
|
|
212
|
+
let resolvePolicyBudget;
|
|
213
|
+
const policyBudget = new Promise((resolve) => {
|
|
214
|
+
resolvePolicyBudget = resolve;
|
|
215
|
+
});
|
|
209
216
|
const refreshIdleTimeout = () => {
|
|
217
|
+
if (shared.terminal)
|
|
218
|
+
return;
|
|
210
219
|
if (idleTimeout)
|
|
211
220
|
clearTimeout(idleTimeout);
|
|
212
221
|
idleTimeout = setTimeout(() => {
|
|
222
|
+
if (knownActiveTools.size > 0) {
|
|
223
|
+
if (!liveDriver?.probe || probeInFlight)
|
|
224
|
+
return;
|
|
225
|
+
probeInFlight = liveDriver.probe()
|
|
226
|
+
.then(() => refreshIdleTimeout())
|
|
227
|
+
.catch((error) => {
|
|
228
|
+
transportFailure = error;
|
|
229
|
+
return requestControlledGracefulAbort(shared, error);
|
|
230
|
+
})
|
|
231
|
+
.finally(() => {
|
|
232
|
+
probeInFlight = undefined;
|
|
233
|
+
});
|
|
234
|
+
probeInFlight.catch(() => undefined);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
213
237
|
idleTimedOut = true;
|
|
214
|
-
shared
|
|
238
|
+
requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec idle timed out`));
|
|
215
239
|
}, shared.terms.idleTimeoutMs);
|
|
216
240
|
idleTimeout.unref?.();
|
|
217
241
|
};
|
|
242
|
+
executionTimeout = setTimeout(() => {
|
|
243
|
+
policyBudgetExceeded = true;
|
|
244
|
+
requestPolicyBudgetCleanup(shared, createAbortError(`${shared.terms.provider} execution policy budget expired`));
|
|
245
|
+
resolvePolicyBudget();
|
|
246
|
+
}, shared.terms.executionTimeoutMs);
|
|
247
|
+
executionTimeout.unref?.();
|
|
218
248
|
refreshIdleTimeout();
|
|
219
249
|
const requestLiveAbort = () => {
|
|
220
250
|
if (shared.explicitlyAborted)
|
|
@@ -222,89 +252,114 @@ async function settleProjection(shared) {
|
|
|
222
252
|
if (abortRequested)
|
|
223
253
|
return;
|
|
224
254
|
abortRequested = true;
|
|
225
|
-
|
|
255
|
+
requestControlledGracefulAbort(shared, shared.lifecycleAbort.signal.reason);
|
|
226
256
|
};
|
|
227
257
|
shared.lifecycleAbort.signal.addEventListener("abort", requestLiveAbort, { once: true });
|
|
228
|
-
|
|
229
|
-
const live = await startLiveProjection(shared.terms, shared.lifecycleAbort.signal, shared.reviveTerms, refreshIdleTimeout, shared.observer);
|
|
230
|
-
shared.onLive(live);
|
|
231
|
-
resolveForceWaiters(shared, live);
|
|
232
|
-
if (shared.lifecycleAbort.signal.aborted) {
|
|
233
|
-
requestLiveAbort();
|
|
234
|
-
}
|
|
258
|
+
const providerSettlement = (async () => {
|
|
235
259
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
260
|
+
const live = await startLiveProjection(shared.terms, shared.lifecycleAbort.signal, shared.reviveTerms, refreshIdleTimeout, shared.observer);
|
|
261
|
+
liveDriver = live;
|
|
262
|
+
shared.onLive(live);
|
|
263
|
+
resolveForceWaiters(shared, live);
|
|
264
|
+
if (shared.lifecycleAbort.signal.aborted) {
|
|
265
|
+
requestLiveAbort();
|
|
238
266
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
type: "fail",
|
|
244
|
-
code: "PROJECTION_STATE_ERROR",
|
|
245
|
-
message: error.message,
|
|
246
|
-
});
|
|
247
|
-
if (event)
|
|
248
|
-
deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, observerEnabled);
|
|
267
|
+
try {
|
|
268
|
+
for await (const event of live.events) {
|
|
269
|
+
deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, knownActiveTools, observerEnabled);
|
|
270
|
+
}
|
|
249
271
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
catch (error) {
|
|
273
|
+
if (error instanceof Error && error.code === "PROJECTION_STATE_ERROR") {
|
|
274
|
+
const event = live.mintEvent({
|
|
275
|
+
type: "fail",
|
|
276
|
+
code: "PROJECTION_STATE_ERROR",
|
|
277
|
+
message: error.message,
|
|
278
|
+
});
|
|
279
|
+
if (event)
|
|
280
|
+
deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, knownActiveTools, observerEnabled);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const event = live.mintEvent({
|
|
284
|
+
type: "diagnostic",
|
|
285
|
+
text: `pump error: ${String(error)}`,
|
|
286
|
+
});
|
|
287
|
+
if (event)
|
|
288
|
+
deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, knownActiveTools, observerEnabled);
|
|
289
|
+
}
|
|
257
290
|
}
|
|
291
|
+
const completionResult = await live.completion.then((value) => ({ ok: true, value }), (error) => ({ ok: false, error }));
|
|
292
|
+
const completionOutcome = completionResult.ok ? completionResult.value : undefined;
|
|
293
|
+
// Outcome classification is the terminal publication boundary. A
|
|
294
|
+
// controlled abort may let the provider run settle before its graceful
|
|
295
|
+
// cleanup promise does, so prove that shared settlement before publishing
|
|
296
|
+
// dismissed, failed-for-another-reason, or completed truth.
|
|
297
|
+
const gracefulResult = shared.gracefulAbort
|
|
298
|
+
? await shared.gracefulAbort.then(() => ({ ok: true }), (error) => ({ ok: false, error }))
|
|
299
|
+
: undefined;
|
|
300
|
+
if (gracefulResult && !gracefulResult.ok && !transportFailure) {
|
|
301
|
+
return classifySettlementFailure(shared, state, gracefulResult.error);
|
|
302
|
+
}
|
|
303
|
+
if (policyBudgetExceeded || transportFailure) {
|
|
304
|
+
return classifyFailure(shared, state, completionResult.ok ? undefined : completionResult.error, idleTimedOut, transportFailure, policyBudgetExceeded);
|
|
305
|
+
}
|
|
306
|
+
if (state.failEvent) {
|
|
307
|
+
return failFromFailEvent(shared, state, state.failEvent);
|
|
308
|
+
}
|
|
309
|
+
if (!completionResult.ok) {
|
|
310
|
+
return classifyFailure(shared, state, completionResult.error, idleTimedOut, transportFailure, policyBudgetExceeded);
|
|
311
|
+
}
|
|
312
|
+
if (shared.lifecycleAbort.signal.aborted) {
|
|
313
|
+
return classifyFailure(shared, state, shared.lifecycleAbort.signal.reason, idleTimedOut, transportFailure, policyBudgetExceeded);
|
|
314
|
+
}
|
|
315
|
+
if (!state.doneEvent && !completionOutcome) {
|
|
316
|
+
return failWithError(shared, state, {
|
|
317
|
+
code: "SUBAGENT_EXEC_ERROR",
|
|
318
|
+
message: `${shared.terms.provider} exec ended before completion`,
|
|
319
|
+
timeoutMs: null,
|
|
320
|
+
exitCode: null,
|
|
321
|
+
}, state.finalMessageCandidate);
|
|
322
|
+
}
|
|
323
|
+
const finalMessage = state.doneEvent?.finalMessage ??
|
|
324
|
+
completionOutcome?.finalMessage ??
|
|
325
|
+
state.finalMessageCandidate ??
|
|
326
|
+
renderOutcomeCapturedText(state.outputBuffer).trim();
|
|
327
|
+
const session = state.doneEvent?.session ?? completionOutcome?.session;
|
|
328
|
+
if (!session) {
|
|
329
|
+
return failWithError(shared, state, {
|
|
330
|
+
code: "SUBAGENT_EXEC_ERROR",
|
|
331
|
+
message: `${shared.terms.provider} exec ended without a session handle`,
|
|
332
|
+
timeoutMs: null,
|
|
333
|
+
exitCode: null,
|
|
334
|
+
}, finalMessage);
|
|
335
|
+
}
|
|
336
|
+
return completeOutcome(shared, state, finalMessage, session);
|
|
258
337
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (!completionResult.ok) {
|
|
265
|
-
return classifyFailure(shared, state, completionResult.error, idleTimedOut);
|
|
266
|
-
}
|
|
267
|
-
if (shared.lifecycleAbort.signal.aborted) {
|
|
268
|
-
return classifyFailure(shared, state, shared.lifecycleAbort.signal.reason, idleTimedOut);
|
|
269
|
-
}
|
|
270
|
-
if (!state.doneEvent && !completionOutcome) {
|
|
271
|
-
return failWithError(shared, state, {
|
|
272
|
-
code: "SUBAGENT_EXEC_ERROR",
|
|
273
|
-
message: `${shared.terms.provider} exec ended before completion`,
|
|
274
|
-
timeoutMs: null,
|
|
275
|
-
exitCode: null,
|
|
276
|
-
}, state.finalMessageCandidate);
|
|
277
|
-
}
|
|
278
|
-
const finalMessage = state.doneEvent?.finalMessage ??
|
|
279
|
-
completionOutcome?.finalMessage ??
|
|
280
|
-
state.finalMessageCandidate ??
|
|
281
|
-
renderOutcomeCapturedText(state.outputBuffer).trim();
|
|
282
|
-
const session = state.doneEvent?.session ?? completionOutcome?.session;
|
|
283
|
-
if (!session) {
|
|
284
|
-
return failWithError(shared, state, {
|
|
285
|
-
code: "SUBAGENT_EXEC_ERROR",
|
|
286
|
-
message: `${shared.terms.provider} exec ended without a session handle`,
|
|
287
|
-
timeoutMs: null,
|
|
288
|
-
exitCode: null,
|
|
289
|
-
}, finalMessage);
|
|
290
|
-
}
|
|
291
|
-
return completeOutcome(shared, state, finalMessage, session);
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
if (error instanceof FlowError) {
|
|
295
|
-
throw error;
|
|
338
|
+
catch (error) {
|
|
339
|
+
if (error instanceof FlowError) {
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
return classifyFailure(shared, state, error, idleTimedOut, transportFailure, policyBudgetExceeded);
|
|
296
343
|
}
|
|
297
|
-
|
|
344
|
+
})();
|
|
345
|
+
providerSettlement.catch(() => undefined);
|
|
346
|
+
try {
|
|
347
|
+
const settled = await Promise.race([
|
|
348
|
+
providerSettlement.then((outcome) => ({ kind: "provider", outcome })),
|
|
349
|
+
policyBudget.then(() => ({ kind: "policy-budget" })),
|
|
350
|
+
]);
|
|
351
|
+
return settled.kind === "provider"
|
|
352
|
+
? settled.outcome
|
|
353
|
+
: classifyFailure(shared, state, undefined, idleTimedOut, transportFailure, true);
|
|
298
354
|
}
|
|
299
355
|
finally {
|
|
300
356
|
if (idleTimeout)
|
|
301
357
|
clearTimeout(idleTimeout);
|
|
358
|
+
if (executionTimeout)
|
|
359
|
+
clearTimeout(executionTimeout);
|
|
302
360
|
shared.lifecycleAbort.signal.removeEventListener("abort", requestLiveAbort);
|
|
303
361
|
shared.terminal = true;
|
|
304
362
|
resolveForceWaiters(shared, undefined);
|
|
305
363
|
shared.publicEvents.close();
|
|
306
364
|
}
|
|
307
365
|
}
|
|
308
|
-
function assertNever(_value) {
|
|
309
|
-
throw new Error("Unhandled provider");
|
|
310
|
-
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SubagentFailure, } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Typed rejection carrier for failed/aborted adapter settlement.
|
|
4
|
+
* Abort keeps name "AbortError" so existing name checks and CLI exit codes hold.
|
|
5
|
+
*/
|
|
6
|
+
export class ProviderTerminalError extends Error {
|
|
7
|
+
fact;
|
|
8
|
+
constructor(fact, options) {
|
|
9
|
+
super(fact.message, options?.cause === undefined ? undefined : { cause: options.cause });
|
|
10
|
+
this.name = fact.kind === "aborted" ? "AbortError" : "ProviderTerminalError";
|
|
11
|
+
this.fact = fact;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function isProviderTerminalError(error) {
|
|
15
|
+
return error instanceof ProviderTerminalError;
|
|
16
|
+
}
|
|
17
|
+
export function createProviderFailure(message, options = {}) {
|
|
18
|
+
return new ProviderTerminalError({
|
|
19
|
+
kind: "failed",
|
|
20
|
+
code: options.code ?? "SUBAGENT_EXEC_ERROR",
|
|
21
|
+
message,
|
|
22
|
+
timeoutMs: options.timeoutMs ?? null,
|
|
23
|
+
exitCode: options.exitCode ?? null,
|
|
24
|
+
...(options.diagnostics !== undefined ? { diagnostics: options.diagnostics } : {}),
|
|
25
|
+
...(options.output !== undefined ? { output: options.output } : {}),
|
|
26
|
+
...(options.publicCause !== undefined ? { publicCause: options.publicCause } : {}),
|
|
27
|
+
}, options.cause === undefined ? undefined : { cause: options.cause });
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Abort-fact constructor. Abort semantics for every live adapter:
|
|
31
|
+
* - abort("graceful") requests provider-native interrupt and keeps local signals
|
|
32
|
+
* open until native settlement proof (or bounded abort-settlement timeout);
|
|
33
|
+
* - abort("force") must establish zero later provider side effects or reject;
|
|
34
|
+
* - run settlement for a requested abort exits as kind "aborted" (name AbortError).
|
|
35
|
+
*/
|
|
36
|
+
export function createAbortError(message, cause) {
|
|
37
|
+
return new ProviderTerminalError({ kind: "aborted", message }, cause === undefined ? undefined : { cause });
|
|
38
|
+
}
|
|
39
|
+
/** Normalize any thrown value into the typed failure/abort egress fact. */
|
|
40
|
+
export function toProviderTerminalError(error) {
|
|
41
|
+
if (error instanceof ProviderTerminalError)
|
|
42
|
+
return error;
|
|
43
|
+
if (error instanceof SubagentFailure) {
|
|
44
|
+
return new ProviderTerminalError({
|
|
45
|
+
kind: "failed",
|
|
46
|
+
code: error.code,
|
|
47
|
+
message: error.message,
|
|
48
|
+
timeoutMs: error.timeoutMs,
|
|
49
|
+
exitCode: error.exitCode,
|
|
50
|
+
diagnostics: error.diagnostics,
|
|
51
|
+
output: error.output,
|
|
52
|
+
}, { cause: error });
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
55
|
+
return new ProviderTerminalError({ kind: "aborted", message: error.message }, { cause: error });
|
|
56
|
+
}
|
|
57
|
+
return createProviderFailure(error instanceof Error ? error.message : String(error), { cause: error instanceof Error ? error : undefined });
|
|
58
|
+
}
|