@oisincoveney/pipeline 3.11.13 → 3.11.15
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/dist/config/schemas.d.ts +1 -1
- package/dist/model-resolver.js +25 -33
- package/dist/moka-submit.d.ts +7 -7
- package/dist/run-state/git-refs.js +4 -1
- package/dist/runner-command-contract.d.ts +2 -2
- package/dist/runner-event-schema.d.ts +6 -6
- package/dist/runtime/agent-node/agent-node.js +91 -24
- package/dist/runtime/opencode-session-executor.js +4 -13
- package/package.json +1 -1
package/dist/config/schemas.d.ts
CHANGED
|
@@ -509,8 +509,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
509
509
|
schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
510
510
|
description: z.ZodOptional<z.ZodString>;
|
|
511
511
|
baseline: z.ZodEnum<{
|
|
512
|
-
execute: "execute";
|
|
513
512
|
quick: "quick";
|
|
513
|
+
execute: "execute";
|
|
514
514
|
}>;
|
|
515
515
|
max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
|
|
516
516
|
node_catalog: z.ZodOptional<z.ZodString>;
|
package/dist/model-resolver.js
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
//#region src/model-resolver.ts
|
|
2
2
|
const DISABLED_MODELS_ENV = "PIPELINE_DISABLED_MODELS";
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
function fallbackModelSelection(models, options) {
|
|
3
|
+
function selectNodeModelCandidates(node, options) {
|
|
4
|
+
const models = node.models ?? [];
|
|
7
5
|
if (models.length === 0) return {
|
|
6
|
+
models: [],
|
|
8
7
|
reason: "node declares no model fallback array",
|
|
9
8
|
skipped: []
|
|
10
9
|
};
|
|
11
10
|
const disabled = disabledModels();
|
|
12
11
|
const available = options?.available;
|
|
13
12
|
const enabled = models.filter((candidate) => !disabled.has(candidate) && isAvailable(candidate, available));
|
|
14
|
-
const
|
|
13
|
+
const baseSkipped = models.filter((candidate) => disabled.has(candidate) || !isAvailable(candidate, available));
|
|
15
14
|
const sizing = sizingFromOptions(options);
|
|
16
|
-
if (!sizing) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
if (!sizing) return {
|
|
16
|
+
models: enabled,
|
|
17
|
+
reason: selectionReason(enabled[0]),
|
|
18
|
+
skipped: baseSkipped
|
|
19
|
+
};
|
|
20
|
+
return sizedCandidates(enabled, baseSkipped, sizing);
|
|
21
|
+
}
|
|
22
|
+
function sizedCandidates(enabled, baseSkipped, options) {
|
|
23
|
+
const { estimatedTokens, budget } = options;
|
|
24
|
+
const required = estimatedTokens / (budget.max_context_pct / 100);
|
|
25
|
+
const fits = [];
|
|
26
|
+
const tooSmall = [];
|
|
27
|
+
for (const candidate of enabled) if ((budget.model_context_windows[candidate] ?? budget.default_context_window) >= required) fits.push(candidate);
|
|
28
|
+
else tooSmall.push(candidate);
|
|
29
|
+
const head = fits[0];
|
|
30
|
+
return {
|
|
31
|
+
models: fits,
|
|
32
|
+
reason: head ? `selected '${head}' (window ${budget.model_context_windows[head] ?? budget.default_context_window}) — holds estimated ${estimatedTokens} tokens within the ${budget.max_context_pct}% context cap` : `estimated context ${estimatedTokens} tokens exceeds ${budget.max_context_pct}% of every available model window`,
|
|
33
|
+
skipped: [...baseSkipped, ...tooSmall]
|
|
34
|
+
};
|
|
25
35
|
}
|
|
26
36
|
function isAvailable(candidate, available) {
|
|
27
37
|
return available ? available.has(candidate) : true;
|
|
@@ -32,24 +42,6 @@ function sizingFromOptions(options) {
|
|
|
32
42
|
estimatedTokens: options.estimatedTokens
|
|
33
43
|
};
|
|
34
44
|
}
|
|
35
|
-
function sizedSelection(enabled, disabledSkipped, options) {
|
|
36
|
-
const { estimatedTokens, budget } = options;
|
|
37
|
-
const required = estimatedTokens / (budget.max_context_pct / 100);
|
|
38
|
-
const tooSmall = [];
|
|
39
|
-
for (const candidate of enabled) {
|
|
40
|
-
const window = budget.model_context_windows[candidate] ?? budget.default_context_window;
|
|
41
|
-
if (window >= required) return {
|
|
42
|
-
model: candidate,
|
|
43
|
-
reason: `selected '${candidate}' (window ${window}) — holds estimated ${estimatedTokens} tokens within the ${budget.max_context_pct}% context cap`,
|
|
44
|
-
skipped: [...disabledSkipped, ...tooSmall]
|
|
45
|
-
};
|
|
46
|
-
tooSmall.push(candidate);
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
reason: `estimated context ${estimatedTokens} tokens exceeds ${budget.max_context_pct}% of every available model window`,
|
|
50
|
-
skipped: [...disabledSkipped, ...tooSmall]
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
45
|
function selectionReason(model) {
|
|
54
46
|
if (model) return "selected first enabled model from node fallback array";
|
|
55
47
|
return `all configured node models are disabled by ${DISABLED_MODELS_ENV}`;
|
|
@@ -58,4 +50,4 @@ function disabledModels() {
|
|
|
58
50
|
return new Set((process.env[DISABLED_MODELS_ENV] ?? "").split(",").map((value) => value.trim()).filter(Boolean));
|
|
59
51
|
}
|
|
60
52
|
//#endregion
|
|
61
|
-
export {
|
|
53
|
+
export { selectNodeModelCandidates };
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
//#region src/moka-submit.d.ts
|
|
6
6
|
declare const mokaSubmitDirectHooksSchema: z.ZodRecord<z.ZodEnum<{
|
|
7
7
|
"workflow.start": "workflow.start";
|
|
8
|
+
"node.finish": "node.finish";
|
|
9
|
+
"node.start": "node.start";
|
|
8
10
|
"workflow.success": "workflow.success";
|
|
9
11
|
"workflow.failure": "workflow.failure";
|
|
10
12
|
"workflow.complete": "workflow.complete";
|
|
11
|
-
"node.start": "node.start";
|
|
12
13
|
"node.success": "node.success";
|
|
13
14
|
"node.error": "node.error";
|
|
14
|
-
"node.finish": "node.finish";
|
|
15
15
|
"gate.failure": "gate.failure";
|
|
16
16
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
17
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -94,13 +94,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strict>>;
|
|
95
95
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
96
96
|
"workflow.start": "workflow.start";
|
|
97
|
+
"node.finish": "node.finish";
|
|
98
|
+
"node.start": "node.start";
|
|
97
99
|
"workflow.success": "workflow.success";
|
|
98
100
|
"workflow.failure": "workflow.failure";
|
|
99
101
|
"workflow.complete": "workflow.complete";
|
|
100
|
-
"node.start": "node.start";
|
|
101
102
|
"node.success": "node.success";
|
|
102
103
|
"node.error": "node.error";
|
|
103
|
-
"node.finish": "node.finish";
|
|
104
104
|
"gate.failure": "gate.failure";
|
|
105
105
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
106
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -161,8 +161,8 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
161
161
|
}, z.core.$strict>>;
|
|
162
162
|
serviceAccountName: z.ZodOptional<z.ZodString>;
|
|
163
163
|
mode: z.ZodEnum<{
|
|
164
|
-
quick: "quick";
|
|
165
164
|
full: "full";
|
|
165
|
+
quick: "quick";
|
|
166
166
|
}>;
|
|
167
167
|
schedulePath: z.ZodOptional<z.ZodString>;
|
|
168
168
|
scheduleYaml: z.ZodOptional<z.ZodString>;
|
|
@@ -207,13 +207,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
207
207
|
}, z.core.$strict>>;
|
|
208
208
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
209
209
|
"workflow.start": "workflow.start";
|
|
210
|
+
"node.finish": "node.finish";
|
|
211
|
+
"node.start": "node.start";
|
|
210
212
|
"workflow.success": "workflow.success";
|
|
211
213
|
"workflow.failure": "workflow.failure";
|
|
212
214
|
"workflow.complete": "workflow.complete";
|
|
213
|
-
"node.start": "node.start";
|
|
214
215
|
"node.success": "node.success";
|
|
215
216
|
"node.error": "node.error";
|
|
216
|
-
"node.finish": "node.finish";
|
|
217
217
|
"gate.failure": "gate.failure";
|
|
218
218
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
219
219
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -109,6 +109,9 @@ function promoteFinalRefEffect(input) {
|
|
|
109
109
|
function headSha(worktreePath) {
|
|
110
110
|
return Effect.map(runGit(worktreePath, ["rev-parse", "HEAD"]), (sha) => sha.trim());
|
|
111
111
|
}
|
|
112
|
+
function runnerCommitMessage(nodeId) {
|
|
113
|
+
return `chore(pipeline): ${nodeId}`;
|
|
114
|
+
}
|
|
112
115
|
function commitChangesIfNeeded(worktreePath, nodeId, committer) {
|
|
113
116
|
return Effect.gen(function* () {
|
|
114
117
|
if ((yield* runGit(worktreePath, [
|
|
@@ -121,7 +124,7 @@ function commitChangesIfNeeded(worktreePath, nodeId, committer) {
|
|
|
121
124
|
yield* runGit(worktreePath, [
|
|
122
125
|
"commit",
|
|
123
126
|
"-m",
|
|
124
|
-
|
|
127
|
+
runnerCommitMessage(nodeId)
|
|
125
128
|
]);
|
|
126
129
|
});
|
|
127
130
|
}
|
|
@@ -43,8 +43,8 @@ declare const runnerDeliverySchema: z.ZodObject<{
|
|
|
43
43
|
declare const mokaSubmissionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
44
44
|
kind: z.ZodLiteral<"graph">;
|
|
45
45
|
mode: z.ZodEnum<{
|
|
46
|
-
quick: "quick";
|
|
47
46
|
full: "full";
|
|
47
|
+
quick: "quick";
|
|
48
48
|
}>;
|
|
49
49
|
}, z.core.$strict>, z.ZodObject<{
|
|
50
50
|
argv: z.ZodArray<z.ZodString>;
|
|
@@ -104,8 +104,8 @@ declare const runnerCommandPayloadSchema: z.ZodObject<{
|
|
|
104
104
|
submission: z.ZodDefault<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
105
105
|
kind: z.ZodLiteral<"graph">;
|
|
106
106
|
mode: z.ZodEnum<{
|
|
107
|
-
quick: "quick";
|
|
108
107
|
full: "full";
|
|
108
|
+
quick: "quick";
|
|
109
109
|
}>;
|
|
110
110
|
}, z.core.$strict>, z.ZodObject<{
|
|
111
111
|
argv: z.ZodArray<z.ZodString>;
|
|
@@ -11,8 +11,8 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
11
11
|
runId: z.ZodString;
|
|
12
12
|
sequence: z.ZodNumber;
|
|
13
13
|
type: z.ZodEnum<{
|
|
14
|
-
"workflow.start": "workflow.start";
|
|
15
14
|
"workflow.planned": "workflow.planned";
|
|
15
|
+
"workflow.start": "workflow.start";
|
|
16
16
|
}>;
|
|
17
17
|
workflowPlan: z.ZodObject<{
|
|
18
18
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -58,10 +58,10 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
58
58
|
}>;
|
|
59
59
|
}, z.core.$strip>;
|
|
60
60
|
type: z.ZodEnum<{
|
|
61
|
-
"node.start": "node.start";
|
|
62
|
-
"node.finish": "node.finish";
|
|
63
61
|
"agent.finish": "agent.finish";
|
|
64
62
|
"agent.start": "agent.start";
|
|
63
|
+
"node.finish": "node.finish";
|
|
64
|
+
"node.start": "node.start";
|
|
65
65
|
}>;
|
|
66
66
|
}, z.core.$strip>, z.ZodObject<{
|
|
67
67
|
at: z.ZodOptional<z.ZodString>;
|
|
@@ -189,8 +189,8 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
189
189
|
runId: z.ZodString;
|
|
190
190
|
sequence: z.ZodNumber;
|
|
191
191
|
type: z.ZodEnum<{
|
|
192
|
-
"workflow.start": "workflow.start";
|
|
193
192
|
"workflow.planned": "workflow.planned";
|
|
193
|
+
"workflow.start": "workflow.start";
|
|
194
194
|
}>;
|
|
195
195
|
workflowPlan: z.ZodObject<{
|
|
196
196
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -236,10 +236,10 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
236
236
|
}>;
|
|
237
237
|
}, z.core.$strip>;
|
|
238
238
|
type: z.ZodEnum<{
|
|
239
|
-
"node.start": "node.start";
|
|
240
|
-
"node.finish": "node.finish";
|
|
241
239
|
"agent.finish": "agent.finish";
|
|
242
240
|
"agent.start": "agent.start";
|
|
241
|
+
"node.finish": "node.finish";
|
|
242
|
+
"node.start": "node.start";
|
|
243
243
|
}>;
|
|
244
244
|
}, z.core.$strip>, z.ZodObject<{
|
|
245
245
|
at: z.ZodOptional<z.ZodString>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolvePackageAssetPath } from "../../package-assets.js";
|
|
2
2
|
import { resolveFileReference } from "../../path-refs.js";
|
|
3
3
|
import { gatewayServerForProfile } from "../../mcp/gateway.js";
|
|
4
|
-
import {
|
|
4
|
+
import { selectNodeModelCandidates } from "../../model-resolver.js";
|
|
5
5
|
import { createRunnerLaunchPlan } from "../../runner.js";
|
|
6
6
|
import { normalizeRunnerOutput, runnerTextCandidates } from "../../runner-output.js";
|
|
7
7
|
import { estimateTokens } from "../../token-estimator.js";
|
|
@@ -29,17 +29,72 @@ function executeAgentNodeEffect(node, context, attempt) {
|
|
|
29
29
|
if (decision.overBudget) return {
|
|
30
30
|
evidence: [
|
|
31
31
|
`agent boundary node=${node.id} profile=${node.profile}`,
|
|
32
|
-
`over token budget: ${decision.
|
|
33
|
-
...decision.
|
|
32
|
+
`over token budget: ${decision.reason}`,
|
|
33
|
+
...decision.skipped.length ? [`model fallbacks skipped: ${decision.skipped.join(", ")}`] : []
|
|
34
34
|
],
|
|
35
35
|
exitCode: 1,
|
|
36
36
|
output: ""
|
|
37
37
|
};
|
|
38
|
-
const
|
|
38
|
+
const profileId = node.profile;
|
|
39
|
+
const fallbackEvidence = [];
|
|
40
|
+
const lastIndex = decision.candidates.length - 1;
|
|
41
|
+
for (let index = 0; index < lastIndex; index += 1) {
|
|
42
|
+
const model = decision.candidates[index];
|
|
43
|
+
const attemptOutcome = yield* runModelAttemptEffect({
|
|
44
|
+
attempt,
|
|
45
|
+
context,
|
|
46
|
+
model,
|
|
47
|
+
node,
|
|
48
|
+
profileId,
|
|
49
|
+
prompt
|
|
50
|
+
});
|
|
51
|
+
if (attemptOutcome.result.exitCode !== 70) return yield* buildAgentAttemptResultEffect({
|
|
52
|
+
attempt,
|
|
53
|
+
context,
|
|
54
|
+
decision,
|
|
55
|
+
fallbackEvidence,
|
|
56
|
+
model,
|
|
57
|
+
node,
|
|
58
|
+
outcome: attemptOutcome,
|
|
59
|
+
profileId
|
|
60
|
+
});
|
|
61
|
+
fallbackEvidence.push(fallbackNote(model, decision.candidates[index + 1], attemptOutcome.result));
|
|
62
|
+
}
|
|
63
|
+
const lastModel = decision.candidates[lastIndex];
|
|
64
|
+
return yield* buildAgentAttemptResultEffect({
|
|
65
|
+
attempt,
|
|
66
|
+
context,
|
|
67
|
+
decision,
|
|
68
|
+
fallbackEvidence,
|
|
69
|
+
model: lastModel,
|
|
70
|
+
node,
|
|
71
|
+
outcome: yield* runModelAttemptEffect({
|
|
72
|
+
attempt,
|
|
73
|
+
context,
|
|
74
|
+
model: lastModel,
|
|
75
|
+
node,
|
|
76
|
+
profileId,
|
|
77
|
+
prompt
|
|
78
|
+
}),
|
|
79
|
+
profileId
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function modelLabel(model) {
|
|
84
|
+
return model ?? "profile/default";
|
|
85
|
+
}
|
|
86
|
+
function fallbackNote(failed, next, result) {
|
|
87
|
+
const detail = result.stderr ? `: ${result.stderr}` : "";
|
|
88
|
+
return `model ${modelLabel(failed)} failed (infra exit ${result.exitCode}${detail}); falling back to ${modelLabel(next)}`;
|
|
89
|
+
}
|
|
90
|
+
function runModelAttemptEffect(inputs) {
|
|
91
|
+
return Effect.gen(function* () {
|
|
92
|
+
const { attempt, context, model, node, profileId, prompt } = inputs;
|
|
93
|
+
const service = yield* AgentNodeRuntimeService;
|
|
39
94
|
const plan = createRunnerLaunchPlan(context.config, {
|
|
40
|
-
model
|
|
95
|
+
model,
|
|
41
96
|
nodeId: node.id,
|
|
42
|
-
profileId
|
|
97
|
+
profileId,
|
|
43
98
|
prompt,
|
|
44
99
|
reasoningEffort: node.reasoning_effort,
|
|
45
100
|
worktreePath: context.worktreePath
|
|
@@ -47,12 +102,22 @@ function executeAgentNodeEffect(node, context, attempt) {
|
|
|
47
102
|
if (node.timeoutMs) plan.timeoutMs = node.timeoutMs;
|
|
48
103
|
context.agentInvocations.push(plan);
|
|
49
104
|
emitAgentStart(context, plan, attempt);
|
|
50
|
-
const result = yield*
|
|
105
|
+
const result = yield* service.executeRunner(context.executor, plan, {
|
|
51
106
|
onOutput: agentOutputRecorder(context, node, attempt),
|
|
52
107
|
signal: context.signal
|
|
53
108
|
});
|
|
54
109
|
emitAgentFinish(context, plan, attempt, result);
|
|
55
110
|
if (result.sessionId) context.nodeStateStore.recordSessionId(node.id, result.sessionId);
|
|
111
|
+
return {
|
|
112
|
+
plan,
|
|
113
|
+
result
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function buildAgentAttemptResultEffect(inputs) {
|
|
118
|
+
return Effect.gen(function* () {
|
|
119
|
+
const { attempt, context, decision, fallbackEvidence, model, node, outcome, profileId } = inputs;
|
|
120
|
+
const { plan, result } = outcome;
|
|
56
121
|
const finalized = yield* finalizeAgentOutputEffect({
|
|
57
122
|
context,
|
|
58
123
|
node,
|
|
@@ -64,10 +129,11 @@ function executeAgentNodeEffect(node, context, attempt) {
|
|
|
64
129
|
const handoff = yield* maybeDeriveHandoffEffect(context, node, finalized.output, attempt);
|
|
65
130
|
return withOptionalHandoff({
|
|
66
131
|
evidence: [
|
|
67
|
-
`agent boundary node=${node.id} profile=${
|
|
132
|
+
`agent boundary node=${node.id} profile=${profileId} runner=${plan.runnerId}`,
|
|
68
133
|
`estimated context tokens: ${decision.estimatedTokens}`,
|
|
69
|
-
`model selection: ${
|
|
70
|
-
...
|
|
134
|
+
`model selection: ${modelLabel(model)} (${decision.reason})`,
|
|
135
|
+
...decision.skipped.length ? [`model fallbacks skipped: ${decision.skipped.join(", ")}`] : [],
|
|
136
|
+
...fallbackEvidence,
|
|
71
137
|
...finalized.evidence,
|
|
72
138
|
...result.stderr ? [`stderr: ${result.stderr}`] : [],
|
|
73
139
|
...result.timedOut ? ["agent timed out"] : []
|
|
@@ -151,27 +217,28 @@ function createHandoffFinalizerPlan(context, node, runner, rawOutput) {
|
|
|
151
217
|
}
|
|
152
218
|
/**
|
|
153
219
|
* Pure model-routing decision for a node: estimate the assembled prompt size and
|
|
154
|
-
*
|
|
155
|
-
* A node with no fallback array
|
|
156
|
-
*
|
|
157
|
-
*
|
|
220
|
+
* resolve the ordered fallback set of models whose window holds it within the
|
|
221
|
+
* context cap. A node with no fallback array (or none surviving the filters)
|
|
222
|
+
* falls back to the profile default (`undefined`). A node with a fallback array
|
|
223
|
+
* but no fitting model under budget is `overBudget` — the caller fails it fast
|
|
224
|
+
* rather than truncating.
|
|
158
225
|
*/
|
|
159
226
|
function decideNodeModel(prompt, node, budget, availableModels) {
|
|
160
227
|
const estimatedTokens = estimateTokens(prompt);
|
|
161
|
-
|
|
162
|
-
estimatedTokens,
|
|
163
|
-
overBudget: false,
|
|
164
|
-
selection: selectNodeModel(node, { available: availableModels })
|
|
165
|
-
};
|
|
166
|
-
const selection = selectNodeModel(node, {
|
|
228
|
+
const candidates = selectNodeModelCandidates(node, {
|
|
167
229
|
available: availableModels,
|
|
168
|
-
budget
|
|
169
|
-
|
|
230
|
+
...budget ? {
|
|
231
|
+
budget,
|
|
232
|
+
estimatedTokens
|
|
233
|
+
} : {}
|
|
170
234
|
});
|
|
235
|
+
const overBudget = Boolean(budget && node.models?.length) && candidates.models.length === 0;
|
|
171
236
|
return {
|
|
237
|
+
candidates: candidates.models.length ? candidates.models : [void 0],
|
|
172
238
|
estimatedTokens,
|
|
173
|
-
overBudget
|
|
174
|
-
|
|
239
|
+
overBudget,
|
|
240
|
+
reason: candidates.reason,
|
|
241
|
+
skipped: candidates.skipped
|
|
175
242
|
};
|
|
176
243
|
}
|
|
177
244
|
function finalizeAgentOutputEffect(inputs) {
|
|
@@ -7,15 +7,6 @@ function createOpencodeSessionRegistry() {
|
|
|
7
7
|
return { sessions: /* @__PURE__ */ new Map() };
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Distinguish infra failure (server/session error -> retry-eligible exit 70)
|
|
11
|
-
* from a normal agent completion (the agent may still have produced a wrong
|
|
12
|
-
* answer; gates decide that, exit 0). This mirrors the EXIT_STARTUP convention
|
|
13
|
-
* in runner-command/run.ts and feeds retry.ts via the node's retry policy.
|
|
14
|
-
*/
|
|
15
|
-
const EXIT_OK = 0;
|
|
16
|
-
const EXIT_AGENT_ERROR = 1;
|
|
17
|
-
const EXIT_INFRA = 70;
|
|
18
|
-
/**
|
|
19
10
|
* SDK-backed replacement for the subprocess `runLaunchPlan`. Conforms to the
|
|
20
11
|
* RuntimeContext.executor seam so agent-node never learns the transport.
|
|
21
12
|
*/
|
|
@@ -288,7 +279,7 @@ function successResult(plan, drive) {
|
|
|
288
279
|
};
|
|
289
280
|
return {
|
|
290
281
|
argv: plan.args,
|
|
291
|
-
exitCode:
|
|
282
|
+
exitCode: 0,
|
|
292
283
|
sessionId: drive.sessionId,
|
|
293
284
|
stdout
|
|
294
285
|
};
|
|
@@ -296,7 +287,7 @@ function successResult(plan, drive) {
|
|
|
296
287
|
function failureResult(plan, error) {
|
|
297
288
|
return {
|
|
298
289
|
argv: plan.args,
|
|
299
|
-
exitCode:
|
|
290
|
+
exitCode: 70,
|
|
300
291
|
stderr: `opencode session failed: ${errorMessage(error)}`,
|
|
301
292
|
stdout: ""
|
|
302
293
|
};
|
|
@@ -309,8 +300,8 @@ function failureResult(plan, error) {
|
|
|
309
300
|
function infraErrorExitCode(error) {
|
|
310
301
|
switch (error.name) {
|
|
311
302
|
case "MessageOutputLengthError":
|
|
312
|
-
case "MessageAbortedError": return
|
|
313
|
-
default: return
|
|
303
|
+
case "MessageAbortedError": return 1;
|
|
304
|
+
default: return 70;
|
|
314
305
|
}
|
|
315
306
|
}
|
|
316
307
|
function describeMessageError(error) {
|
package/package.json
CHANGED
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"prepack": "bun run build:cli"
|
|
129
129
|
},
|
|
130
130
|
"type": "module",
|
|
131
|
-
"version": "3.11.
|
|
131
|
+
"version": "3.11.15",
|
|
132
132
|
"description": "Config-driven multi-agent pipeline runner for repository work",
|
|
133
133
|
"main": "./dist/index.js",
|
|
134
134
|
"types": "./dist/index.d.ts",
|