@astrosheep/keiyaku 2.8.4 → 2.9.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/README.md +35 -15
- package/build/.tsbuildinfo +1 -1
- package/build/agents/{call-terms_v2.js → call-terms.js} +12 -8
- package/build/agents/harness/control-types.js +1 -0
- package/build/agents/harness/execution-handle.js +23 -3
- package/build/agents/harness/index.js +6 -607
- package/build/agents/harness/outcome.js +141 -0
- package/build/agents/harness/projection.js +310 -0
- package/build/agents/harness/router.js +201 -0
- package/build/agents/harness/runtime.js +2 -1
- package/build/agents/{launch-snapshot_v2.js → launch-snapshot/model.js} +69 -74
- package/build/agents/launch-snapshot/resolve.js +72 -0
- package/build/agents/opencode-sdk.js +24 -3
- package/build/agents/providers/{claude-agent-sdk.js → claude-agent-sdk/adapter.js} +46 -368
- package/build/agents/providers/claude-agent-sdk/events.js +218 -0
- package/build/agents/providers/claude-agent-sdk/session.js +158 -0
- package/build/agents/providers/codex-app-server/adapter.js +347 -0
- package/build/agents/providers/codex-app-server/events.js +352 -0
- package/build/agents/providers/codex-app-server/session.js +266 -0
- package/build/agents/providers/codex-sdk.js +23 -5
- package/build/agents/providers/opencode-sdk/adapter.js +344 -0
- package/build/agents/providers/opencode-sdk/events.js +354 -0
- package/build/agents/providers/opencode-sdk/session.js +180 -0
- package/build/agents/providers/pi/adapter.js +269 -0
- package/build/agents/providers/pi/checkpoint.js +41 -0
- package/build/agents/providers/pi/events.js +282 -0
- package/build/agents/{selector_v2.js → selector.js} +8 -6
- package/build/cli/commands/akuma/akuma/handler.js +4 -0
- package/build/cli/commands/akuma/akuma/meta.js +16 -0
- package/build/cli/commands/akuma/catalog.js +8 -0
- package/build/cli/commands/akuma/list/handler.js +15 -0
- package/build/cli/commands/akuma/list/meta-ls.js +9 -0
- package/build/cli/commands/akuma/view/handler.js +34 -0
- package/build/cli/commands/akuma/view/meta.js +8 -0
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +10 -0
- package/build/cli/commands/contract/amend/meta.js +12 -0
- package/build/cli/commands/contract/arc/handler.js +9 -0
- package/build/cli/commands/contract/arc/meta.js +26 -0
- package/build/cli/commands/contract/bind/handler.js +23 -0
- package/build/cli/commands/contract/bind/meta.js +30 -0
- package/build/cli/commands/contract/catalog.js +16 -0
- package/build/cli/commands/contract/forfeit/handler.js +13 -0
- package/build/cli/commands/contract/forfeit/meta.js +12 -0
- package/build/cli/commands/contract/log/handler.js +12 -0
- package/build/cli/commands/contract/log/meta.js +12 -0
- package/build/cli/commands/contract/petition/handler.js +26 -0
- package/build/cli/commands/contract/petition/meta.js +23 -0
- package/build/cli/commands/contract/renew/handler.js +10 -0
- package/build/cli/commands/contract/renew/meta.js +17 -0
- package/build/cli/commands/projection/call/handler.js +39 -0
- package/build/cli/commands/projection/call/meta.js +9 -0
- package/build/cli/commands/projection/catalog.js +14 -0
- package/build/cli/commands/projection/kill/handler.js +35 -0
- package/build/cli/commands/projection/kill/meta.js +11 -0
- package/build/cli/commands/projection/revive/handler.js +53 -0
- package/build/cli/commands/projection/revive/meta.js +9 -0
- package/build/cli/commands/projection/status/handler.js +23 -0
- package/build/cli/commands/projection/status/meta.js +9 -0
- package/build/cli/commands/projection/tell/handler.js +34 -0
- package/build/cli/commands/projection/tell/meta.js +9 -0
- package/build/cli/commands/projection/wait/handler.js +21 -0
- package/build/cli/commands/projection/wait/meta.js +11 -0
- package/build/cli/commands/registry.js +100 -0
- package/build/cli/commands/shared.js +71 -0
- package/build/cli/commands/skills/catalog.js +6 -0
- package/build/cli/commands/skills/install/handler.js +10 -0
- package/build/cli/commands/skills/install/meta.js +9 -0
- package/build/cli/commands/skills/skills/handler.js +4 -0
- package/build/cli/commands/skills/skills/meta.js +10 -0
- package/build/cli/commands/system/catalog.js +8 -0
- package/build/cli/commands/system/completion/handler.js +10 -0
- package/build/cli/commands/system/completion/meta.js +9 -0
- package/build/cli/commands/system/dump-env/handler.js +3 -0
- package/build/cli/commands/system/dump-env/meta.js +10 -0
- package/build/cli/commands/system/guide/handler.js +4 -0
- package/build/cli/commands/system/guide/meta.js +9 -0
- package/build/cli/commands/task/add/handler.js +21 -0
- package/build/cli/commands/task/add/meta.js +8 -0
- package/build/cli/commands/task/catalog.js +22 -0
- package/build/cli/commands/task/doctor/handler.js +4 -0
- package/build/cli/commands/task/doctor/meta.js +8 -0
- package/build/cli/commands/task/done/handler.js +17 -0
- package/build/cli/commands/task/done/meta.js +8 -0
- package/build/cli/commands/task/drop/handler.js +6 -0
- package/build/cli/commands/task/drop/meta.js +8 -0
- package/build/cli/commands/task/ls/handler.js +13 -0
- package/build/cli/commands/task/ls/meta.js +8 -0
- package/build/cli/commands/task/shared.js +131 -0
- package/build/cli/commands/task/start/handler.js +6 -0
- package/build/cli/commands/task/start/meta.js +8 -0
- package/build/cli/commands/task/stop/handler.js +17 -0
- package/build/cli/commands/task/stop/meta.js +8 -0
- package/build/cli/commands/task/task/handler.js +5 -0
- package/build/cli/commands/task/task/meta.js +11 -0
- package/build/cli/commands/task/update/handler.js +18 -0
- package/build/cli/commands/task/update/meta.js +8 -0
- package/build/cli/commands/task/view/handler.js +14 -0
- package/build/cli/commands/task/view/meta.js +8 -0
- package/build/cli/completion.js +26 -27
- package/build/cli/flags.js +79 -2
- package/build/cli/help.js +27 -49
- package/build/cli/index.js +121 -374
- package/build/cli/output-stream-error-policy.js +17 -0
- package/build/cli/parse.js +159 -72
- package/build/cli/projection-address.js +5 -0
- package/build/cli/render/arc.js +1 -1
- package/build/cli/render/errors.js +4 -3
- package/build/cli/render/format.js +14 -0
- package/build/cli/render/kanshi.js +106 -0
- package/build/cli/render/petition.js +24 -1
- package/build/cli/render/projection-activity.js +5 -1
- package/build/cli/render/shared.js +2 -2
- package/build/cli/render/status.js +79 -13
- package/build/cli/render/task.js +113 -0
- package/build/cli/render/wait.js +23 -3
- package/build/cli/types.js +1 -1
- package/build/config/{akuma-loader_v2.js → akuma-loader.js} +2 -2
- package/build/config/env.js +9 -4
- package/build/config/settings/disease.js +26 -0
- package/build/config/settings/knobs.js +8 -0
- package/build/config/settings/loader.js +244 -0
- package/build/config/settings/schema.js +276 -0
- package/build/core/addressing.js +1 -1
- package/build/core/amend.js +3 -3
- package/build/core/arc.js +5 -4
- package/build/core/bind-workspace.js +123 -0
- package/build/core/bind.js +75 -155
- package/build/core/call/call.js +224 -0
- package/build/core/call/context.js +238 -0
- package/build/core/call/execution.js +217 -0
- package/build/core/call/prompt.js +42 -0
- package/build/core/call/reference.js +24 -0
- package/build/core/call-persist.js +1 -1
- package/build/core/claim-delivery.js +247 -0
- package/build/core/claim.js +39 -277
- package/build/core/context.js +2 -1
- package/build/core/{render.js → contract-view.js} +12 -140
- package/build/core/draft.js +107 -9
- package/build/core/entry.js +9 -1
- package/build/core/execution-coordinate.js +4 -20
- package/build/core/execution-pact.js +16 -31
- package/build/core/forfeit.js +35 -22
- package/build/core/hints.js +2 -2
- package/build/core/log.js +2 -2
- package/build/core/petition-claim-gates.js +8 -6
- package/build/core/petition-preview.js +97 -0
- package/build/core/petition-run.js +3 -2
- package/build/core/petition.js +39 -26
- package/build/core/projection/generation/database.js +306 -0
- package/build/core/projection/generation/identity.js +84 -0
- package/build/core/projection/generation/model.js +201 -0
- package/build/core/projection/generation/store.js +73 -0
- package/build/core/projection/generation/transitions.js +258 -0
- package/build/core/projection/heart.js +0 -307
- package/build/core/projection/tell/database.js +109 -0
- package/build/core/projection/tell/model.js +97 -0
- package/build/core/{projection-tells.js → projection/tell/store.js} +3 -158
- package/build/core/projection-activity.js +23 -2
- package/build/core/projection-core.js +2 -1
- package/build/core/projection-execution-observer.js +259 -0
- package/build/core/projection-generation-continuation.js +1 -1
- package/build/core/projection-generation-execution.js +90 -20
- package/build/core/projection-generation-launcher.js +1 -1
- package/build/core/projection-generation-runner.js +198 -4
- package/build/core/projection-identity.js +1 -1
- package/build/core/projection-kill.js +50 -17
- package/build/core/projection-life-observer.js +1 -1
- package/build/core/projection-life-protocol.js +10 -0
- package/build/core/projection-mint.js +1 -1
- package/build/core/projection-status.js +45 -32
- package/build/core/projection-wait.js +12 -2
- package/build/core/projection-wake.js +5 -2
- package/build/core/{queue_v2.js → queue.js} +2 -1
- package/build/core/registry.js +1 -1
- package/build/core/renew.js +7 -7
- package/build/core/response-artifact-catalog-sqlite.js +112 -0
- package/build/core/response-artifact-catalog.js +7 -0
- package/build/core/seal.js +44 -16
- package/build/core/status/board.js +286 -0
- package/build/core/status/drift.js +99 -0
- package/build/core/status/lifecycle.js +84 -0
- package/build/core/status/reconciliation.js +131 -0
- package/build/core/stored-agent-event.js +28 -4
- package/build/core/target-ref.js +10 -0
- package/build/core/task/board.js +175 -0
- package/build/core/task/commands.js +211 -0
- package/build/core/task/document.js +189 -0
- package/build/core/task/model.js +1 -0
- package/build/core/task/settlement-git.js +207 -0
- package/build/core/task/settlement-policy.js +82 -0
- package/build/core/task/source-board.js +84 -0
- package/build/core/task/source-model.js +1 -0
- package/build/core/task/validation.js +44 -0
- package/build/core/task-contract.js +224 -0
- package/build/core/task-doctor.js +14 -0
- package/build/core/task-git-actor.js +38 -0
- package/build/core/task-git-runtime.js +34 -0
- package/build/core/task-git-store.js +375 -0
- package/build/core/task-repository.js +1 -0
- package/build/core/task-store-repository.js +86 -0
- package/build/core/task-store.js +1 -0
- package/build/core/task-worktree.js +51 -0
- package/build/core/task.js +4 -0
- package/build/core/transcripts.js +138 -56
- package/build/core/validation.js +17 -0
- package/build/core/verdict.js +2 -2
- package/build/core/worktree-path.js +24 -6
- package/build/flow-error.js +3 -2
- package/build/generated/version.js +1 -1
- package/build/git/commits.js +3 -0
- package/build/git/diff/parsers.js +0 -94
- package/build/index.js +2 -0
- package/build/keiyaku-constants.js +2 -0
- package/build/keiyaku.js +4 -3
- package/package.json +3 -2
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +11 -6
- package/build/agents/harness/pump.js +0 -158
- package/build/agents/providers/codex-app-server.js +0 -864
- package/build/agents/providers/opencode-sdk.js +0 -363
- package/build/agents/providers/pi.js +0 -557
- package/build/config/settings.js +0 -533
- package/build/core/call.js +0 -686
- package/build/core/projection/generation.js +0 -412
- package/build/core/projection/identity.js +0 -81
- package/build/core/projection/mint.js +0 -174
- package/build/core/projection-generation-store.js +0 -707
- package/build/core/status.js +0 -539
|
@@ -23,9 +23,16 @@ function withCodexSdkModelReasoningEffort(threadOptions) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
let codexConstructor = Codex;
|
|
26
|
+
function getCodexConstructor(override) {
|
|
27
|
+
if (override)
|
|
28
|
+
return override;
|
|
29
|
+
return codexConstructor;
|
|
30
|
+
}
|
|
31
|
+
/** @deprecated Use CodexSdkOptions.codexConstructor instead. */
|
|
26
32
|
export function setCodexSdkConstructorForTests(constructor) {
|
|
27
33
|
codexConstructor = constructor;
|
|
28
34
|
}
|
|
35
|
+
/** @deprecated Use CodexSdkOptions.codexConstructor instead. */
|
|
29
36
|
export function resetCodexSdkConstructorForTests() {
|
|
30
37
|
codexConstructor = Codex;
|
|
31
38
|
}
|
|
@@ -60,7 +67,12 @@ function extractAgentMessage(event) {
|
|
|
60
67
|
if (event.type !== CODEX_EVENT_ITEM_COMPLETED && event.type !== CODEX_EVENT_ITEM_UPDATED) {
|
|
61
68
|
return undefined;
|
|
62
69
|
}
|
|
63
|
-
|
|
70
|
+
if (event.item.type !== "agent_message")
|
|
71
|
+
return undefined;
|
|
72
|
+
const text = coerceString(event.item.text);
|
|
73
|
+
if (!text)
|
|
74
|
+
return undefined;
|
|
75
|
+
return { id: event.item.id, text };
|
|
64
76
|
}
|
|
65
77
|
function codexActivityCall(item) {
|
|
66
78
|
switch (item.type) {
|
|
@@ -157,18 +169,23 @@ function emitCodexSemanticEvent(builder, event) {
|
|
|
157
169
|
...(phase === "started" ? {} : { result: codexActivityResult(event.item) }),
|
|
158
170
|
});
|
|
159
171
|
}
|
|
172
|
+
/** @deprecated Use the codex-app-server adapter. */
|
|
160
173
|
export async function startCodexSdk(prompt, cwd, options) {
|
|
161
174
|
const threadId = options.threadId?.trim();
|
|
162
175
|
const recordedEventTypes = [];
|
|
163
176
|
let totalEventCount = 0;
|
|
164
177
|
let activeAbort;
|
|
178
|
+
let runReturned = false;
|
|
165
179
|
appendDebugLog(`startCodexSdk: executable=${options.executable ?? "codex"} model=${options.model ?? "default"} ${CODEX_MODEL_REASONING_EFFORT_CONFIG_KEY}=${String(options.config?.[CODEX_MODEL_REASONING_EFFORT_CONFIG_KEY] ?? "default")} mode=${threadId ? "resume" : "fresh"}`, { cwd, section: CODEX_SDK_PROVIDER });
|
|
166
180
|
return createProjectionDriver({
|
|
167
181
|
steerMode: "replay",
|
|
168
182
|
initialTurn: options.initialTurn,
|
|
169
183
|
onIngress: options.onIngress,
|
|
170
|
-
async abort() {
|
|
184
|
+
async abort(mode) {
|
|
171
185
|
activeAbort?.abort();
|
|
186
|
+
if (mode === "force" && !runReturned) {
|
|
187
|
+
throw new Error("codex-sdk cannot guarantee forced termination");
|
|
188
|
+
}
|
|
172
189
|
},
|
|
173
190
|
async run(builder) {
|
|
174
191
|
activeAbort = new AbortController();
|
|
@@ -186,7 +203,7 @@ export async function startCodexSdk(prompt, cwd, options) {
|
|
|
186
203
|
config: options.config,
|
|
187
204
|
env,
|
|
188
205
|
};
|
|
189
|
-
const sdk = new codexConstructor(codexOptions);
|
|
206
|
+
const sdk = new (getCodexConstructor(options.codexConstructor))(codexOptions);
|
|
190
207
|
const threadOptions = withCodexSdkModelReasoningEffort(options.threadOptions);
|
|
191
208
|
const thread = threadId ? sdk.resumeThread(threadId, threadOptions) : sdk.startThread(threadOptions);
|
|
192
209
|
const streamed = await thread.runStreamed(prompt, { signal: activeAbort.signal });
|
|
@@ -255,8 +272,8 @@ export async function startCodexSdk(prompt, cwd, options) {
|
|
|
255
272
|
emitCodexSemanticEvent(builder, event);
|
|
256
273
|
const message = extractAgentMessage(event);
|
|
257
274
|
if (message) {
|
|
258
|
-
lastAgentMessage = message;
|
|
259
|
-
builder.emit({ type: "message", text: message });
|
|
275
|
+
lastAgentMessage = message.text;
|
|
276
|
+
builder.emit({ type: "message", id: message.id, text: message.text });
|
|
260
277
|
}
|
|
261
278
|
});
|
|
262
279
|
}
|
|
@@ -304,6 +321,7 @@ export async function startCodexSdk(prompt, cwd, options) {
|
|
|
304
321
|
throw error;
|
|
305
322
|
}
|
|
306
323
|
finally {
|
|
324
|
+
runReturned = true;
|
|
307
325
|
linked.removeEventListener("abort", onOuterAbort);
|
|
308
326
|
}
|
|
309
327
|
},
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FlowError } from "../../../flow-error.js";
|
|
3
|
+
import { appendDebugBlock, appendDebugLog } from "../../../telemetry/debug-log.js";
|
|
4
|
+
import { SUBAGENT_SESSION_VERSION } from "../../session.js";
|
|
5
|
+
import { createProjectionDriver } from "../../harness/execution-handle.js";
|
|
6
|
+
import { buildSubagentEnv, coerceString, emitProviderEvidence, sha256Utf8 } from "../../harness/runtime.js";
|
|
7
|
+
import { renderEventTypeSummary } from "../event-type-tail.js";
|
|
8
|
+
import { createOpencodeEventController } from "./events.js";
|
|
9
|
+
import { OPENCODE_DEFAULT_EXECUTABLE, OPENCODE_SDK_PROVIDER, OpencodeIdleMonitor, loadOpencodeSdk, sessionIdFrom, withAbort, setOpencodeSdkLoaderForTests as setLoader, resetOpencodeSdkLoaderForTests as resetLoader, } from "./session.js";
|
|
10
|
+
export const opencodeSessionSchema = z.object({ sessionId: z.string().trim().min(1) });
|
|
11
|
+
export function parseOpencodeModelRef(model, effort) {
|
|
12
|
+
const trimmed = model.trim();
|
|
13
|
+
const slash = trimmed.indexOf("/");
|
|
14
|
+
if (slash <= 0 || slash === trimmed.length - 1) {
|
|
15
|
+
throw new FlowError("INVALID_SETTINGS", `Invalid opencode model '${model}'. Expected opaque shape '<provider>/<model>' with non-empty segments split at the first slash.`);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
providerID: trimmed.slice(0, slash),
|
|
19
|
+
id: trimmed.slice(slash + 1),
|
|
20
|
+
...(effort !== undefined ? { variant: effort } : {}),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function setOpencodeSdkLoaderForTests(loader) {
|
|
24
|
+
setLoader(loader);
|
|
25
|
+
}
|
|
26
|
+
export function resetOpencodeSdkLoaderForTests() {
|
|
27
|
+
resetLoader();
|
|
28
|
+
}
|
|
29
|
+
export async function startOpencode(prompt, cwd, options = {}) {
|
|
30
|
+
const sessionId = options.sessionId?.trim();
|
|
31
|
+
const executable = options.executable ?? OPENCODE_DEFAULT_EXECUTABLE;
|
|
32
|
+
const baseModelRef = options.model === undefined
|
|
33
|
+
? undefined
|
|
34
|
+
: parseOpencodeModelRef(options.model, options.effort);
|
|
35
|
+
const baseEffort = options.effort;
|
|
36
|
+
let activeSessionId;
|
|
37
|
+
let sdk;
|
|
38
|
+
let streamAbort;
|
|
39
|
+
let executionSignal;
|
|
40
|
+
let idleMonitor;
|
|
41
|
+
let enqueueTail = Promise.resolve();
|
|
42
|
+
let enqueueFailure;
|
|
43
|
+
let acceptingEnqueue = true;
|
|
44
|
+
let builderRef;
|
|
45
|
+
let resolveRunSettled;
|
|
46
|
+
let rejectRunSettled;
|
|
47
|
+
const runSettled = new Promise((resolve, reject) => {
|
|
48
|
+
resolveRunSettled = resolve;
|
|
49
|
+
rejectRunSettled = reject;
|
|
50
|
+
});
|
|
51
|
+
runSettled.catch(() => undefined);
|
|
52
|
+
let eventController;
|
|
53
|
+
const asProviderError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
54
|
+
const rememberEnqueueFailure = (error) => {
|
|
55
|
+
const failure = asProviderError(error);
|
|
56
|
+
enqueueFailure ??= failure;
|
|
57
|
+
return failure;
|
|
58
|
+
};
|
|
59
|
+
const promptSteer = async (client, text, tellId) => {
|
|
60
|
+
if (options.onEvidence) {
|
|
61
|
+
emitProviderEvidence(options.onEvidence, {
|
|
62
|
+
type: "outbound",
|
|
63
|
+
provider: OPENCODE_SDK_PROVIDER,
|
|
64
|
+
direction: "input",
|
|
65
|
+
kind: tellId ? "steer" : "turn-start",
|
|
66
|
+
...sha256Utf8(text),
|
|
67
|
+
}, (textDiagnostic) => builderRef?.emit({ type: "diagnostic", text: textDiagnostic }));
|
|
68
|
+
}
|
|
69
|
+
const receipt = await client.v2.session.prompt({
|
|
70
|
+
sessionID: activeSessionId,
|
|
71
|
+
// OpenCode documents no client-id idempotence; omit it and retain the
|
|
72
|
+
// at-least-once retry window until such a contract exists.
|
|
73
|
+
prompt: { text },
|
|
74
|
+
delivery: "steer",
|
|
75
|
+
}, { throwOnError: true, signal: executionSignal });
|
|
76
|
+
const admitted = receipt.data.data;
|
|
77
|
+
const ordinal = admitted.admittedSeq;
|
|
78
|
+
if (options.onEvidence) {
|
|
79
|
+
emitProviderEvidence(options.onEvidence, {
|
|
80
|
+
type: "ack",
|
|
81
|
+
provider: OPENCODE_SDK_PROVIDER,
|
|
82
|
+
fence: { kind: "ordinal", ordinal },
|
|
83
|
+
outbound: tellId ? "steer" : "run",
|
|
84
|
+
}, (textDiagnostic) => builderRef?.emit({ type: "diagnostic", text: textDiagnostic }));
|
|
85
|
+
}
|
|
86
|
+
return { fence: { kind: "ordinal", ordinal } };
|
|
87
|
+
};
|
|
88
|
+
const waitIdle = async () => {
|
|
89
|
+
if (!idleMonitor)
|
|
90
|
+
throw new Error(`${OPENCODE_SDK_PROVIDER} cannot observe idle: no active session`);
|
|
91
|
+
await idleMonitor.waitForIdle();
|
|
92
|
+
};
|
|
93
|
+
const applyBaseModel = async (client) => {
|
|
94
|
+
if (!baseModelRef)
|
|
95
|
+
return;
|
|
96
|
+
await client.v2.session.switchModel({ sessionID: activeSessionId, model: baseModelRef }, { throwOnError: true, signal: executionSignal });
|
|
97
|
+
};
|
|
98
|
+
const submitTell = async (tell) => {
|
|
99
|
+
if (!sdk || !activeSessionId) {
|
|
100
|
+
throw new Error(`${OPENCODE_SDK_PROVIDER} cannot steer: no active session`);
|
|
101
|
+
}
|
|
102
|
+
const client = sdk.client;
|
|
103
|
+
const tellEffort = tell.effort;
|
|
104
|
+
if (tellEffort !== undefined && tellEffort !== baseEffort) {
|
|
105
|
+
if (!baseModelRef) {
|
|
106
|
+
throw new FlowError("INVALID_EFFORT_OVERRIDE", `Effort '${tellEffort}' requires an explicit model.`);
|
|
107
|
+
}
|
|
108
|
+
const signal = executionSignal ?? new AbortController().signal;
|
|
109
|
+
await waitIdle();
|
|
110
|
+
await client.v2.session.switchModel({
|
|
111
|
+
sessionID: activeSessionId,
|
|
112
|
+
model: { providerID: baseModelRef.providerID, id: baseModelRef.id, variant: tellEffort },
|
|
113
|
+
}, { throwOnError: true, signal });
|
|
114
|
+
const ack = await promptSteer(client, tell.text, tell.id);
|
|
115
|
+
return {
|
|
116
|
+
ack,
|
|
117
|
+
settle: (async () => {
|
|
118
|
+
await waitIdle();
|
|
119
|
+
await applyBaseModel(client);
|
|
120
|
+
})(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return { ack: await promptSteer(client, tell.text, tell.id), settle: Promise.resolve() };
|
|
124
|
+
};
|
|
125
|
+
const enqueue = (tell) => {
|
|
126
|
+
if (!acceptingEnqueue) {
|
|
127
|
+
return Promise.reject(enqueueFailure ?? new Error(`${OPENCODE_SDK_PROVIDER} session is no longer accepting tells`));
|
|
128
|
+
}
|
|
129
|
+
let resolveAck;
|
|
130
|
+
let rejectAck;
|
|
131
|
+
let ackResolved = false;
|
|
132
|
+
const ack = new Promise((resolve, reject) => {
|
|
133
|
+
resolveAck = resolve;
|
|
134
|
+
rejectAck = reject;
|
|
135
|
+
});
|
|
136
|
+
const job = enqueueTail.then(async () => {
|
|
137
|
+
if (enqueueFailure) {
|
|
138
|
+
rejectAck(enqueueFailure);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const submission = await submitTell(tell);
|
|
143
|
+
ackResolved = true;
|
|
144
|
+
resolveAck(submission.ack);
|
|
145
|
+
await submission.settle;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
const failure = rememberEnqueueFailure(error);
|
|
149
|
+
if (!ackResolved)
|
|
150
|
+
rejectAck(failure);
|
|
151
|
+
throw failure;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
enqueueTail = job.catch((error) => {
|
|
155
|
+
rememberEnqueueFailure(error);
|
|
156
|
+
});
|
|
157
|
+
return ack;
|
|
158
|
+
};
|
|
159
|
+
const drainEnqueueTail = async () => {
|
|
160
|
+
for (;;) {
|
|
161
|
+
const observed = enqueueTail;
|
|
162
|
+
await observed;
|
|
163
|
+
if (observed !== enqueueTail)
|
|
164
|
+
continue;
|
|
165
|
+
acceptingEnqueue = false;
|
|
166
|
+
if (enqueueFailure)
|
|
167
|
+
throw enqueueFailure;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
appendDebugLog(`startOpencode: executable=${executable} model=${options.model ?? "default"} mode=${sessionId ? "resume" : "fresh"}`, { cwd, section: OPENCODE_SDK_PROVIDER });
|
|
172
|
+
return createProjectionDriver({
|
|
173
|
+
steerMode: "mid-execution",
|
|
174
|
+
initialTurn: options.initialTurn,
|
|
175
|
+
enqueue,
|
|
176
|
+
onIngress: options.onIngress,
|
|
177
|
+
async abort(mode) {
|
|
178
|
+
acceptingEnqueue = false;
|
|
179
|
+
streamAbort?.abort();
|
|
180
|
+
if (mode === "force") {
|
|
181
|
+
const failures = [];
|
|
182
|
+
if (sdk && activeSessionId) {
|
|
183
|
+
try {
|
|
184
|
+
await sdk.client.v2.session.interrupt({ sessionID: activeSessionId }, { throwOnError: true });
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
failures.push(error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
await sdk?.close?.("force");
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
failures.push(error);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
await runSettled;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
failures.push(error);
|
|
201
|
+
}
|
|
202
|
+
if (failures.length === 1)
|
|
203
|
+
throw failures[0];
|
|
204
|
+
if (failures.length > 1) {
|
|
205
|
+
throw new AggregateError(failures, `${OPENCODE_SDK_PROVIDER} forced abort failed`);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (sdk && activeSessionId) {
|
|
210
|
+
try {
|
|
211
|
+
await sdk.client.v2.session.interrupt({ sessionID: activeSessionId }, { throwOnError: true });
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// idle interrupt may error
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
async run(builder) {
|
|
219
|
+
builderRef = builder;
|
|
220
|
+
streamAbort = new AbortController();
|
|
221
|
+
const combined = new AbortController();
|
|
222
|
+
executionSignal = combined.signal;
|
|
223
|
+
const forward = () => combined.abort();
|
|
224
|
+
builder.signal.addEventListener("abort", forward, { once: true });
|
|
225
|
+
options.signal?.addEventListener("abort", forward, { once: true });
|
|
226
|
+
if (builder.signal.aborted || options.signal?.aborted)
|
|
227
|
+
forward();
|
|
228
|
+
const control = { enqueue };
|
|
229
|
+
try {
|
|
230
|
+
const env = buildSubagentEnv(options.env);
|
|
231
|
+
sdk = await withAbort(loadOpencodeSdk(executable, cwd, env, combined.signal), combined.signal, `${OPENCODE_SDK_PROVIDER} exec cancelled by client`);
|
|
232
|
+
const sessionResponse = sessionId
|
|
233
|
+
? await withAbort(sdk.client.v2.session.get({ sessionID: sessionId }, { throwOnError: true, signal: combined.signal }), combined.signal, `${OPENCODE_SDK_PROVIDER} exec cancelled by client`)
|
|
234
|
+
: await withAbort(sdk.client.v2.session.create({
|
|
235
|
+
location: { directory: cwd },
|
|
236
|
+
...(baseModelRef ? { model: baseModelRef } : {}),
|
|
237
|
+
}, { throwOnError: true, signal: combined.signal }), combined.signal, `${OPENCODE_SDK_PROVIDER} exec cancelled by client`);
|
|
238
|
+
activeSessionId = sessionIdFrom(sessionResponse.data.data, sessionId);
|
|
239
|
+
if (!activeSessionId) {
|
|
240
|
+
const message = `${OPENCODE_SDK_PROVIDER} exec could not determine session id`;
|
|
241
|
+
builder.emit({ type: "fail", message });
|
|
242
|
+
throw new Error(message);
|
|
243
|
+
}
|
|
244
|
+
idleMonitor = new OpencodeIdleMonitor(sdk.client.v2.session, activeSessionId, combined.signal);
|
|
245
|
+
eventController = createOpencodeEventController({
|
|
246
|
+
builder,
|
|
247
|
+
control,
|
|
248
|
+
idleMonitorIngress: () => idleMonitor?.ingress(),
|
|
249
|
+
onEvidence: options.onEvidence,
|
|
250
|
+
onSyncCheckpoint: options.onSyncCheckpoint,
|
|
251
|
+
onDeliveryOpportunity: options.onDeliveryOpportunity,
|
|
252
|
+
executionSignal: combined.signal,
|
|
253
|
+
getSessionId: () => activeSessionId,
|
|
254
|
+
client: sdk.client,
|
|
255
|
+
});
|
|
256
|
+
if (options.onEvidence) {
|
|
257
|
+
emitProviderEvidence(options.onEvidence, { type: "session", provider: OPENCODE_SDK_PROVIDER, sessionId: activeSessionId }, (text) => builder.emit({ type: "diagnostic", text }));
|
|
258
|
+
}
|
|
259
|
+
if (sessionId && baseModelRef) {
|
|
260
|
+
await applyBaseModel(sdk.client);
|
|
261
|
+
}
|
|
262
|
+
const eventsResult = await sdk.client.v2.session.events({ sessionID: activeSessionId }, { signal: streamAbort.signal });
|
|
263
|
+
const streamTask = (async () => {
|
|
264
|
+
try {
|
|
265
|
+
for await (const item of eventsResult.stream) {
|
|
266
|
+
if (streamAbort.signal.aborted || combined.signal.aborted)
|
|
267
|
+
break;
|
|
268
|
+
eventController.processUnknownStreamItem(item);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
if (!streamAbort.signal.aborted && !combined.signal.aborted)
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
})();
|
|
276
|
+
await promptSteer(sdk.client, prompt);
|
|
277
|
+
await waitIdle();
|
|
278
|
+
await drainEnqueueTail();
|
|
279
|
+
streamAbort.abort();
|
|
280
|
+
await streamTask;
|
|
281
|
+
await eventController.drainHistory(eventController.lastSeenSeq());
|
|
282
|
+
const lastTurnFailure = eventController.lastTurnFailure();
|
|
283
|
+
if (lastTurnFailure)
|
|
284
|
+
throw lastTurnFailure;
|
|
285
|
+
const messagesResponse = await withAbort(sdk.client.v2.session.messages({ sessionID: activeSessionId, order: "desc", limit: 32 }, { throwOnError: true, signal: combined.signal }), combined.signal, `${OPENCODE_SDK_PROVIDER} exec cancelled by client`);
|
|
286
|
+
const messagesBody = messagesResponse.data;
|
|
287
|
+
const messages = messagesBody.data ?? [];
|
|
288
|
+
const { finalAssistant, finalMessage } = eventController.finalAssistantText(messages);
|
|
289
|
+
if (finalAssistant?.error) {
|
|
290
|
+
const message = coerceString(finalAssistant.error.message) ?? `${OPENCODE_SDK_PROVIDER} assistant error`;
|
|
291
|
+
builder.emit({ type: "diagnostic", text: message });
|
|
292
|
+
builder.emit({ type: "fail", message });
|
|
293
|
+
throw new Error(message);
|
|
294
|
+
}
|
|
295
|
+
if (finalMessage) {
|
|
296
|
+
builder.emit({
|
|
297
|
+
type: "message",
|
|
298
|
+
id: finalAssistant?.id ?? "opencode-final",
|
|
299
|
+
text: finalMessage,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
eventController.closeTurn();
|
|
303
|
+
const sessionEnvelope = {
|
|
304
|
+
provider: "opencode-sdk",
|
|
305
|
+
version: SUBAGENT_SESSION_VERSION,
|
|
306
|
+
handle: { sessionId: activeSessionId },
|
|
307
|
+
};
|
|
308
|
+
const resolvedFinal = finalMessage ?? "";
|
|
309
|
+
builder.emit({
|
|
310
|
+
type: "done",
|
|
311
|
+
finalMessage: resolvedFinal,
|
|
312
|
+
session: sessionEnvelope,
|
|
313
|
+
});
|
|
314
|
+
return { finalMessage: resolvedFinal, session: sessionEnvelope };
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
appendDebugLog(`startOpencode error: ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`, { cwd, section: OPENCODE_SDK_PROVIDER });
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
acceptingEnqueue = false;
|
|
322
|
+
if (activeSessionId) {
|
|
323
|
+
appendDebugBlock("opencode-sdk stdout event types", renderEventTypeSummary(eventController?.recordedEventTypes() ?? [], eventController?.totalEventCount() ?? 0), { cwd, section: OPENCODE_SDK_PROVIDER });
|
|
324
|
+
}
|
|
325
|
+
streamAbort?.abort();
|
|
326
|
+
idleMonitor?.dispose();
|
|
327
|
+
idleMonitor = undefined;
|
|
328
|
+
executionSignal = undefined;
|
|
329
|
+
try {
|
|
330
|
+
await sdk?.close?.();
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
rejectRunSettled(error);
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
finally {
|
|
337
|
+
builder.signal.removeEventListener("abort", forward);
|
|
338
|
+
options.signal?.removeEventListener("abort", forward);
|
|
339
|
+
resolveRunSettled();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|