ennodia 0.1.1 → 0.2.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/CONTRIBUTING.md +60 -36
- package/README.md +74 -58
- package/bench/README.md +7 -5
- package/bench/bug-recall/run.ts +12 -4
- package/bin/ennodia +23 -2
- package/docs/assets/agents/mcp.svg +1 -1
- package/docs/assets/orchestration-pipeline.svg +4 -3
- package/docs/comparisons/agent-frameworks.md +15 -10
- package/docs/comparisons/autogen.md +20 -15
- package/docs/comparisons/chathub.md +15 -14
- package/docs/comparisons/index.md +30 -22
- package/docs/comparisons/langgraph.md +19 -12
- package/docs/comparisons/mixture-of-agents.md +20 -17
- package/docs/comparisons/model-merging.md +7 -5
- package/docs/comparisons/openrouter.md +30 -22
- package/docs/concepts/compositional-audits.md +16 -13
- package/docs/concepts/data-governance.md +31 -15
- package/docs/concepts/how-ennodia-works.md +48 -22
- package/docs/concepts/interfaces-and-core.md +19 -6
- package/docs/concepts/second-opinions.md +20 -20
- package/docs/getting-started.md +55 -27
- package/docs/guides/agent-skills.md +16 -13
- package/docs/guides/budgets-and-limits.md +30 -20
- package/docs/guides/running-better-audits.md +50 -44
- package/docs/index.md +60 -37
- package/docs/install.md +41 -32
- package/docs/reference/benchmarks.md +6 -4
- package/docs/reference/controlled-english.md +130 -0
- package/docs/reference/ennodia-io.md +28 -22
- package/docs/reference/mcp-tools.md +244 -87
- package/docs/reference/supported-harnesses.md +9 -9
- package/package.json +7 -5
- package/src/advisor.ts +685 -0
- package/src/budget.ts +25 -6
- package/src/cli.ts +1 -1
- package/src/compare.ts +248 -52
- package/src/compositional.ts +18 -0
- package/src/core.ts +547 -16
- package/src/harnesses.ts +33 -2
- package/src/index.ts +38 -0
- package/src/plan-advice.ts +601 -0
- package/src/runs.ts +74 -9
- package/src/server.ts +312 -46
- package/src/skills.ts +131 -11
- package/src/tasks.ts +192 -22
- package/src/version.ts +1 -1
package/src/server.ts
CHANGED
|
@@ -152,6 +152,223 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
152
152
|
},
|
|
153
153
|
);
|
|
154
154
|
|
|
155
|
+
server.registerTool(
|
|
156
|
+
"ennodia_start_plan_advice",
|
|
157
|
+
{
|
|
158
|
+
title: "Start Ennodia Plan Advisor",
|
|
159
|
+
description:
|
|
160
|
+
"Ask one Advisor to propose a bounded team of harness, model, and skill assignments. This starts only the Advisor task: its output is strict, inert plan data that Ennodia validates and never executes automatically. Poll ennodia_get_plan_advice, then explicitly call ennodia_start_advised_plan with the returned digest.",
|
|
161
|
+
inputSchema: {
|
|
162
|
+
prompt: z
|
|
163
|
+
.string()
|
|
164
|
+
.min(1)
|
|
165
|
+
.describe("The work for which the Advisor should propose a team."),
|
|
166
|
+
cwd: z
|
|
167
|
+
.string()
|
|
168
|
+
.optional()
|
|
169
|
+
.describe(
|
|
170
|
+
"Optional target working directory used only to discover available skills. The Advisor task runs in a separate empty temporary directory.",
|
|
171
|
+
),
|
|
172
|
+
refresh: z
|
|
173
|
+
.boolean()
|
|
174
|
+
.default(false)
|
|
175
|
+
.describe(
|
|
176
|
+
"Re-scan harnesses before freezing the Advisor inventory snapshot.",
|
|
177
|
+
),
|
|
178
|
+
advisorHarnessId: z
|
|
179
|
+
.string()
|
|
180
|
+
.optional()
|
|
181
|
+
.describe(
|
|
182
|
+
`Harness to run the Plan Advisor. Omit to use the default priority: ${comparePriorityText}.`,
|
|
183
|
+
),
|
|
184
|
+
advisorModel: z
|
|
185
|
+
.string()
|
|
186
|
+
.optional()
|
|
187
|
+
.describe("Optional model override for the Plan Advisor task."),
|
|
188
|
+
allowedHarnessIds: z
|
|
189
|
+
.array(z.string().min(1))
|
|
190
|
+
.min(1)
|
|
191
|
+
.max(64)
|
|
192
|
+
.optional()
|
|
193
|
+
.describe(
|
|
194
|
+
"Worker harness IDs the Advisor may select. Omit to allow every runnable public Ennodia adapter.",
|
|
195
|
+
),
|
|
196
|
+
allowedModels: z
|
|
197
|
+
.record(z.string().min(1), z.array(z.string().min(1)).max(128))
|
|
198
|
+
.optional()
|
|
199
|
+
.describe(
|
|
200
|
+
"Exact caller-approved worker model IDs by harness. A model omitted by the Advisor uses that harness's default.",
|
|
201
|
+
),
|
|
202
|
+
maxSlices: z
|
|
203
|
+
.number()
|
|
204
|
+
.int()
|
|
205
|
+
.min(1)
|
|
206
|
+
.max(64)
|
|
207
|
+
.optional()
|
|
208
|
+
.describe("Maximum explicit worker slices the Advisor may propose."),
|
|
209
|
+
maxSkillsPerSlice: z
|
|
210
|
+
.number()
|
|
211
|
+
.int()
|
|
212
|
+
.min(0)
|
|
213
|
+
.max(64)
|
|
214
|
+
.optional()
|
|
215
|
+
.describe("Maximum installed native skills assigned to one slice."),
|
|
216
|
+
maxTotalSkillAssignments: z
|
|
217
|
+
.number()
|
|
218
|
+
.int()
|
|
219
|
+
.min(0)
|
|
220
|
+
.max(1_024)
|
|
221
|
+
.optional()
|
|
222
|
+
.describe("Maximum skill assignments across the complete plan."),
|
|
223
|
+
timeoutMs: z
|
|
224
|
+
.number()
|
|
225
|
+
.int()
|
|
226
|
+
.positive()
|
|
227
|
+
.max(60 * 60 * 1000)
|
|
228
|
+
.optional()
|
|
229
|
+
.describe(
|
|
230
|
+
"Timeout for the single Plan Advisor task in milliseconds, capped at one hour.",
|
|
231
|
+
),
|
|
232
|
+
budget: budgetSchema.optional(),
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
async (input) => jsonResult(await core.startPlanAdvice(input)),
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
server.registerTool(
|
|
239
|
+
"ennodia_list_plan_advice",
|
|
240
|
+
{
|
|
241
|
+
title: "List Ennodia plan advice",
|
|
242
|
+
description:
|
|
243
|
+
"List recent Plan Advisor requests started by this Ennodia MCP server process.",
|
|
244
|
+
inputSchema: {
|
|
245
|
+
includeProposal: z
|
|
246
|
+
.boolean()
|
|
247
|
+
.default(false)
|
|
248
|
+
.describe("Include the untrusted model-authored proposal when available."),
|
|
249
|
+
includePlan: z
|
|
250
|
+
.boolean()
|
|
251
|
+
.default(false)
|
|
252
|
+
.describe("Include the validated inert execution plan when ready."),
|
|
253
|
+
includeEvents: z
|
|
254
|
+
.boolean()
|
|
255
|
+
.default(false)
|
|
256
|
+
.describe("Include bounded Plan Advisor event history."),
|
|
257
|
+
maxEvents: z
|
|
258
|
+
.number()
|
|
259
|
+
.int()
|
|
260
|
+
.nonnegative()
|
|
261
|
+
.max(300)
|
|
262
|
+
.default(25)
|
|
263
|
+
.describe(
|
|
264
|
+
"Maximum Plan Advisor events per item when includeEvents is true.",
|
|
265
|
+
),
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
async (options) => jsonResult(core.listPlanAdvice(options)),
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
server.registerTool(
|
|
272
|
+
"ennodia_get_plan_advice",
|
|
273
|
+
{
|
|
274
|
+
title: "Get Ennodia plan advice",
|
|
275
|
+
description:
|
|
276
|
+
"Inspect Plan Advisor status, validation issues, frozen inventory identity, proposal, validated plan, digest, budgets, events, and ETA. A plan can be launched only when status is ready. An authorized plan has status consumed and cannot run again.",
|
|
277
|
+
inputSchema: {
|
|
278
|
+
adviceId: z
|
|
279
|
+
.string()
|
|
280
|
+
.min(1)
|
|
281
|
+
.describe("Plan advice ID returned by ennodia_start_plan_advice."),
|
|
282
|
+
includeProposal: z
|
|
283
|
+
.boolean()
|
|
284
|
+
.default(true)
|
|
285
|
+
.describe("Include the untrusted model-authored proposal when available."),
|
|
286
|
+
includePlan: z
|
|
287
|
+
.boolean()
|
|
288
|
+
.default(true)
|
|
289
|
+
.describe("Include the validated inert execution plan when ready."),
|
|
290
|
+
includeEvents: z
|
|
291
|
+
.boolean()
|
|
292
|
+
.default(true)
|
|
293
|
+
.describe("Include bounded Plan Advisor event history."),
|
|
294
|
+
maxEvents: z
|
|
295
|
+
.number()
|
|
296
|
+
.int()
|
|
297
|
+
.nonnegative()
|
|
298
|
+
.max(300)
|
|
299
|
+
.default(100)
|
|
300
|
+
.describe("Maximum Plan Advisor events to include. Use 0 to omit events."),
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
async ({ adviceId, ...options }) => {
|
|
304
|
+
const advice = core.getPlanAdvice(adviceId, options);
|
|
305
|
+
if (!advice) {
|
|
306
|
+
throw new Error(`Unknown plan advice: ${adviceId}`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return jsonResult(advice);
|
|
310
|
+
},
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
server.registerTool(
|
|
314
|
+
"ennodia_cancel_plan_advice",
|
|
315
|
+
{
|
|
316
|
+
title: "Cancel Ennodia plan advice",
|
|
317
|
+
description: "Cancel a running Plan Advisor request and its Advisor task.",
|
|
318
|
+
inputSchema: {
|
|
319
|
+
adviceId: z
|
|
320
|
+
.string()
|
|
321
|
+
.min(1)
|
|
322
|
+
.describe("Plan advice ID returned by ennodia_start_plan_advice."),
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
async ({ adviceId }) => jsonResult(core.cancelPlanAdvice(adviceId)),
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
server.registerTool(
|
|
329
|
+
"ennodia_start_advised_plan",
|
|
330
|
+
{
|
|
331
|
+
title: "Start an Ennodia advised plan",
|
|
332
|
+
description:
|
|
333
|
+
"Explicitly launch the exact validated worker plan from a ready Plan Advisor request. Ennodia re-checks the caller-supplied digest, current harness and skill inventory, caller allowlisted model assignments, and budget before starting the first worker task; any mismatch fails closed with zero launches. A plan is single-use after authorization. Provider model availability remains unverified until the harness runs.",
|
|
334
|
+
inputSchema: {
|
|
335
|
+
adviceId: z
|
|
336
|
+
.string()
|
|
337
|
+
.min(1)
|
|
338
|
+
.describe("Ready plan advice ID returned by ennodia_start_plan_advice."),
|
|
339
|
+
expectedPlanDigest: z
|
|
340
|
+
.string()
|
|
341
|
+
.min(1)
|
|
342
|
+
.describe(
|
|
343
|
+
"Exact planDigest returned by ennodia_get_plan_advice for explicit, stale-plan-safe execution.",
|
|
344
|
+
),
|
|
345
|
+
cwd: z
|
|
346
|
+
.string()
|
|
347
|
+
.optional()
|
|
348
|
+
.describe(
|
|
349
|
+
"Working directory for worker tasks. Omit to reuse the directory whose skills were inventoried.",
|
|
350
|
+
),
|
|
351
|
+
isolateCwd: z
|
|
352
|
+
.boolean()
|
|
353
|
+
.optional()
|
|
354
|
+
.describe(
|
|
355
|
+
"Run each worker against an ephemeral isolated copy of cwd so parallel writes cannot clobber each other. Isolation fails before task spawn if the copied tree contains a symbolic link. The execution path is reported as the task cwd for traceability and deleted when the task becomes terminal.",
|
|
356
|
+
),
|
|
357
|
+
timeoutMs: z
|
|
358
|
+
.number()
|
|
359
|
+
.int()
|
|
360
|
+
.positive()
|
|
361
|
+
.max(60 * 60 * 1000)
|
|
362
|
+
.optional()
|
|
363
|
+
.describe(
|
|
364
|
+
"Per-worker timeout in milliseconds, capped at one hour.",
|
|
365
|
+
),
|
|
366
|
+
budget: budgetSchema.optional(),
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
async (input) => jsonResult(await core.startAdvisedPlan(input)),
|
|
370
|
+
);
|
|
371
|
+
|
|
155
372
|
server.registerTool(
|
|
156
373
|
"ennodia_estimate_budget",
|
|
157
374
|
{
|
|
@@ -180,7 +397,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
180
397
|
.union([z.literal("auto"), z.boolean()])
|
|
181
398
|
.default("auto")
|
|
182
399
|
.describe(
|
|
183
|
-
"Whether
|
|
400
|
+
"Whether the Judge + Result Advisor comparison should be included in the estimate. auto follows the planner.",
|
|
184
401
|
),
|
|
185
402
|
refresh: z
|
|
186
403
|
.boolean()
|
|
@@ -193,7 +410,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
193
410
|
.max(200_000)
|
|
194
411
|
.optional()
|
|
195
412
|
.describe(
|
|
196
|
-
"Maximum characters from each successful task output assumed for
|
|
413
|
+
"Maximum characters from each successful task output assumed for Judge + Result Advisor input.",
|
|
197
414
|
),
|
|
198
415
|
budget: budgetSchema.optional(),
|
|
199
416
|
},
|
|
@@ -206,13 +423,13 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
206
423
|
{
|
|
207
424
|
title: "Estimate compositional Ennodia budget",
|
|
208
425
|
description:
|
|
209
|
-
"Resolve focused compositional slices to harnesses and estimate child-task and
|
|
426
|
+
"Resolve focused compositional slices to harnesses and estimate child-task and later Judge + Result Advisor budget without starting child processes.",
|
|
210
427
|
inputSchema: {
|
|
211
428
|
prompt: z
|
|
212
429
|
.string()
|
|
213
430
|
.min(1)
|
|
214
431
|
.describe(
|
|
215
|
-
"Overall
|
|
432
|
+
"Overall task or question that every slice belongs to.",
|
|
216
433
|
),
|
|
217
434
|
slices: z
|
|
218
435
|
.array(compositionalSliceSchema)
|
|
@@ -235,13 +452,13 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
235
452
|
.array(z.string())
|
|
236
453
|
.optional()
|
|
237
454
|
.describe(
|
|
238
|
-
"
|
|
455
|
+
"Default installed native skill IDs for slices that omit slice.skillIds. A slice-level list, including [], replaces this default.",
|
|
239
456
|
),
|
|
240
457
|
includeCompareEstimate: z
|
|
241
458
|
.boolean()
|
|
242
459
|
.default(true)
|
|
243
460
|
.describe(
|
|
244
|
-
"Include a later
|
|
461
|
+
"Include a later Judge + Result Advisor pass in the returned preflight budget estimate.",
|
|
245
462
|
),
|
|
246
463
|
maxOutputChars: z
|
|
247
464
|
.number()
|
|
@@ -250,7 +467,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
250
467
|
.max(200_000)
|
|
251
468
|
.optional()
|
|
252
469
|
.describe(
|
|
253
|
-
"Maximum characters per successful slice output assumed for a later
|
|
470
|
+
"Maximum characters per successful slice output assumed for a later Judge + Result Advisor estimate.",
|
|
254
471
|
),
|
|
255
472
|
budget: budgetSchema.optional(),
|
|
256
473
|
},
|
|
@@ -263,7 +480,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
263
480
|
{
|
|
264
481
|
title: "Start an Ennodia task",
|
|
265
482
|
description:
|
|
266
|
-
"Start raw child harness tasks without run-level
|
|
483
|
+
"Start raw child harness tasks without a run-level Judge + Result Advisor pass. Use for debugging, direct harness calls, or manual comparison workflows; prefer ennodia_run for normal end-to-end use.",
|
|
267
484
|
inputSchema: {
|
|
268
485
|
prompt: z
|
|
269
486
|
.string()
|
|
@@ -286,6 +503,12 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
286
503
|
.string()
|
|
287
504
|
.optional()
|
|
288
505
|
.describe("Working directory for child harness commands."),
|
|
506
|
+
isolateCwd: z
|
|
507
|
+
.boolean()
|
|
508
|
+
.optional()
|
|
509
|
+
.describe(
|
|
510
|
+
"Run each task against an ephemeral isolated copy of cwd instead of cwd itself. Use this whenever starting more than one task against the same cwd (e.g. comparing skills or harnesses), so concurrent file writes cannot clobber each other. Isolation fails before task spawn if the copied tree contains a symbolic link. The reported task cwd is an execution trace; its temporary directory is deleted when the task becomes terminal.",
|
|
511
|
+
),
|
|
289
512
|
model: z
|
|
290
513
|
.string()
|
|
291
514
|
.optional()
|
|
@@ -320,13 +543,13 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
320
543
|
{
|
|
321
544
|
title: "Start compositional Ennodia tasks",
|
|
322
545
|
description:
|
|
323
|
-
"Start one focused child task per slice for compositional reviews. Poll the returned task IDs, then pass useful completed task IDs to ennodia_start_compare for
|
|
546
|
+
"Start one focused child task per slice for compositional reviews. Poll the returned task IDs, then pass useful completed task IDs to ennodia_start_compare for a Judge + Result Advisor comparison.",
|
|
324
547
|
inputSchema: {
|
|
325
548
|
prompt: z
|
|
326
549
|
.string()
|
|
327
550
|
.min(1)
|
|
328
551
|
.describe(
|
|
329
|
-
"Overall
|
|
552
|
+
"Overall task or question that every slice belongs to.",
|
|
330
553
|
),
|
|
331
554
|
slices: z
|
|
332
555
|
.array(compositionalSliceSchema)
|
|
@@ -339,6 +562,12 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
339
562
|
.string()
|
|
340
563
|
.optional()
|
|
341
564
|
.describe("Working directory for child harness commands."),
|
|
565
|
+
isolateCwd: z
|
|
566
|
+
.boolean()
|
|
567
|
+
.optional()
|
|
568
|
+
.describe(
|
|
569
|
+
"Run each slice's task against an ephemeral isolated copy of cwd instead of cwd itself, so slices that write files cannot clobber each other. Isolation fails before task spawn if the copied tree contains a symbolic link. The reported task cwd is an execution trace; its temporary directory is deleted when the task becomes terminal.",
|
|
570
|
+
),
|
|
342
571
|
timeoutMs: z
|
|
343
572
|
.number()
|
|
344
573
|
.int()
|
|
@@ -356,13 +585,13 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
356
585
|
.array(z.string())
|
|
357
586
|
.optional()
|
|
358
587
|
.describe(
|
|
359
|
-
"
|
|
588
|
+
"Default installed native skill IDs for slices that omit slice.skillIds. A slice-level list, including [], replaces this default.",
|
|
360
589
|
),
|
|
361
590
|
includeCompareEstimate: z
|
|
362
591
|
.boolean()
|
|
363
592
|
.default(true)
|
|
364
593
|
.describe(
|
|
365
|
-
"Include a later
|
|
594
|
+
"Include a later Judge + Result Advisor pass in the returned preflight budget estimate.",
|
|
366
595
|
),
|
|
367
596
|
maxOutputChars: z
|
|
368
597
|
.number()
|
|
@@ -371,7 +600,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
371
600
|
.max(200_000)
|
|
372
601
|
.optional()
|
|
373
602
|
.describe(
|
|
374
|
-
"Maximum characters per successful slice output assumed for a later
|
|
603
|
+
"Maximum characters per successful slice output assumed for a later Judge + Result Advisor estimate.",
|
|
375
604
|
),
|
|
376
605
|
budget: budgetSchema.optional(),
|
|
377
606
|
},
|
|
@@ -417,12 +646,18 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
417
646
|
.union([z.literal("auto"), z.boolean()])
|
|
418
647
|
.default("auto")
|
|
419
648
|
.describe(
|
|
420
|
-
"Whether to run
|
|
649
|
+
"Whether to run the Judge + Result Advisor after tasks finish. auto compares when the planner sees value and at least two tasks produce output.",
|
|
421
650
|
),
|
|
422
651
|
cwd: z
|
|
423
652
|
.string()
|
|
424
653
|
.optional()
|
|
425
654
|
.describe("Working directory for child harness commands."),
|
|
655
|
+
isolateCwd: z
|
|
656
|
+
.boolean()
|
|
657
|
+
.optional()
|
|
658
|
+
.describe(
|
|
659
|
+
"Run each selected harness against an ephemeral isolated copy of cwd instead of cwd itself. Use this in parallel mode or whenever comparing skills/harnesses against the same cwd, so concurrent file writes cannot clobber each other. Isolation fails before task spawn if the copied tree contains a symbolic link. The reported task cwd is an execution trace; its temporary directory is deleted when the task becomes terminal.",
|
|
660
|
+
),
|
|
426
661
|
model: z
|
|
427
662
|
.string()
|
|
428
663
|
.optional()
|
|
@@ -444,22 +679,34 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
444
679
|
.string()
|
|
445
680
|
.optional()
|
|
446
681
|
.describe(
|
|
447
|
-
`Harness to use as the
|
|
682
|
+
`Harness to use as the comparison Judge. Omit to use the default priority: ${comparePriorityText}.`,
|
|
448
683
|
),
|
|
449
684
|
judgeModel: z
|
|
450
685
|
.string()
|
|
451
686
|
.optional()
|
|
452
|
-
.describe("Optional model override for the
|
|
687
|
+
.describe("Optional model override for the comparison Judge."),
|
|
688
|
+
advisorHarnessId: z
|
|
689
|
+
.string()
|
|
690
|
+
.optional()
|
|
691
|
+
.describe(
|
|
692
|
+
"Harness that runs the Result Advisor after the Judge. Defaults to the judge harness selection.",
|
|
693
|
+
),
|
|
694
|
+
advisorModel: z
|
|
695
|
+
.string()
|
|
696
|
+
.optional()
|
|
697
|
+
.describe("Optional model override for the Result Advisor."),
|
|
453
698
|
synthesizerHarnessId: z
|
|
454
699
|
.string()
|
|
455
700
|
.optional()
|
|
456
701
|
.describe(
|
|
457
|
-
"
|
|
702
|
+
"Deprecated alias for advisorHarnessId. Do not send both fields with different values.",
|
|
458
703
|
),
|
|
459
704
|
synthesizerModel: z
|
|
460
705
|
.string()
|
|
461
706
|
.optional()
|
|
462
|
-
.describe(
|
|
707
|
+
.describe(
|
|
708
|
+
"Deprecated alias for advisorModel. Do not send both fields with different values.",
|
|
709
|
+
),
|
|
463
710
|
maxOutputChars: z
|
|
464
711
|
.number()
|
|
465
712
|
.int()
|
|
@@ -467,7 +714,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
467
714
|
.max(200_000)
|
|
468
715
|
.optional()
|
|
469
716
|
.describe(
|
|
470
|
-
"Maximum characters from each successful task output to pass into
|
|
717
|
+
"Maximum characters from each successful task output to pass into the Judge + Result Advisor workflow. Use 0 to suppress candidate text.",
|
|
471
718
|
),
|
|
472
719
|
skillIds: z
|
|
473
720
|
.array(z.string())
|
|
@@ -517,7 +764,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
517
764
|
{
|
|
518
765
|
title: "List durable Ennodia run history",
|
|
519
766
|
description:
|
|
520
|
-
"Read terminal run receipts persisted under the local Ennodia history directory. Use after a restart to inspect previous final answers and
|
|
767
|
+
"Read terminal run receipts persisted under the local Ennodia history directory. Use after a restart to inspect previous final answers and Judge disagreement analysis.",
|
|
521
768
|
inputSchema: {
|
|
522
769
|
limit: z
|
|
523
770
|
.number()
|
|
@@ -536,7 +783,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
536
783
|
{
|
|
537
784
|
title: "Get Ennodia run",
|
|
538
785
|
description:
|
|
539
|
-
"Inspect run status, selected harnesses, child task IDs,
|
|
786
|
+
"Inspect run status, selected harnesses, child task IDs, comparison ID, final Advisor answer, events, and ETA.",
|
|
540
787
|
inputSchema: {
|
|
541
788
|
runId: z.string().min(1).describe("Run ID returned by ennodia_run."),
|
|
542
789
|
includeEvents: z
|
|
@@ -575,7 +822,8 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
575
822
|
"ennodia_cancel_run",
|
|
576
823
|
{
|
|
577
824
|
title: "Cancel Ennodia run",
|
|
578
|
-
description:
|
|
825
|
+
description:
|
|
826
|
+
"Cancel a high-level run and any active child task, Judge, or Result Advisor.",
|
|
579
827
|
inputSchema: {
|
|
580
828
|
runId: z.string().min(1).describe("Run ID returned by ennodia_run."),
|
|
581
829
|
},
|
|
@@ -623,7 +871,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
623
871
|
{
|
|
624
872
|
title: "Get compositional Ennodia status",
|
|
625
873
|
description:
|
|
626
|
-
"Inspect a batch of compositional shard tasks, group running and terminal states, and return
|
|
874
|
+
"Inspect a batch of compositional shard tasks, group running and terminal states, and return successful task IDs ready for Judge + Result Advisor comparison.",
|
|
627
875
|
inputSchema: {
|
|
628
876
|
taskIds: z
|
|
629
877
|
.array(z.string().min(1).describe("Task ID returned by a compositional start."))
|
|
@@ -634,7 +882,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
634
882
|
.string()
|
|
635
883
|
.optional()
|
|
636
884
|
.describe(
|
|
637
|
-
"Optional
|
|
885
|
+
"Optional comparison prompt to include in the returned compareNext object.",
|
|
638
886
|
),
|
|
639
887
|
minSuccessfulTasksForCompare: z
|
|
640
888
|
.number()
|
|
@@ -678,9 +926,9 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
678
926
|
server.registerTool(
|
|
679
927
|
"ennodia_start_compare",
|
|
680
928
|
{
|
|
681
|
-
title: "Start Ennodia
|
|
929
|
+
title: "Start Ennodia Judge + Result Advisor",
|
|
682
930
|
description:
|
|
683
|
-
"Compare completed Ennodia task outputs or caller-supplied responses.
|
|
931
|
+
"Compare completed Ennodia task outputs or caller-supplied responses. The Judge maps agreements, contradictions, and risks; the Result Advisor then combines that analysis into the final answer. Returns a Compare ID to inspect with ennodia_get_compare.",
|
|
684
932
|
inputSchema: {
|
|
685
933
|
prompt: z
|
|
686
934
|
.string()
|
|
@@ -718,26 +966,38 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
718
966
|
.string()
|
|
719
967
|
.optional()
|
|
720
968
|
.describe(
|
|
721
|
-
`Harness to use as the
|
|
969
|
+
`Harness to use as the comparison Judge. Omit to use the default priority: ${comparePriorityText}.`,
|
|
722
970
|
),
|
|
723
971
|
judgeModel: z
|
|
724
972
|
.string()
|
|
725
973
|
.optional()
|
|
726
|
-
.describe("Optional model override for the
|
|
974
|
+
.describe("Optional model override for the comparison Judge."),
|
|
975
|
+
advisorHarnessId: z
|
|
976
|
+
.string()
|
|
977
|
+
.optional()
|
|
978
|
+
.describe(
|
|
979
|
+
"Harness that runs the Result Advisor after the Judge. Defaults to the judge harness selection.",
|
|
980
|
+
),
|
|
981
|
+
advisorModel: z
|
|
982
|
+
.string()
|
|
983
|
+
.optional()
|
|
984
|
+
.describe("Optional model override for the Result Advisor."),
|
|
727
985
|
synthesizerHarnessId: z
|
|
728
986
|
.string()
|
|
729
987
|
.optional()
|
|
730
988
|
.describe(
|
|
731
|
-
"
|
|
989
|
+
"Deprecated alias for advisorHarnessId. Do not send both fields with different values.",
|
|
732
990
|
),
|
|
733
991
|
synthesizerModel: z
|
|
734
992
|
.string()
|
|
735
993
|
.optional()
|
|
736
|
-
.describe(
|
|
994
|
+
.describe(
|
|
995
|
+
"Deprecated alias for advisorModel. Do not send both fields with different values.",
|
|
996
|
+
),
|
|
737
997
|
cwd: z
|
|
738
998
|
.string()
|
|
739
999
|
.optional()
|
|
740
|
-
.describe("Working directory for
|
|
1000
|
+
.describe("Working directory for Judge and Result Advisor child tasks."),
|
|
741
1001
|
timeoutMs: z
|
|
742
1002
|
.number()
|
|
743
1003
|
.int()
|
|
@@ -745,7 +1005,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
745
1005
|
.max(60 * 60 * 1000)
|
|
746
1006
|
.optional()
|
|
747
1007
|
.describe(
|
|
748
|
-
"Per-child timeout for
|
|
1008
|
+
"Per-child timeout for Judge and Result Advisor tasks in milliseconds, capped at one hour.",
|
|
749
1009
|
),
|
|
750
1010
|
maxOutputChars: z
|
|
751
1011
|
.number()
|
|
@@ -754,7 +1014,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
754
1014
|
.max(200_000)
|
|
755
1015
|
.optional()
|
|
756
1016
|
.describe(
|
|
757
|
-
"Maximum characters from each task output to include as a
|
|
1017
|
+
"Maximum characters from each task output to include as a comparison candidate. Use 0 to suppress task output text.",
|
|
758
1018
|
),
|
|
759
1019
|
budget: budgetSchema.optional(),
|
|
760
1020
|
},
|
|
@@ -765,17 +1025,18 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
765
1025
|
server.registerTool(
|
|
766
1026
|
"ennodia_list_compares",
|
|
767
1027
|
{
|
|
768
|
-
title: "List Ennodia
|
|
769
|
-
description:
|
|
1028
|
+
title: "List Ennodia Judge + Advisor comparisons",
|
|
1029
|
+
description:
|
|
1030
|
+
"List Judge + Result Advisor comparisons started by this Ennodia MCP server process.",
|
|
770
1031
|
inputSchema: {
|
|
771
1032
|
includeCandidates: z
|
|
772
1033
|
.boolean()
|
|
773
1034
|
.default(false)
|
|
774
|
-
.describe("Include bounded candidate response previews for each
|
|
1035
|
+
.describe("Include bounded candidate response previews for each comparison."),
|
|
775
1036
|
includeEvents: z
|
|
776
1037
|
.boolean()
|
|
777
1038
|
.default(false)
|
|
778
|
-
.describe("Include bounded
|
|
1039
|
+
.describe("Include bounded Judge + Result Advisor event history."),
|
|
779
1040
|
maxCandidateChars: z
|
|
780
1041
|
.number()
|
|
781
1042
|
.int()
|
|
@@ -792,7 +1053,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
792
1053
|
.max(300)
|
|
793
1054
|
.default(25)
|
|
794
1055
|
.describe(
|
|
795
|
-
"Maximum
|
|
1056
|
+
"Maximum comparison events to include when includeEvents is true.",
|
|
796
1057
|
),
|
|
797
1058
|
},
|
|
798
1059
|
},
|
|
@@ -802,9 +1063,9 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
802
1063
|
server.registerTool(
|
|
803
1064
|
"ennodia_get_compare",
|
|
804
1065
|
{
|
|
805
|
-
title: "Get Ennodia
|
|
1066
|
+
title: "Get Ennodia Judge + Result Advisor comparison",
|
|
806
1067
|
description:
|
|
807
|
-
"Inspect
|
|
1068
|
+
"Inspect comparison status, candidate inputs, Judge analysis, Result Advisor answer, child task IDs, degradation state, and ETA.",
|
|
808
1069
|
inputSchema: {
|
|
809
1070
|
compareId: z
|
|
810
1071
|
.string()
|
|
@@ -817,7 +1078,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
817
1078
|
includeEvents: z
|
|
818
1079
|
.boolean()
|
|
819
1080
|
.default(true)
|
|
820
|
-
.describe("Include bounded
|
|
1081
|
+
.describe("Include bounded Judge + Result Advisor event history."),
|
|
821
1082
|
maxCandidateChars: z
|
|
822
1083
|
.number()
|
|
823
1084
|
.int()
|
|
@@ -833,7 +1094,7 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
833
1094
|
.nonnegative()
|
|
834
1095
|
.max(300)
|
|
835
1096
|
.default(100)
|
|
836
|
-
.describe("Maximum
|
|
1097
|
+
.describe("Maximum comparison events to include. Use 0 to omit events."),
|
|
837
1098
|
},
|
|
838
1099
|
},
|
|
839
1100
|
async ({ compareId, ...options }) => {
|
|
@@ -849,8 +1110,9 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
849
1110
|
server.registerTool(
|
|
850
1111
|
"ennodia_cancel_compare",
|
|
851
1112
|
{
|
|
852
|
-
title: "Cancel Ennodia
|
|
853
|
-
description:
|
|
1113
|
+
title: "Cancel Ennodia Judge + Result Advisor comparison",
|
|
1114
|
+
description:
|
|
1115
|
+
"Cancel a running Judge + Result Advisor comparison and its active child task.",
|
|
854
1116
|
inputSchema: {
|
|
855
1117
|
compareId: z
|
|
856
1118
|
.string()
|
|
@@ -870,7 +1132,9 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
870
1132
|
taskId: z
|
|
871
1133
|
.string()
|
|
872
1134
|
.min(1)
|
|
873
|
-
.describe(
|
|
1135
|
+
.describe(
|
|
1136
|
+
"Task ID returned by a raw, compositional, advised-plan, run, Plan Advisor, or Compare start.",
|
|
1137
|
+
),
|
|
874
1138
|
includeOutput: z
|
|
875
1139
|
.boolean()
|
|
876
1140
|
.default(true)
|
|
@@ -916,7 +1180,9 @@ export function createEnnodiaServer(core: EnnodiaCore = defaultCore): McpServer
|
|
|
916
1180
|
taskId: z
|
|
917
1181
|
.string()
|
|
918
1182
|
.min(1)
|
|
919
|
-
.describe(
|
|
1183
|
+
.describe(
|
|
1184
|
+
"Task ID returned by a raw, compositional, advised-plan, run, Plan Advisor, or Compare start.",
|
|
1185
|
+
),
|
|
920
1186
|
},
|
|
921
1187
|
},
|
|
922
1188
|
async ({ taskId }) => jsonResult(core.cancelTask(taskId)),
|