@astrosheep/keiyaku 2.9.2 → 2.9.4
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 +13 -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 +25 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +47 -4
- package/build/agents/harness/projection.js +42 -59
- 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 +50 -53
- package/build/agents/providers/codex-app-server/events.js +67 -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/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 +8 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/arc/handler.js +7 -1
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +34 -7
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/petition/handler.js +4 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +58 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +7 -2
- 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/skills/handler.js +1 -1
- package/build/cli/commands/task/add/handler.js +5 -13
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/ls/handler.js +3 -5
- 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/stop/handler.js +4 -8
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/update/handler.js +4 -8
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +4 -11
- package/build/cli/index.js +57 -83
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/parse-flags.js +14 -5
- package/build/cli/parse-metadata.js +3 -3
- package/build/cli/parse-selectors.js +1 -1
- package/build/cli/parse.js +21 -0
- package/build/cli/projection-address.js +7 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- 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 +55 -12
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +3 -0
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +37 -14
- package/build/cli/render/success-response.js +77 -0
- package/build/cli/render/task.js +54 -14
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +58 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +38 -36
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +1 -1
- 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 +135 -18
- package/build/core/arc.js +19 -67
- 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 +21 -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 +20 -3
- package/build/core/draft.js +123 -16
- 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/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 +2 -38
- package/build/core/projection/generation/model.js +42 -1
- 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} +19 -49
- 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} +5 -3
- 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} +18 -3
- package/build/core/projection/generation/store.js +2 -2
- package/build/core/projection/generation/transitions.js +1 -1
- 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} +14 -19
- 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} +2 -57
- 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} +1 -1
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
- package/build/core/projection/projection-terminal-failure.js +104 -0
- package/build/core/projection/projection-wait.js +278 -0
- package/build/core/projection/projection-wake.js +203 -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 +426 -99
- package/build/core/scope.js +143 -66
- package/build/core/seal.js +139 -35
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
- 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} +22 -18
- 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} +1 -1
- package/build/core/{petition.js → settlement/petition.js} +12 -10
- 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 +295 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/status/board.js +24 -23
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +3 -0
- package/build/core/task/board.js +40 -4
- package/build/core/task/commands.js +30 -21
- package/build/core/task/index.js +12 -0
- package/build/core/task/settlement-git.js +157 -65
- package/build/core/task/settlement-policy.js +54 -24
- package/build/core/task/task-contract.js +370 -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} +92 -29
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -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 +5 -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 +85 -39
- package/build/fs/durability.js +27 -0
- 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/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 +3 -3
- package/build/keiyaku.js +2 -36
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +3 -2
- package/skills/keiyaku-akuma/SKILL.md +10 -6
- package/skills/keiyaku-task/SKILL.md +1 -1
- package/skills/keiyaku-workflow/SKILL.md +25 -4
- 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 {
|
|
@@ -82,13 +83,55 @@ export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
|
82
83
|
exitCode: null,
|
|
83
84
|
}, state.finalMessageCandidate);
|
|
84
85
|
}
|
|
86
|
+
return classifyExecutionFailure(shared, state, error);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A rejected graceful settlement is terminal evidence, not an outcome intent.
|
|
90
|
+
* In particular, dismiss/external-cancel intent must not downgrade it to a
|
|
91
|
+
* clean dismissed result.
|
|
92
|
+
*/
|
|
93
|
+
export function classifySettlementFailure(shared, state, error) {
|
|
94
|
+
return classifyExecutionFailure(shared, state, error);
|
|
95
|
+
}
|
|
96
|
+
function classifyFromFailureFact(shared, state, fact) {
|
|
97
|
+
return failWithError(shared, state, {
|
|
98
|
+
code: fact.code,
|
|
99
|
+
message: fact.message,
|
|
100
|
+
timeoutMs: fact.timeoutMs,
|
|
101
|
+
exitCode: fact.exitCode,
|
|
102
|
+
...(fact.publicCause ? { publicCause: fact.publicCause } : {}),
|
|
103
|
+
}, state.finalMessageCandidate ?? fact.message, fact.diagnostics || renderCapturedText(state.diagnosticsBuffer), fact.output || renderCapturedText(state.outputBuffer));
|
|
104
|
+
}
|
|
105
|
+
function classifyFromAbortFact(shared, state, fact) {
|
|
106
|
+
// Abort without dismiss/external-cancel remains failed truth (historical bytes).
|
|
107
|
+
appendThrownMessage(state.diagnosticsBuffer, fact.message);
|
|
108
|
+
return failWithError(shared, state, {
|
|
109
|
+
code: "SUBAGENT_EXEC_ERROR",
|
|
110
|
+
message: fact.message,
|
|
111
|
+
timeoutMs: null,
|
|
112
|
+
exitCode: null,
|
|
113
|
+
}, state.finalMessageCandidate ?? fact.message);
|
|
114
|
+
}
|
|
115
|
+
function classifyExecutionFailure(shared, state, error) {
|
|
116
|
+
if (isProviderTerminalError(error)) {
|
|
117
|
+
if (error.fact.kind === "aborted") {
|
|
118
|
+
return classifyFromAbortFact(shared, state, error.fact);
|
|
119
|
+
}
|
|
120
|
+
return classifyFromFailureFact(shared, state, error.fact);
|
|
121
|
+
}
|
|
85
122
|
if (error instanceof SubagentFailure) {
|
|
86
|
-
return
|
|
123
|
+
return classifyFromFailureFact(shared, state, {
|
|
124
|
+
kind: "failed",
|
|
87
125
|
code: error.code,
|
|
88
126
|
message: error.message,
|
|
89
127
|
timeoutMs: error.timeoutMs,
|
|
90
128
|
exitCode: error.exitCode,
|
|
91
|
-
|
|
129
|
+
diagnostics: error.diagnostics,
|
|
130
|
+
output: error.output,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
134
|
+
return classifyFromAbortFact(shared, state, { kind: "aborted", message: error.message });
|
|
92
135
|
}
|
|
93
136
|
const message = error instanceof Error ? error.message : `Unknown ${shared.terms.provider} exec error`;
|
|
94
137
|
appendThrownMessage(state.diagnosticsBuffer, message);
|
|
@@ -102,7 +145,7 @@ export function classifyFailure(shared, state, error, idleTimedOut) {
|
|
|
102
145
|
export function failWithError(shared, state, error, finalMessage, diagnostics = renderCapturedText(state.diagnosticsBuffer), output = renderCapturedText(state.outputBuffer)) {
|
|
103
146
|
return mintOutcome({
|
|
104
147
|
status: "failed",
|
|
105
|
-
error,
|
|
148
|
+
error: { version: OUTCOME_ERROR_VERSION, ...error },
|
|
106
149
|
finalMessage: finalMessage ?? error.message,
|
|
107
150
|
output,
|
|
108
151
|
diagnostics,
|
|
@@ -2,7 +2,7 @@ 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
8
|
export function call(terms, options) {
|
|
@@ -12,17 +12,7 @@ export function revive(terms, options) {
|
|
|
12
12
|
return createProjection(terms, terms, options);
|
|
13
13
|
}
|
|
14
14
|
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
|
-
}
|
|
15
|
+
return createSteerableProjection(terms, reviveTerms, options);
|
|
26
16
|
}
|
|
27
17
|
function createSteerableProjection(terms, reviveTerms, options) {
|
|
28
18
|
const shared = createProjectionState(terms, reviveTerms, options);
|
|
@@ -84,31 +74,6 @@ function createSteerableProjection(terms, reviveTerms, options) {
|
|
|
84
74
|
},
|
|
85
75
|
};
|
|
86
76
|
}
|
|
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
77
|
function createProjectionState(terms, reviveTerms, options) {
|
|
113
78
|
const shared = {
|
|
114
79
|
id: randomUUID(),
|
|
@@ -129,9 +94,7 @@ function createProjectionState(terms, reviveTerms, options) {
|
|
|
129
94
|
if (terms.signal) {
|
|
130
95
|
const listener = () => {
|
|
131
96
|
shared.externallyAborted = true;
|
|
132
|
-
|
|
133
|
-
shared.lifecycleAbort.abort(terms.signal?.reason);
|
|
134
|
-
}
|
|
97
|
+
requestControlledGracefulAbort(shared, terms.signal?.reason);
|
|
135
98
|
};
|
|
136
99
|
terms.signal.addEventListener("abort", listener, { once: true });
|
|
137
100
|
if (terms.signal.aborted) {
|
|
@@ -144,20 +107,17 @@ function dismissProjection(shared) {
|
|
|
144
107
|
if (shared.dismissed || shared.terminal)
|
|
145
108
|
return;
|
|
146
109
|
shared.dismissed = true;
|
|
147
|
-
|
|
148
|
-
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec dismissed`));
|
|
149
|
-
}
|
|
150
|
-
requestDismissAbort(shared.live);
|
|
110
|
+
requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec dismissed`));
|
|
151
111
|
}
|
|
152
112
|
async function abortProjection(shared, mode = "graceful") {
|
|
153
113
|
shared.explicitlyAborted = true;
|
|
154
|
-
if (!shared.lifecycleAbort.signal.aborted) {
|
|
155
|
-
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
156
|
-
}
|
|
157
114
|
if (mode !== "force") {
|
|
158
|
-
await shared.
|
|
115
|
+
await requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
159
116
|
return;
|
|
160
117
|
}
|
|
118
|
+
if (!shared.lifecycleAbort.signal.aborted) {
|
|
119
|
+
shared.lifecycleAbort.abort(createAbortError(`${shared.terms.provider} exec cancelled by client`));
|
|
120
|
+
}
|
|
161
121
|
shared.forceAbort ??= (async () => {
|
|
162
122
|
const live = shared.live ?? (shared.terminal ? undefined : await new Promise((resolve) => {
|
|
163
123
|
shared.forceWaiters.add(resolve);
|
|
@@ -171,12 +131,28 @@ function resolveForceWaiters(shared, live) {
|
|
|
171
131
|
resolve(live);
|
|
172
132
|
shared.forceWaiters.clear();
|
|
173
133
|
}
|
|
174
|
-
function
|
|
175
|
-
if (
|
|
176
|
-
return;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.
|
|
134
|
+
function requestControlledGracefulAbort(shared, reason) {
|
|
135
|
+
if (shared.gracefulAbort)
|
|
136
|
+
return shared.gracefulAbort;
|
|
137
|
+
const live = shared.live;
|
|
138
|
+
if (!live) {
|
|
139
|
+
if (!shared.lifecycleAbort.signal.aborted)
|
|
140
|
+
shared.lifecycleAbort.abort(reason);
|
|
141
|
+
return Promise.resolve();
|
|
142
|
+
}
|
|
143
|
+
shared.gracefulAbort = (async () => {
|
|
144
|
+
try {
|
|
145
|
+
await live.abort("graceful");
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
if (!shared.lifecycleAbort.signal.aborted)
|
|
149
|
+
shared.lifecycleAbort.abort(reason);
|
|
150
|
+
}
|
|
151
|
+
})();
|
|
152
|
+
// Dismiss, timeout, and external cancellation are outcome-driven controls;
|
|
153
|
+
// keep their rejection observed while explicit abort still receives it.
|
|
154
|
+
shared.gracefulAbort.catch(() => undefined);
|
|
155
|
+
return shared.gracefulAbort;
|
|
180
156
|
}
|
|
181
157
|
function deliverDriverEvent(shared, state, live, event, refreshIdleTimeout, observerEnabled) {
|
|
182
158
|
const prepared = prepareAgentEventForPersistence(event);
|
|
@@ -211,7 +187,7 @@ async function settleProjection(shared) {
|
|
|
211
187
|
clearTimeout(idleTimeout);
|
|
212
188
|
idleTimeout = setTimeout(() => {
|
|
213
189
|
idleTimedOut = true;
|
|
214
|
-
shared
|
|
190
|
+
requestControlledGracefulAbort(shared, createAbortError(`${shared.terms.provider} exec idle timed out`));
|
|
215
191
|
}, shared.terms.idleTimeoutMs);
|
|
216
192
|
idleTimeout.unref?.();
|
|
217
193
|
};
|
|
@@ -222,7 +198,7 @@ async function settleProjection(shared) {
|
|
|
222
198
|
if (abortRequested)
|
|
223
199
|
return;
|
|
224
200
|
abortRequested = true;
|
|
225
|
-
|
|
201
|
+
requestControlledGracefulAbort(shared, shared.lifecycleAbort.signal.reason);
|
|
226
202
|
};
|
|
227
203
|
shared.lifecycleAbort.signal.addEventListener("abort", requestLiveAbort, { once: true });
|
|
228
204
|
try {
|
|
@@ -258,6 +234,16 @@ async function settleProjection(shared) {
|
|
|
258
234
|
}
|
|
259
235
|
const completionResult = await live.completion.then((value) => ({ ok: true, value }), (error) => ({ ok: false, error }));
|
|
260
236
|
const completionOutcome = completionResult.ok ? completionResult.value : undefined;
|
|
237
|
+
// Outcome classification is the terminal publication boundary. A
|
|
238
|
+
// controlled abort may let the provider run settle before its graceful
|
|
239
|
+
// cleanup promise does, so prove that shared settlement before publishing
|
|
240
|
+
// dismissed, failed-for-another-reason, or completed truth.
|
|
241
|
+
const gracefulResult = shared.gracefulAbort
|
|
242
|
+
? await shared.gracefulAbort.then(() => ({ ok: true }), (error) => ({ ok: false, error }))
|
|
243
|
+
: undefined;
|
|
244
|
+
if (gracefulResult && !gracefulResult.ok) {
|
|
245
|
+
return classifySettlementFailure(shared, state, gracefulResult.error);
|
|
246
|
+
}
|
|
261
247
|
if (state.failEvent) {
|
|
262
248
|
return failFromFailEvent(shared, state, state.failEvent);
|
|
263
249
|
}
|
|
@@ -305,6 +291,3 @@ async function settleProjection(shared) {
|
|
|
305
291
|
shared.publicEvents.close();
|
|
306
292
|
}
|
|
307
293
|
}
|
|
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
|
+
}
|
|
@@ -1,30 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SUBAGENT_SESSION_VERSION, subagentSessionEnvelopeSchema, } from "../session.js";
|
|
3
|
-
import { startClaudeAgentSdk, claudeSessionSchema, } from "../providers/claude-agent-sdk/adapter.js";
|
|
4
|
-
import { startCodexAppServer, codexAppServerSessionSchema, } from "../providers/codex-app-server/adapter.js";
|
|
5
|
-
import { startCodexSdk, codexThreadSchema, } from "../providers/codex-sdk.js";
|
|
6
|
-
import { startOpencode, opencodeSessionSchema, } from "../providers/opencode-sdk/adapter.js";
|
|
7
|
-
import { startPi, piSessionSchema, } from "../providers/pi/adapter.js";
|
|
8
|
-
function admitResumeShape(provider, schema, session, resumePath) {
|
|
9
|
-
const envelopeResult = subagentSessionEnvelopeSchema.safeParse(session);
|
|
10
|
-
if (!envelopeResult.success) {
|
|
11
|
-
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' includes an invalid session envelope.`);
|
|
12
|
-
}
|
|
13
|
-
if (session.provider !== provider) {
|
|
14
|
-
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' was created with provider '${session.provider}', but the selected subagent resolves to '${provider}'. Cross-provider resume is not supported.`);
|
|
15
|
-
}
|
|
16
|
-
if (session.version !== SUBAGENT_SESSION_VERSION) {
|
|
17
|
-
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' uses unsupported session version '${session.version}' for provider '${session.provider}'.`);
|
|
18
|
-
}
|
|
19
|
-
const shapeResult = schema.safeParse(session.handle);
|
|
20
|
-
if (!shapeResult.success) {
|
|
21
|
-
throw new FlowError("INVALID_RESPONSE_PATH", `Resume path file '${resumePath}' includes an invalid session handle for provider '${session.provider}'.`);
|
|
22
|
-
}
|
|
23
|
-
return shapeResult.data;
|
|
24
|
-
}
|
|
25
|
-
function assertNever(_value) {
|
|
26
|
-
throw new Error("Unhandled provider");
|
|
27
|
-
}
|
|
1
|
+
import { getProviderRegistration } from "../providers/registry.js";
|
|
28
2
|
export async function startLiveProjection(terms, signal, reviveTerms, onIngress, observer) {
|
|
29
3
|
const onSyncCheckpoint = observer
|
|
30
4
|
? (control, checkpoint) => {
|
|
@@ -38,164 +12,14 @@ export async function startLiveProjection(terms, signal, reviveTerms, onIngress,
|
|
|
38
12
|
observer.onDeliveryOpportunity(control);
|
|
39
13
|
}
|
|
40
14
|
: undefined;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
onSyncCheckpoint,
|
|
52
|
-
onEvidence: terms.onEvidence,
|
|
53
|
-
onIngress,
|
|
54
|
-
initialTurn: terms.initialTurn,
|
|
55
|
-
loader: terms.loader,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
return startPi(terms.prompt, terms.workdir, {
|
|
59
|
-
model: terms.model,
|
|
60
|
-
thinkingLevel: terms.thinkingLevel,
|
|
61
|
-
signal,
|
|
62
|
-
appendSystemPromptOverride: terms.appendSystemPromptOverride,
|
|
63
|
-
onSyncCheckpoint,
|
|
64
|
-
onEvidence: terms.onEvidence,
|
|
65
|
-
onIngress,
|
|
66
|
-
initialTurn: terms.initialTurn,
|
|
67
|
-
loader: terms.loader,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
case "claude-agent-sdk": {
|
|
71
|
-
const claudeOptions = {
|
|
72
|
-
model: terms.model,
|
|
73
|
-
executable: terms.executable,
|
|
74
|
-
effort: terms.effort,
|
|
75
|
-
env: terms.env,
|
|
76
|
-
signal,
|
|
77
|
-
permissionMode: terms.permissionMode,
|
|
78
|
-
settingSources: terms.settingSources,
|
|
79
|
-
allowDangerouslySkipPermissions: terms.allowDangerouslySkipPermissions,
|
|
80
|
-
disallowedTools: terms.disallowedTools,
|
|
81
|
-
systemPrompt: terms.systemPrompt,
|
|
82
|
-
onSyncCheckpoint,
|
|
83
|
-
onEvidence: terms.onEvidence,
|
|
84
|
-
onIngress,
|
|
85
|
-
initialTurn: terms.initialTurn,
|
|
86
|
-
loader: terms.loader,
|
|
87
|
-
};
|
|
88
|
-
if (reviveTerms) {
|
|
89
|
-
const session = admitResumeShape("claude-agent-sdk", claudeSessionSchema, reviveTerms.session, reviveTerms.resumePath);
|
|
90
|
-
return startClaudeAgentSdk(terms.prompt, terms.workdir, {
|
|
91
|
-
...claudeOptions,
|
|
92
|
-
sessionId: session.sessionId,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
return startClaudeAgentSdk(terms.prompt, terms.workdir, claudeOptions);
|
|
96
|
-
}
|
|
97
|
-
case "codex-app-server": {
|
|
98
|
-
if (reviveTerms) {
|
|
99
|
-
const session = admitResumeShape("codex-app-server", codexAppServerSessionSchema, reviveTerms.session, reviveTerms.resumePath);
|
|
100
|
-
return startCodexAppServer(terms.prompt, terms.workdir, {
|
|
101
|
-
model: terms.model,
|
|
102
|
-
effort: terms.effort,
|
|
103
|
-
profile: terms.profile,
|
|
104
|
-
config: terms.config,
|
|
105
|
-
sandboxPolicy: terms.sandboxPolicy,
|
|
106
|
-
approvalPolicy: terms.approvalPolicy,
|
|
107
|
-
executable: terms.executable,
|
|
108
|
-
env: terms.env,
|
|
109
|
-
signal,
|
|
110
|
-
threadId: session.threadId,
|
|
111
|
-
codexHome: session.codexHome,
|
|
112
|
-
developerInstructions: terms.developerInstructions,
|
|
113
|
-
onSyncCheckpoint,
|
|
114
|
-
onDeliveryOpportunity,
|
|
115
|
-
onEvidence: terms.onEvidence,
|
|
116
|
-
onIngress,
|
|
117
|
-
initialTurn: terms.initialTurn,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
return startCodexAppServer(terms.prompt, terms.workdir, {
|
|
121
|
-
model: terms.model,
|
|
122
|
-
effort: terms.effort,
|
|
123
|
-
profile: terms.profile,
|
|
124
|
-
config: terms.config,
|
|
125
|
-
sandboxPolicy: terms.sandboxPolicy,
|
|
126
|
-
approvalPolicy: terms.approvalPolicy,
|
|
127
|
-
executable: terms.executable,
|
|
128
|
-
env: terms.env,
|
|
129
|
-
signal,
|
|
130
|
-
developerInstructions: terms.developerInstructions,
|
|
131
|
-
onSyncCheckpoint,
|
|
132
|
-
onDeliveryOpportunity,
|
|
133
|
-
onEvidence: terms.onEvidence,
|
|
134
|
-
onIngress,
|
|
135
|
-
initialTurn: terms.initialTurn,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
case "codex-sdk": {
|
|
139
|
-
if (reviveTerms) {
|
|
140
|
-
const session = admitResumeShape("codex-sdk", codexThreadSchema, reviveTerms.session, reviveTerms.resumePath);
|
|
141
|
-
return startCodexSdk(terms.prompt, terms.workdir, {
|
|
142
|
-
model: terms.model,
|
|
143
|
-
profile: terms.profile,
|
|
144
|
-
config: terms.config,
|
|
145
|
-
threadOptions: terms.threadOptions,
|
|
146
|
-
executable: terms.executable,
|
|
147
|
-
signal,
|
|
148
|
-
threadId: session.threadId,
|
|
149
|
-
onEvidence: terms.onEvidence,
|
|
150
|
-
onIngress,
|
|
151
|
-
initialTurn: terms.initialTurn,
|
|
152
|
-
codexConstructor: terms.codexConstructor,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
return startCodexSdk(terms.prompt, terms.workdir, {
|
|
156
|
-
model: terms.model,
|
|
157
|
-
profile: terms.profile,
|
|
158
|
-
config: terms.config,
|
|
159
|
-
threadOptions: terms.threadOptions,
|
|
160
|
-
executable: terms.executable,
|
|
161
|
-
signal,
|
|
162
|
-
onEvidence: terms.onEvidence,
|
|
163
|
-
onIngress,
|
|
164
|
-
initialTurn: terms.initialTurn,
|
|
165
|
-
codexConstructor: terms.codexConstructor,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
case "opencode-sdk": {
|
|
169
|
-
if (reviveTerms) {
|
|
170
|
-
const session = admitResumeShape("opencode-sdk", opencodeSessionSchema, reviveTerms.session, reviveTerms.resumePath);
|
|
171
|
-
return startOpencode(terms.prompt, terms.workdir, {
|
|
172
|
-
model: terms.model,
|
|
173
|
-
effort: terms.effort,
|
|
174
|
-
executable: terms.executable,
|
|
175
|
-
env: terms.env,
|
|
176
|
-
signal,
|
|
177
|
-
sessionId: session.sessionId,
|
|
178
|
-
onSyncCheckpoint,
|
|
179
|
-
onDeliveryOpportunity,
|
|
180
|
-
onEvidence: terms.onEvidence,
|
|
181
|
-
onIngress,
|
|
182
|
-
initialTurn: terms.initialTurn,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
return startOpencode(terms.prompt, terms.workdir, {
|
|
186
|
-
model: terms.model,
|
|
187
|
-
effort: terms.effort,
|
|
188
|
-
executable: terms.executable,
|
|
189
|
-
env: terms.env,
|
|
190
|
-
signal,
|
|
191
|
-
onSyncCheckpoint,
|
|
192
|
-
onDeliveryOpportunity,
|
|
193
|
-
onEvidence: terms.onEvidence,
|
|
194
|
-
onIngress,
|
|
195
|
-
initialTurn: terms.initialTurn,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
default:
|
|
199
|
-
return assertNever(terms);
|
|
200
|
-
}
|
|
15
|
+
const registration = getProviderRegistration(terms.provider);
|
|
16
|
+
return registration.startLive({
|
|
17
|
+
terms,
|
|
18
|
+
signal,
|
|
19
|
+
reviveTerms,
|
|
20
|
+
onSyncCheckpoint,
|
|
21
|
+
onDeliveryOpportunity,
|
|
22
|
+
onIngress,
|
|
23
|
+
observer,
|
|
24
|
+
});
|
|
201
25
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { getConfig } from "../../config/env.js";
|
|
3
3
|
import { DISABLE_SUBAGENT_SPAWN_ENV_KEY } from "../../config/env-keys.js";
|
|
4
|
+
export const PROVIDER_ABORT_SETTLEMENT_TIMEOUT_MS = 5_000;
|
|
4
5
|
export function sha256Utf8(value) {
|
|
5
6
|
const bytes = Buffer.from(value, "utf8");
|
|
6
7
|
return { sha256: createHash("sha256").update(bytes).digest("hex"), byteLength: bytes.byteLength };
|
|
@@ -33,10 +34,22 @@ export function emitProviderEvidence(callback, evidence, diagnostic) {
|
|
|
33
34
|
reportFailure();
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
export { createAbortError } from "./provider-adapter.js";
|
|
38
|
+
export async function awaitProviderAbortSettlement(provider, settlement, operation = "graceful abort could not prove provider terminal settlement") {
|
|
39
|
+
let timer;
|
|
40
|
+
const deadline = new Promise((_, reject) => {
|
|
41
|
+
timer = setTimeout(() => {
|
|
42
|
+
reject(new Error(`${provider} ${operation} within ${PROVIDER_ABORT_SETTLEMENT_TIMEOUT_MS}ms`));
|
|
43
|
+
}, PROVIDER_ABORT_SETTLEMENT_TIMEOUT_MS);
|
|
44
|
+
timer.unref?.();
|
|
45
|
+
});
|
|
46
|
+
try {
|
|
47
|
+
return await Promise.race([settlement, deadline]);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
if (timer)
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
}
|
|
40
53
|
}
|
|
41
54
|
export function coerceString(value) {
|
|
42
55
|
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isSubagentProvider } from "../../keiyaku.js";
|
|
2
|
+
import { SUBAGENT_SESSION_VERSION, subagentSessionEnvelopeSchema, } from "../session.js";
|
|
3
|
+
import { getProviderRegistration } from "../providers/registry.js";
|
|
4
|
+
/** Validate a continuation envelope through its owning provider schema. */
|
|
5
|
+
export function isRecoverableSessionEnvelope(provider, value) {
|
|
6
|
+
if (!isSubagentProvider(provider))
|
|
7
|
+
return false;
|
|
8
|
+
const envelope = subagentSessionEnvelopeSchema.safeParse(value);
|
|
9
|
+
if (!envelope.success)
|
|
10
|
+
return false;
|
|
11
|
+
if (envelope.data.provider !== provider || envelope.data.version !== SUBAGENT_SESSION_VERSION) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return getProviderRegistration(provider).sessionSchema.safeParse(envelope.data.handle).success;
|
|
15
|
+
}
|