@oisincoveney/pipeline 2.5.0 → 2.6.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.
@@ -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<{
@@ -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>;
@@ -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<{
@@ -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({
@@ -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";
10
8
  "workflow.success": "workflow.success";
11
9
  "workflow.failure": "workflow.failure";
12
10
  "workflow.complete": "workflow.complete";
11
+ "node.start": "node.start";
13
12
  "node.success": "node.success";
14
13
  "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";
99
97
  "workflow.success": "workflow.success";
100
98
  "workflow.failure": "workflow.failure";
101
99
  "workflow.complete": "workflow.complete";
100
+ "node.start": "node.start";
102
101
  "node.success": "node.success";
103
102
  "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<{
@@ -206,13 +206,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
206
206
  }, z.core.$strict>>;
207
207
  hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
208
208
  "workflow.start": "workflow.start";
209
- "node.finish": "node.finish";
210
- "node.start": "node.start";
211
209
  "workflow.success": "workflow.success";
212
210
  "workflow.failure": "workflow.failure";
213
211
  "workflow.complete": "workflow.complete";
212
+ "node.start": "node.start";
214
213
  "node.success": "node.success";
215
214
  "node.error": "node.error";
215
+ "node.finish": "node.finish";
216
216
  "gate.failure": "gate.failure";
217
217
  }> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
218
218
  failure: z.ZodDefault<z.ZodEnum<{
@@ -10,8 +10,8 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
10
10
  at: z.ZodOptional<z.ZodString>;
11
11
  sequence: z.ZodNumber;
12
12
  type: z.ZodEnum<{
13
- "workflow.planned": "workflow.planned";
14
13
  "workflow.start": "workflow.start";
14
+ "workflow.planned": "workflow.planned";
15
15
  }>;
16
16
  workflowPlan: z.ZodObject<{
17
17
  edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -55,10 +55,10 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
55
55
  }>;
56
56
  }, z.core.$strip>;
57
57
  type: z.ZodEnum<{
58
+ "node.start": "node.start";
59
+ "node.finish": "node.finish";
58
60
  "agent.finish": "agent.finish";
59
61
  "agent.start": "agent.start";
60
- "node.finish": "node.finish";
61
- "node.start": "node.start";
62
62
  }>;
63
63
  }, z.core.$strip>, z.ZodObject<{
64
64
  at: z.ZodOptional<z.ZodString>;
@@ -180,8 +180,8 @@ declare const runnerEventBatchSchema: z.ZodObject<{
180
180
  at: z.ZodOptional<z.ZodString>;
181
181
  sequence: z.ZodNumber;
182
182
  type: z.ZodEnum<{
183
- "workflow.planned": "workflow.planned";
184
183
  "workflow.start": "workflow.start";
184
+ "workflow.planned": "workflow.planned";
185
185
  }>;
186
186
  workflowPlan: z.ZodObject<{
187
187
  edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -225,10 +225,10 @@ declare const runnerEventBatchSchema: z.ZodObject<{
225
225
  }>;
226
226
  }, z.core.$strip>;
227
227
  type: z.ZodEnum<{
228
+ "node.start": "node.start";
229
+ "node.finish": "node.finish";
228
230
  "agent.finish": "agent.finish";
229
231
  "agent.start": "agent.start";
230
- "node.finish": "node.finish";
231
- "node.start": "node.start";
232
232
  }>;
233
233
  }, z.core.$strip>, z.ZodObject<{
234
234
  at: z.ZodOptional<z.ZodString>;
@@ -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.5.0",
124
+ "version": "2.6.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",