@oisincoveney/pipeline 2.5.0 → 2.7.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/dist/config/schemas.d.ts +10 -9
- package/dist/config/schemas.js +1 -0
- package/dist/moka-submit.d.ts +1 -1
- package/dist/runner-command-contract.d.ts +2 -2
- package/dist/runtime/parallel-node/parallel-node.js +24 -4
- package/dist/runtime/select-candidate/select-candidate.js +60 -2
- package/package.json +1 -1
package/dist/config/schemas.d.ts
CHANGED
|
@@ -221,8 +221,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
221
221
|
policy: z.ZodOptional<z.ZodObject<{
|
|
222
222
|
commands: z.ZodOptional<z.ZodEnum<{
|
|
223
223
|
allow: "allow";
|
|
224
|
-
"trusted-only": "trusted-only";
|
|
225
224
|
deny: "deny";
|
|
225
|
+
"trusted-only": "trusted-only";
|
|
226
226
|
}>>;
|
|
227
227
|
modules: z.ZodOptional<z.ZodEnum<{
|
|
228
228
|
allow: "allow";
|
|
@@ -246,8 +246,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
246
246
|
}, z.core.$strict>>>;
|
|
247
247
|
default_profile: z.ZodOptional<z.ZodString>;
|
|
248
248
|
mode: z.ZodEnum<{
|
|
249
|
-
hosted: "hosted";
|
|
250
249
|
local: "local";
|
|
250
|
+
hosted: "hosted";
|
|
251
251
|
}>;
|
|
252
252
|
provider: z.ZodLiteral<"toolhive">;
|
|
253
253
|
authorization_env: z.ZodDefault<z.ZodString>;
|
|
@@ -290,10 +290,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
290
290
|
}, z.core.$strict>>;
|
|
291
291
|
output: z.ZodOptional<z.ZodObject<{
|
|
292
292
|
format: z.ZodEnum<{
|
|
293
|
+
json_schema: "json_schema";
|
|
293
294
|
text: "text";
|
|
294
295
|
json: "json";
|
|
295
296
|
jsonl: "jsonl";
|
|
296
|
-
json_schema: "json_schema";
|
|
297
297
|
}>;
|
|
298
298
|
repair: z.ZodOptional<z.ZodObject<{
|
|
299
299
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -311,6 +311,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
311
311
|
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
312
312
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
313
313
|
tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
314
|
+
task: "task";
|
|
314
315
|
read: "read";
|
|
315
316
|
list: "list";
|
|
316
317
|
grep: "grep";
|
|
@@ -318,7 +319,6 @@ declare const configSchema: z.ZodObject<{
|
|
|
318
319
|
bash: "bash";
|
|
319
320
|
edit: "edit";
|
|
320
321
|
write: "write";
|
|
321
|
-
task: "task";
|
|
322
322
|
}>>>;
|
|
323
323
|
}, z.core.$strict>>>;
|
|
324
324
|
runner_command: z.ZodDefault<z.ZodObject<{
|
|
@@ -344,8 +344,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
344
344
|
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
345
345
|
path: z.ZodString;
|
|
346
346
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
347
|
-
package: "package";
|
|
348
347
|
project: "project";
|
|
348
|
+
package: "package";
|
|
349
349
|
}>>;
|
|
350
350
|
}, z.core.$strict>>>;
|
|
351
351
|
runners: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -362,14 +362,15 @@ declare const configSchema: z.ZodObject<{
|
|
|
362
362
|
disabled: "disabled";
|
|
363
363
|
}>>>;
|
|
364
364
|
output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
365
|
+
json_schema: "json_schema";
|
|
365
366
|
text: "text";
|
|
366
367
|
json: "json";
|
|
367
368
|
jsonl: "jsonl";
|
|
368
|
-
json_schema: "json_schema";
|
|
369
369
|
}>>>;
|
|
370
370
|
rules: z.ZodOptional<z.ZodBoolean>;
|
|
371
371
|
skills: z.ZodOptional<z.ZodBoolean>;
|
|
372
372
|
tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
373
|
+
task: "task";
|
|
373
374
|
read: "read";
|
|
374
375
|
list: "list";
|
|
375
376
|
grep: "grep";
|
|
@@ -377,7 +378,6 @@ declare const configSchema: z.ZodObject<{
|
|
|
377
378
|
bash: "bash";
|
|
378
379
|
edit: "edit";
|
|
379
380
|
write: "write";
|
|
380
|
-
task: "task";
|
|
381
381
|
}>>>;
|
|
382
382
|
}, z.core.$strict>;
|
|
383
383
|
command: z.ZodOptional<z.ZodString>;
|
|
@@ -472,8 +472,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
472
472
|
schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
473
473
|
description: z.ZodOptional<z.ZodString>;
|
|
474
474
|
baseline: z.ZodEnum<{
|
|
475
|
-
execute: "execute";
|
|
476
475
|
quick: "quick";
|
|
476
|
+
execute: "execute";
|
|
477
477
|
}>;
|
|
478
478
|
max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
|
|
479
479
|
node_catalog: z.ZodOptional<z.ZodString>;
|
|
@@ -485,8 +485,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
485
485
|
skills: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
486
486
|
path: z.ZodString;
|
|
487
487
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
488
|
-
package: "package";
|
|
489
488
|
project: "project";
|
|
489
|
+
package: "package";
|
|
490
490
|
}>>;
|
|
491
491
|
}, z.core.$strict>>>;
|
|
492
492
|
task_context: z.ZodOptional<z.ZodObject<{
|
|
@@ -495,6 +495,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
495
495
|
best_of_n: z.ZodOptional<z.ZodObject<{
|
|
496
496
|
categories: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
497
497
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
498
|
+
judge_model: z.ZodOptional<z.ZodString>;
|
|
498
499
|
n: z.ZodDefault<z.ZodNumber>;
|
|
499
500
|
}, z.core.$strict>>;
|
|
500
501
|
context_handoff: z.ZodOptional<z.ZodObject<{
|
package/dist/config/schemas.js
CHANGED
|
@@ -469,6 +469,7 @@ const parallelWorktreesSchema = z.object({ enabled: z.boolean().default(false) }
|
|
|
469
469
|
const bestOfNSchema = z.object({
|
|
470
470
|
categories: z.array(z.string()).default(["green"]),
|
|
471
471
|
enabled: z.boolean().default(false),
|
|
472
|
+
judge_model: z.string().optional(),
|
|
472
473
|
n: z.number().int().positive().default(1)
|
|
473
474
|
}).strict();
|
|
474
475
|
const pipelineFileSchema = z.object({
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -160,8 +160,8 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
160
160
|
}, z.core.$strict>>;
|
|
161
161
|
serviceAccountName: z.ZodOptional<z.ZodString>;
|
|
162
162
|
mode: z.ZodEnum<{
|
|
163
|
-
quick: "quick";
|
|
164
163
|
full: "full";
|
|
164
|
+
quick: "quick";
|
|
165
165
|
}>;
|
|
166
166
|
schedulePath: z.ZodOptional<z.ZodString>;
|
|
167
167
|
scheduleYaml: z.ZodOptional<z.ZodString>;
|
|
@@ -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>;
|
|
@@ -91,20 +91,40 @@ function createLinkedAbortController(signal) {
|
|
|
91
91
|
controller
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
|
+
function childCategory(childId, fanOut) {
|
|
95
|
+
return fanOut ? Object.keys(fanOut.by_category).find((category) => childId.includes(category)) : void 0;
|
|
96
|
+
}
|
|
97
|
+
function makeCategoryGate(context) {
|
|
98
|
+
const fanOut = context.config.token_budget?.fan_out_width;
|
|
99
|
+
const limits = /* @__PURE__ */ new Map();
|
|
100
|
+
return (childId, run) => {
|
|
101
|
+
const category = childCategory(childId, fanOut);
|
|
102
|
+
if (!(category && fanOut)) return run();
|
|
103
|
+
let limit = limits.get(category);
|
|
104
|
+
if (!limit) {
|
|
105
|
+
limit = pLimit(fanOut.by_category[category]);
|
|
106
|
+
limits.set(category, limit);
|
|
107
|
+
}
|
|
108
|
+
return limit(run);
|
|
109
|
+
};
|
|
110
|
+
}
|
|
94
111
|
function executeParallelChildren(children, context, runtime) {
|
|
95
112
|
for (const child of children) runtime.markNodeReady(context, child.id);
|
|
96
|
-
|
|
113
|
+
const gate = makeCategoryGate(context);
|
|
114
|
+
const runChild = (child) => gate(child.id, () => runChildInWorktree(child, context, runtime));
|
|
115
|
+
if (!context.maxParallelNodes) return Promise.all(children.map((child) => runChild(child)));
|
|
97
116
|
const limit = pLimit(context.maxParallelNodes);
|
|
98
|
-
return Promise.all(children.map((child) => limit(() =>
|
|
117
|
+
return Promise.all(children.map((child) => limit(() => runChild(child))));
|
|
99
118
|
}
|
|
100
119
|
async function executeFailFastParallelChildren(children, context, abortController, runtime) {
|
|
101
120
|
for (const child of children) runtime.markNodeReady(context, child.id);
|
|
121
|
+
const gate = makeCategoryGate(context);
|
|
102
122
|
const limit = pLimit({
|
|
103
123
|
concurrency: context.maxParallelNodes ?? children.length,
|
|
104
124
|
rejectOnClear: true
|
|
105
125
|
});
|
|
106
126
|
return (await Promise.allSettled(children.map((child) => limit(async () => {
|
|
107
|
-
const result = await runChildInWorktree(child, context, runtime);
|
|
127
|
+
const result = await gate(child.id, () => runChildInWorktree(child, context, runtime));
|
|
108
128
|
if (result.status === "failed") {
|
|
109
129
|
abortController.abort();
|
|
110
130
|
limit.clearQueue();
|
|
@@ -121,4 +141,4 @@ function parallelOutput(children, results) {
|
|
|
121
141
|
return JSON.stringify({ children: Object.fromEntries(children.filter((child) => outputsByNode.has(child.id)).map((child) => [child.id, outputsByNode.get(child.id)])) });
|
|
122
142
|
}
|
|
123
143
|
//#endregion
|
|
124
|
-
export { executeParallelNode, parallelEvidence, parallelOutput };
|
|
144
|
+
export { childCategory, executeParallelNode, parallelEvidence, parallelOutput };
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { createRunnerLaunchPlan } from "../../runner.js";
|
|
2
|
+
import { normalizeRunnerOutput } from "../../runner-output.js";
|
|
1
3
|
import { parseJsonObject } from "../json-validation/json-validation.js";
|
|
2
4
|
import "../json-validation/index.js";
|
|
3
5
|
//#region src/runtime/select-candidate/select-candidate.ts
|
|
6
|
+
const SCORE_RE = /-?\d+(?:\.\d+)?/;
|
|
4
7
|
function selectBestCandidate(candidates) {
|
|
5
8
|
const passing = candidates.filter((candidate) => candidate.status === "PASS");
|
|
6
9
|
if (passing.length === 0) return null;
|
|
7
10
|
return passing.reduce((best, candidate) => (candidate.judgeScore ?? 0) > (best.judgeScore ?? 0) ? candidate : best);
|
|
8
11
|
}
|
|
9
|
-
function executeSelectCandidateBuiltin(context, node) {
|
|
10
|
-
const candidates = readCandidates(context, node?.needs.at(0) ?? null);
|
|
12
|
+
async function executeSelectCandidateBuiltin(context, node) {
|
|
13
|
+
const candidates = await scoreCandidates(context, readCandidates(context, node?.needs.at(0) ?? null));
|
|
11
14
|
const selected = selectBestCandidate(candidates);
|
|
12
15
|
if (!selected) return {
|
|
13
16
|
evidence: [`select-candidate: no passing candidate among ${candidates.length}`, ...candidates.map((candidate) => `- ${candidate.nodeId}: FAIL`)],
|
|
@@ -20,6 +23,61 @@ function executeSelectCandidateBuiltin(context, node) {
|
|
|
20
23
|
output: selected.output
|
|
21
24
|
};
|
|
22
25
|
}
|
|
26
|
+
async function scoreCandidates(context, candidates) {
|
|
27
|
+
const model = context.config.best_of_n?.judge_model;
|
|
28
|
+
const runner = Object.keys(context.config.runners).at(0);
|
|
29
|
+
if (!(model && runner)) return candidates;
|
|
30
|
+
return await Promise.all(candidates.map((candidate) => scoreCandidate(context, candidate, runner, model)));
|
|
31
|
+
}
|
|
32
|
+
async function scoreCandidate(context, candidate, runner, model) {
|
|
33
|
+
const plan = judgePlan(context, candidate, runner, model);
|
|
34
|
+
context.agentInvocations.push(plan);
|
|
35
|
+
const judgeScore = parseScore(normalizeRunnerOutput(plan, (await context.executor(plan, { signal: context.signal })).stdout).output);
|
|
36
|
+
return judgeScore === null ? candidate : {
|
|
37
|
+
...candidate,
|
|
38
|
+
judgeScore
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function judgePlan(context, candidate, runner, model) {
|
|
42
|
+
const profileId = `select-candidate:judge:${candidate.nodeId}`;
|
|
43
|
+
return createRunnerLaunchPlan({
|
|
44
|
+
...context.config,
|
|
45
|
+
profiles: {
|
|
46
|
+
...context.config.profiles,
|
|
47
|
+
[profileId]: {
|
|
48
|
+
filesystem: { mode: "read-only" },
|
|
49
|
+
instructions: { inline: "Score the candidate implementation." },
|
|
50
|
+
network: { mode: "disabled" },
|
|
51
|
+
output: { format: "text" },
|
|
52
|
+
runner,
|
|
53
|
+
tools: []
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, {
|
|
57
|
+
model,
|
|
58
|
+
nodeId: profileId,
|
|
59
|
+
profileId,
|
|
60
|
+
prompt: judgePrompt(context.task, candidate.output),
|
|
61
|
+
worktreePath: context.worktreePath
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function judgePrompt(task, output) {
|
|
65
|
+
return [
|
|
66
|
+
"Score how well this candidate implementation satisfies the task.",
|
|
67
|
+
"Return ONLY a number between 0 and 1 (1 = best). No prose, no fences.",
|
|
68
|
+
"",
|
|
69
|
+
`Task: ${task}`,
|
|
70
|
+
"",
|
|
71
|
+
"Candidate result:",
|
|
72
|
+
output
|
|
73
|
+
].join("\n");
|
|
74
|
+
}
|
|
75
|
+
function parseScore(text) {
|
|
76
|
+
const match = SCORE_RE.exec(text);
|
|
77
|
+
if (!match) return null;
|
|
78
|
+
const value = Number(match[0]);
|
|
79
|
+
return Number.isFinite(value) ? Math.max(0, Math.min(1, value)) : null;
|
|
80
|
+
}
|
|
23
81
|
function readCandidates(context, upstreamNodeId) {
|
|
24
82
|
if (!upstreamNodeId) return [];
|
|
25
83
|
const upstream = context.plan.graph.node(upstreamNodeId);
|
package/package.json
CHANGED
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"prepack": "bun run build:cli"
|
|
122
122
|
},
|
|
123
123
|
"type": "module",
|
|
124
|
-
"version": "2.
|
|
124
|
+
"version": "2.7.0",
|
|
125
125
|
"description": "Config-driven multi-agent pipeline runner for repository work",
|
|
126
126
|
"main": "./dist/index.js",
|
|
127
127
|
"types": "./dist/index.d.ts",
|