@tangle-network/agent-runtime 0.53.0 → 0.54.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 +27 -16
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +5 -3
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +1 -1
- package/dist/analyst-loop.js +2 -2
- package/dist/{chunk-K5M3SHEU.js → chunk-2BDXWZUC.js} +5 -34
- package/dist/chunk-2BDXWZUC.js.map +1 -0
- package/dist/chunk-A73RADPB.js +281 -0
- package/dist/chunk-A73RADPB.js.map +1 -0
- package/dist/chunk-FRBWCJLP.js +396 -0
- package/dist/chunk-FRBWCJLP.js.map +1 -0
- package/dist/chunk-GRAGM4MC.js +72 -0
- package/dist/chunk-GRAGM4MC.js.map +1 -0
- package/dist/{chunk-K6WP7PYW.js → chunk-JTH2FPCK.js} +3231 -424
- package/dist/chunk-JTH2FPCK.js.map +1 -0
- package/dist/{chunk-P4QNEXFC.js → chunk-KJH62YEK.js} +2 -2
- package/dist/{chunk-HNUXAZIJ.js → chunk-P5OKDSLB.js} +2 -2
- package/dist/{chunk-GSUO5QS6.js → chunk-VLF5RHEQ.js} +2 -5
- package/dist/{chunk-GSUO5QS6.js.map → chunk-VLF5RHEQ.js.map} +1 -1
- package/dist/{chunk-JFIYKDXF.js → chunk-XRYEZPR6.js} +2 -1
- package/dist/chunk-XRYEZPR6.js.map +1 -0
- package/dist/{coder-LKm3Mczw.d.ts → coder-CEkUFv8h.d.ts} +1 -1
- package/dist/{types-CNDJCL_0.d.ts → coordination-BMzskrUR.d.ts} +268 -2
- package/dist/{kb-gate-CKfykcYQ.d.ts → delegates-BPLIl8EC.d.ts} +491 -566
- package/dist/index.d.ts +7 -7
- package/dist/index.js +23 -80
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +2 -2
- package/dist/kb-gate-CuzMYGYM.d.ts +76 -0
- package/dist/{loop-runner-bin-D4Ir7b00.d.ts → loop-runner-bin-BGpVVyXp.d.ts} +6 -27
- package/dist/loop-runner-bin.d.ts +5 -5
- package/dist/loop-runner-bin.js +6 -5
- package/dist/loops.d.ts +8 -6
- package/dist/loops.js +32 -8
- package/dist/mcp/bin.js +94 -30
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +9 -272
- package/dist/mcp/index.js +45 -365
- package/dist/mcp/index.js.map +1 -1
- package/dist/{openai-tools-CKfR3EMh.d.ts → openai-tools-CoeLQ7Uo.d.ts} +1 -1
- package/dist/profiles.d.ts +2 -2
- package/dist/profiles.js +4 -4
- package/dist/{router-client-B0Qi1NiN.d.ts → router-client-30Y_pca8.d.ts} +1 -1
- package/dist/{run-loop-DgVhucoR.d.ts → run-loop-DluzfJ2h.d.ts} +1 -1
- package/dist/runtime.d.ts +424 -23
- package/dist/runtime.js +32 -8
- package/dist/topology.d.ts +54 -1
- package/dist/topology.js +222 -0
- package/dist/topology.js.map +1 -1
- package/dist/{types-CklkW4Eh.d.ts → types-C8rNlxfV.d.ts} +4 -4
- package/dist/workflow.d.ts +2 -2
- package/dist/workflow.js +4 -2
- package/dist/workflow.js.map +1 -1
- package/package.json +5 -5
- package/skills/agent-runtime-adoption/SKILL.md +54 -46
- package/skills/build-with-agent-runtime/SKILL.md +12 -8
- package/skills/loop-writer/SKILL.md +9 -1
- package/skills/supervise/SKILL.md +24 -0
- package/dist/chunk-5M2WDWBI.js +0 -908
- package/dist/chunk-5M2WDWBI.js.map +0 -1
- package/dist/chunk-AYRQZRDV.js +0 -623
- package/dist/chunk-AYRQZRDV.js.map +0 -1
- package/dist/chunk-FO4DCM7R.js +0 -1356
- package/dist/chunk-FO4DCM7R.js.map +0 -1
- package/dist/chunk-JFIYKDXF.js.map +0 -1
- package/dist/chunk-K5M3SHEU.js.map +0 -1
- package/dist/chunk-K6WP7PYW.js.map +0 -1
- package/dist/driver-B2RKkVJW.d.ts +0 -221
- /package/dist/{chunk-P4QNEXFC.js.map → chunk-KJH62YEK.js.map} +0 -0
- /package/dist/{chunk-HNUXAZIJ.js.map → chunk-P5OKDSLB.js.map} +0 -0
package/dist/mcp/index.js
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DELEGATE_UI_AUDIT_DESCRIPTION,
|
|
3
|
-
DELEGATE_UI_AUDIT_INPUT_SCHEMA,
|
|
4
|
-
DELEGATE_UI_AUDIT_TOOL_NAME,
|
|
5
2
|
captureWorktreeDiff,
|
|
6
|
-
createDelegateUiAuditHandler,
|
|
7
3
|
createInProcessExecutor,
|
|
8
|
-
createInProcessTransport,
|
|
9
|
-
createMcpServer,
|
|
10
4
|
createPropagatingTraceEmitter,
|
|
11
5
|
createWorktree,
|
|
12
6
|
detectExecutor,
|
|
13
7
|
readTraceContextFromEnv,
|
|
14
8
|
removeWorktree,
|
|
15
|
-
traceContextToEnv
|
|
16
|
-
|
|
17
|
-
} from "../chunk-5M2WDWBI.js";
|
|
18
|
-
import "../chunk-WIR4HOOJ.js";
|
|
9
|
+
traceContextToEnv
|
|
10
|
+
} from "../chunk-FRBWCJLP.js";
|
|
19
11
|
import {
|
|
20
12
|
mcpToolsForRuntimeMcp,
|
|
21
13
|
mcpToolsForRuntimeMcpSubset
|
|
22
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-KJH62YEK.js";
|
|
15
|
+
import {
|
|
16
|
+
createKbGate
|
|
17
|
+
} from "../chunk-FNMGYYSS.js";
|
|
18
|
+
import {
|
|
19
|
+
coderTaskFromArgs,
|
|
20
|
+
createDefaultCoderDelegate,
|
|
21
|
+
createFleetWorkspaceExecutor,
|
|
22
|
+
createSiblingSandboxExecutor,
|
|
23
|
+
settleDetachedCoderTurn
|
|
24
|
+
} from "../chunk-A73RADPB.js";
|
|
25
|
+
import "../chunk-KADIJAD4.js";
|
|
26
|
+
import {
|
|
27
|
+
runLocalHarness
|
|
28
|
+
} from "../chunk-GLR25NG7.js";
|
|
29
|
+
import {
|
|
30
|
+
DELEGATION_MCP_SERVER_KEY,
|
|
31
|
+
buildDelegationMcpServer,
|
|
32
|
+
composeProductionAgentProfile
|
|
33
|
+
} from "../chunk-XRYEZPR6.js";
|
|
23
34
|
import {
|
|
24
35
|
DELEGATE_CODE_DESCRIPTION,
|
|
25
36
|
DELEGATE_CODE_INPUT_SCHEMA,
|
|
@@ -30,66 +41,54 @@ import {
|
|
|
30
41
|
DELEGATE_RESEARCH_DESCRIPTION,
|
|
31
42
|
DELEGATE_RESEARCH_INPUT_SCHEMA,
|
|
32
43
|
DELEGATE_RESEARCH_TOOL_NAME,
|
|
44
|
+
DELEGATE_UI_AUDIT_DESCRIPTION,
|
|
45
|
+
DELEGATE_UI_AUDIT_INPUT_SCHEMA,
|
|
46
|
+
DELEGATE_UI_AUDIT_TOOL_NAME,
|
|
33
47
|
DELEGATION_HISTORY_DESCRIPTION,
|
|
34
48
|
DELEGATION_HISTORY_INPUT_SCHEMA,
|
|
35
49
|
DELEGATION_HISTORY_TOOL_NAME,
|
|
36
50
|
DELEGATION_STATUS_DESCRIPTION,
|
|
37
51
|
DELEGATION_STATUS_INPUT_SCHEMA,
|
|
38
52
|
DELEGATION_STATUS_TOOL_NAME,
|
|
53
|
+
DELEGATION_TRACE_MAX_BYTES,
|
|
54
|
+
DELEGATION_TRACE_MAX_SPANS,
|
|
39
55
|
DelegationPersistenceError,
|
|
40
56
|
DelegationStateCorruptError,
|
|
41
57
|
DelegationTaskQueue,
|
|
42
58
|
FileDelegationStore,
|
|
43
59
|
InMemoryDelegationStore,
|
|
44
60
|
InMemoryFeedbackStore,
|
|
61
|
+
assertTraceDerivedFindings,
|
|
62
|
+
buildDelegationTraceSpans,
|
|
63
|
+
capDelegationTrace,
|
|
64
|
+
composeLoopTraceEmitters,
|
|
65
|
+
createCoordinationTools,
|
|
45
66
|
createDelegateCodeHandler,
|
|
46
67
|
createDelegateFeedbackHandler,
|
|
47
68
|
createDelegateResearchHandler,
|
|
69
|
+
createDelegateUiAuditHandler,
|
|
48
70
|
createDelegationHistoryHandler,
|
|
49
71
|
createDelegationStatusHandler,
|
|
72
|
+
createDelegationTraceCollector,
|
|
73
|
+
createDriveTurnResumeDriver,
|
|
74
|
+
createInProcessTransport,
|
|
75
|
+
createMcpServer,
|
|
76
|
+
detachedTurnEvents,
|
|
50
77
|
eventToSnapshot,
|
|
78
|
+
formatDetachedSessionRef,
|
|
51
79
|
hashIdempotencyInput,
|
|
80
|
+
parseDetachedSessionRef,
|
|
81
|
+
runDetachedTurn,
|
|
52
82
|
validateDelegateCodeArgs,
|
|
53
83
|
validateDelegateFeedbackArgs,
|
|
54
84
|
validateDelegateResearchArgs,
|
|
85
|
+
validateDelegateUiAuditArgs,
|
|
55
86
|
validateDelegationHistoryArgs,
|
|
56
87
|
validateDelegationStatusArgs
|
|
57
|
-
} from "../chunk-
|
|
58
|
-
import
|
|
59
|
-
|
|
60
|
-
} from "../chunk-FNMGYYSS.js";
|
|
61
|
-
import {
|
|
62
|
-
DELEGATION_TRACE_MAX_BYTES,
|
|
63
|
-
DELEGATION_TRACE_MAX_SPANS,
|
|
64
|
-
buildDelegationTraceSpans,
|
|
65
|
-
capDelegationTrace,
|
|
66
|
-
coderTaskFromArgs,
|
|
67
|
-
composeLoopTraceEmitters,
|
|
68
|
-
createDefaultCoderDelegate,
|
|
69
|
-
createDelegationTraceCollector,
|
|
70
|
-
createDriveTurnResumeDriver,
|
|
71
|
-
createFleetWorkspaceExecutor,
|
|
72
|
-
createSiblingSandboxExecutor,
|
|
73
|
-
detachedTurnEvents,
|
|
74
|
-
formatDetachedSessionRef,
|
|
75
|
-
parseDetachedSessionRef,
|
|
76
|
-
runDetachedTurn,
|
|
77
|
-
settleDetachedCoderTurn
|
|
78
|
-
} from "../chunk-AYRQZRDV.js";
|
|
79
|
-
import "../chunk-KADIJAD4.js";
|
|
80
|
-
import {
|
|
81
|
-
runLocalHarness
|
|
82
|
-
} from "../chunk-GLR25NG7.js";
|
|
83
|
-
import {
|
|
84
|
-
DELEGATION_MCP_SERVER_KEY,
|
|
85
|
-
buildDelegationMcpServer,
|
|
86
|
-
composeProductionAgentProfile
|
|
87
|
-
} from "../chunk-JFIYKDXF.js";
|
|
88
|
+
} from "../chunk-JTH2FPCK.js";
|
|
89
|
+
import "../chunk-WIR4HOOJ.js";
|
|
90
|
+
import "../chunk-VLF5RHEQ.js";
|
|
88
91
|
import "../chunk-G3RGMA7C.js";
|
|
89
|
-
import {
|
|
90
|
-
assertTraceDerivedFindings
|
|
91
|
-
} from "../chunk-K6WP7PYW.js";
|
|
92
|
-
import "../chunk-GSUO5QS6.js";
|
|
93
92
|
import "../chunk-DGUM43GV.js";
|
|
94
93
|
|
|
95
94
|
// src/mcp/tools/checks.ts
|
|
@@ -258,325 +257,6 @@ function makeCheckRunner(kinds, opts) {
|
|
|
258
257
|
return runCheck(kind, trace, opts, producedAt);
|
|
259
258
|
};
|
|
260
259
|
}
|
|
261
|
-
|
|
262
|
-
// src/mcp/tools/coordination.ts
|
|
263
|
-
var idArg = { type: "string", description: "The workerId returned by spawn_worker." };
|
|
264
|
-
function createCoordinationTools(opts) {
|
|
265
|
-
let stopped = false;
|
|
266
|
-
let reason;
|
|
267
|
-
let questionSeq = 0;
|
|
268
|
-
const ledger = [];
|
|
269
|
-
const questions = [];
|
|
270
|
-
const questionPolicy = opts.questionPolicy ?? "auto";
|
|
271
|
-
const str = (v, field) => {
|
|
272
|
-
if (typeof v !== "string" || v.length === 0)
|
|
273
|
-
throw new Error(`coordination tools: "${field}" must be a non-empty string`);
|
|
274
|
-
return v;
|
|
275
|
-
};
|
|
276
|
-
const obj = (raw) => {
|
|
277
|
-
if (!raw || typeof raw !== "object")
|
|
278
|
-
throw new Error("coordination tools: arguments must be an object");
|
|
279
|
-
return raw;
|
|
280
|
-
};
|
|
281
|
-
const level = (v) => {
|
|
282
|
-
if (v === "worker" || v === "driver" || v === "loop") return v;
|
|
283
|
-
throw new Error('coordination tools: "level" must be worker, driver, or loop');
|
|
284
|
-
};
|
|
285
|
-
const urgency = (v) => {
|
|
286
|
-
if (v === "continue-without" || v === "blocks-step" || v === "blocks-run") return v;
|
|
287
|
-
throw new Error(
|
|
288
|
-
'coordination tools: "urgency" must be continue-without, blocks-step, or blocks-run'
|
|
289
|
-
);
|
|
290
|
-
};
|
|
291
|
-
const recordSettled = (s) => {
|
|
292
|
-
const w = s.kind === "done" ? {
|
|
293
|
-
id: s.handle.id,
|
|
294
|
-
status: "done",
|
|
295
|
-
score: s.verdict?.score ?? 0,
|
|
296
|
-
valid: s.verdict?.valid ?? false,
|
|
297
|
-
outRef: s.outRef
|
|
298
|
-
} : { id: s.handle.id, status: "down", reason: s.reason };
|
|
299
|
-
ledger.push(w);
|
|
300
|
-
return w;
|
|
301
|
-
};
|
|
302
|
-
const nextQuestionId = (from) => `${from}:q${questionSeq++}`;
|
|
303
|
-
const normalizeQuestion = (q, fallbackFrom) => {
|
|
304
|
-
const from = str(q.from ?? fallbackFrom, "from");
|
|
305
|
-
return {
|
|
306
|
-
id: typeof q.id === "string" && q.id.length > 0 ? q.id : nextQuestionId(from),
|
|
307
|
-
from,
|
|
308
|
-
level: level(q.level),
|
|
309
|
-
question: str(q.question, "question"),
|
|
310
|
-
reason: str(q.reason, "reason"),
|
|
311
|
-
...q.options ? { options: q.options } : {},
|
|
312
|
-
urgency: urgency(q.urgency)
|
|
313
|
-
};
|
|
314
|
-
};
|
|
315
|
-
const addQuestion = (raw, fallbackFrom, decision) => {
|
|
316
|
-
const q = normalizeQuestion(raw, fallbackFrom);
|
|
317
|
-
const existing = questions.find((x) => x.id === q.id);
|
|
318
|
-
if (existing) return { question: existing, added: false };
|
|
319
|
-
const effectiveDecision = decision ?? (questionPolicy === "bubble" ? {
|
|
320
|
-
kind: "escalate",
|
|
321
|
-
to: "parent",
|
|
322
|
-
reason: "question policy bubbled to parent"
|
|
323
|
-
} : void 0);
|
|
324
|
-
const status = effectiveDecision?.kind === "answer" ? "answered" : effectiveDecision?.kind === "defer" ? "deferred" : effectiveDecision?.kind === "escalate" ? "escalated" : "open";
|
|
325
|
-
const record = {
|
|
326
|
-
...q,
|
|
327
|
-
status,
|
|
328
|
-
openedAt: Date.now(),
|
|
329
|
-
...effectiveDecision ? { decision: effectiveDecision } : {}
|
|
330
|
-
};
|
|
331
|
-
questions.push(record);
|
|
332
|
-
return { question: record, added: true };
|
|
333
|
-
};
|
|
334
|
-
const emitNewQuestion = async (record) => {
|
|
335
|
-
if (record.added) await opts.onEvent?.({ type: "question", question: record.question });
|
|
336
|
-
return record.question;
|
|
337
|
-
};
|
|
338
|
-
const decideQuestion = (questionId, decision) => {
|
|
339
|
-
const idx = questions.findIndex((q) => q.id === questionId);
|
|
340
|
-
if (idx < 0) throw new Error(`unknown questionId ${JSON.stringify(questionId)}`);
|
|
341
|
-
const prior = questions[idx];
|
|
342
|
-
const status = decision.kind === "answer" ? "answered" : decision.kind === "defer" ? "deferred" : "escalated";
|
|
343
|
-
const next = { ...prior, status, decision };
|
|
344
|
-
questions[idx] = next;
|
|
345
|
-
return next;
|
|
346
|
-
};
|
|
347
|
-
const blockingQuestionsForStop = () => {
|
|
348
|
-
if (questionPolicy === "auto" || questionPolicy === "bubble") return [];
|
|
349
|
-
return questions.filter((q) => {
|
|
350
|
-
const blocking = q.urgency === "blocks-step" || q.urgency === "blocks-run";
|
|
351
|
-
if (!blocking) return false;
|
|
352
|
-
if (questionPolicy === "mustDecide") return q.status === "open";
|
|
353
|
-
return q.status !== "answered" && q.status !== "deferred";
|
|
354
|
-
});
|
|
355
|
-
};
|
|
356
|
-
const tools = [
|
|
357
|
-
{
|
|
358
|
-
name: "spawn_worker",
|
|
359
|
-
description: "Start a worker the driver will drive. `profile` is the worker or another driver; `task` is what it should do. Reserves budget from the conserved pool and fails closed.",
|
|
360
|
-
inputSchema: {
|
|
361
|
-
type: "object",
|
|
362
|
-
properties: {
|
|
363
|
-
profile: { description: "The worker/driver profile to run." },
|
|
364
|
-
task: { description: "The task the worker should perform." },
|
|
365
|
-
label: { type: "string", description: "Optional trace label." }
|
|
366
|
-
},
|
|
367
|
-
required: ["profile", "task"]
|
|
368
|
-
},
|
|
369
|
-
handler: (raw) => {
|
|
370
|
-
const a = obj(raw);
|
|
371
|
-
const agent = opts.makeWorkerAgent(a.profile);
|
|
372
|
-
const res = opts.scope.spawn(agent, a.task, {
|
|
373
|
-
budget: opts.perWorker,
|
|
374
|
-
label: typeof a.label === "string" ? a.label : "worker"
|
|
375
|
-
});
|
|
376
|
-
return Promise.resolve(res.ok ? { workerId: res.handle.id } : { error: res.reason });
|
|
377
|
-
}
|
|
378
|
-
},
|
|
379
|
-
{
|
|
380
|
-
name: "observe_worker",
|
|
381
|
-
description: "Inspect a worker status, spend, and settled output artifact when available.",
|
|
382
|
-
inputSchema: { type: "object", properties: { workerId: idArg }, required: ["workerId"] },
|
|
383
|
-
handler: async (raw) => {
|
|
384
|
-
const id = str(obj(raw).workerId, "workerId");
|
|
385
|
-
const node = opts.scope.view.nodes.find((n) => n.id === id);
|
|
386
|
-
if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` };
|
|
387
|
-
const output = node.outRef ? await opts.blobs.get(node.outRef) : void 0;
|
|
388
|
-
return {
|
|
389
|
-
status: node.status,
|
|
390
|
-
spent: node.spent,
|
|
391
|
-
outRef: node.outRef ?? null,
|
|
392
|
-
output: output ?? null
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
name: "steer_worker",
|
|
398
|
-
description: "Deliver an out-of-band instruction to a running worker inbox.",
|
|
399
|
-
inputSchema: {
|
|
400
|
-
type: "object",
|
|
401
|
-
properties: {
|
|
402
|
-
workerId: idArg,
|
|
403
|
-
instruction: { type: "string", description: "What the worker should do next." }
|
|
404
|
-
},
|
|
405
|
-
required: ["workerId", "instruction"]
|
|
406
|
-
},
|
|
407
|
-
handler: (raw) => {
|
|
408
|
-
const a = obj(raw);
|
|
409
|
-
const delivered = opts.scope.send(str(a.workerId, "workerId"), {
|
|
410
|
-
steer: str(a.instruction, "instruction")
|
|
411
|
-
});
|
|
412
|
-
return Promise.resolve({ delivered });
|
|
413
|
-
}
|
|
414
|
-
},
|
|
415
|
-
{
|
|
416
|
-
name: "await_next",
|
|
417
|
-
description: "Wait for the next spawned worker to settle. Returns { idle: true } when none are live.",
|
|
418
|
-
inputSchema: { type: "object", properties: {} },
|
|
419
|
-
handler: async () => {
|
|
420
|
-
const s = await opts.scope.next();
|
|
421
|
-
if (!s) return { idle: true };
|
|
422
|
-
const w = recordSettled(s);
|
|
423
|
-
return w.status === "done" ? {
|
|
424
|
-
settled: w.id,
|
|
425
|
-
status: "done",
|
|
426
|
-
score: w.score,
|
|
427
|
-
valid: w.valid,
|
|
428
|
-
outRef: w.outRef
|
|
429
|
-
} : { settled: w.id, status: "down", reason: w.reason };
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
name: "list_questions",
|
|
434
|
-
description: "List questions raised by workers, drivers, or analysts. Blocking stop behavior follows questionPolicy.",
|
|
435
|
-
inputSchema: { type: "object", properties: {} },
|
|
436
|
-
handler: () => Promise.resolve({ questions })
|
|
437
|
-
},
|
|
438
|
-
{
|
|
439
|
-
name: "answer_question",
|
|
440
|
-
description: "Record an answer, deferral, or escalation for a loop question.",
|
|
441
|
-
inputSchema: {
|
|
442
|
-
type: "object",
|
|
443
|
-
properties: {
|
|
444
|
-
questionId: { type: "string" },
|
|
445
|
-
answer: { type: "string" },
|
|
446
|
-
by: { type: "string", description: 'Node id or "user".' },
|
|
447
|
-
deferReason: { type: "string" },
|
|
448
|
-
escalateTo: { type: "string", enum: ["parent", "user"] },
|
|
449
|
-
escalateReason: { type: "string" }
|
|
450
|
-
},
|
|
451
|
-
required: ["questionId"]
|
|
452
|
-
},
|
|
453
|
-
handler: (raw) => {
|
|
454
|
-
const a = obj(raw);
|
|
455
|
-
const questionId = str(a.questionId, "questionId");
|
|
456
|
-
if (typeof a.answer === "string" && a.answer.length > 0) {
|
|
457
|
-
return Promise.resolve({
|
|
458
|
-
question: decideQuestion(questionId, {
|
|
459
|
-
kind: "answer",
|
|
460
|
-
answer: a.answer,
|
|
461
|
-
by: typeof a.by === "string" && a.by.length > 0 ? a.by : "user"
|
|
462
|
-
})
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
if (typeof a.deferReason === "string" && a.deferReason.length > 0) {
|
|
466
|
-
return Promise.resolve({
|
|
467
|
-
question: decideQuestion(questionId, {
|
|
468
|
-
kind: "defer",
|
|
469
|
-
reason: a.deferReason
|
|
470
|
-
})
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
if (a.escalateTo === "parent" || a.escalateTo === "user") {
|
|
474
|
-
const escalateReason = typeof a.escalateReason === "string" && a.escalateReason.length > 0 ? a.escalateReason : "driver escalated";
|
|
475
|
-
return Promise.resolve({
|
|
476
|
-
question: decideQuestion(questionId, {
|
|
477
|
-
kind: "escalate",
|
|
478
|
-
to: a.escalateTo,
|
|
479
|
-
reason: escalateReason
|
|
480
|
-
})
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
throw new Error("answer_question: provide answer, deferReason, or escalateTo");
|
|
484
|
-
}
|
|
485
|
-
},
|
|
486
|
-
{
|
|
487
|
-
name: "ask_parent",
|
|
488
|
-
description: "Raise a question to the parent driver/Pi/user when this driver cannot decide.",
|
|
489
|
-
inputSchema: {
|
|
490
|
-
type: "object",
|
|
491
|
-
properties: {
|
|
492
|
-
from: { type: "string" },
|
|
493
|
-
level: { type: "string", enum: ["worker", "driver", "loop"] },
|
|
494
|
-
question: { type: "string" },
|
|
495
|
-
reason: { type: "string" },
|
|
496
|
-
urgency: { type: "string", enum: ["continue-without", "blocks-step", "blocks-run"] }
|
|
497
|
-
},
|
|
498
|
-
required: ["from", "level", "question", "reason", "urgency"]
|
|
499
|
-
},
|
|
500
|
-
handler: async (raw) => {
|
|
501
|
-
const a = obj(raw);
|
|
502
|
-
const from = str(a.from, "from");
|
|
503
|
-
const q = await emitNewQuestion(
|
|
504
|
-
addQuestion(
|
|
505
|
-
{
|
|
506
|
-
from,
|
|
507
|
-
level: level(a.level),
|
|
508
|
-
question: str(a.question, "question"),
|
|
509
|
-
reason: str(a.reason, "reason"),
|
|
510
|
-
urgency: urgency(a.urgency)
|
|
511
|
-
},
|
|
512
|
-
from,
|
|
513
|
-
{ kind: "escalate", to: "parent", reason: "asked parent" }
|
|
514
|
-
)
|
|
515
|
-
);
|
|
516
|
-
return { question: q };
|
|
517
|
-
}
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
name: "stop",
|
|
521
|
-
description: "Declare the run complete.",
|
|
522
|
-
inputSchema: {
|
|
523
|
-
type: "object",
|
|
524
|
-
properties: { reason: { type: "string", description: "Why you are stopping." } }
|
|
525
|
-
},
|
|
526
|
-
handler: (raw) => {
|
|
527
|
-
const blocking = blockingQuestionsForStop();
|
|
528
|
-
if (blocking.length) {
|
|
529
|
-
return Promise.resolve({
|
|
530
|
-
stopped: false,
|
|
531
|
-
error: "unresolved-blocking-questions",
|
|
532
|
-
questions: blocking
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
stopped = true;
|
|
536
|
-
const r = obj(raw).reason;
|
|
537
|
-
reason = typeof r === "string" ? r : void 0;
|
|
538
|
-
return Promise.resolve({ stopped: true });
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
];
|
|
542
|
-
if (opts.analysts) {
|
|
543
|
-
tools.push({
|
|
544
|
-
name: "list_analysts",
|
|
545
|
-
description: "List trace-analyst lenses available to run over a settled worker.",
|
|
546
|
-
inputSchema: { type: "object", properties: {} },
|
|
547
|
-
handler: () => Promise.resolve({ analysts: opts.analysts?.kinds })
|
|
548
|
-
});
|
|
549
|
-
tools.push({
|
|
550
|
-
name: "run_analyst",
|
|
551
|
-
description: "Apply an analyst lens to a settled worker trace.",
|
|
552
|
-
inputSchema: {
|
|
553
|
-
type: "object",
|
|
554
|
-
properties: {
|
|
555
|
-
kind: { type: "string", description: "The analyst kind id." },
|
|
556
|
-
workerId: idArg
|
|
557
|
-
},
|
|
558
|
-
required: ["kind", "workerId"]
|
|
559
|
-
},
|
|
560
|
-
handler: async (raw) => {
|
|
561
|
-
const a = obj(raw);
|
|
562
|
-
const id = str(a.workerId, "workerId");
|
|
563
|
-
const node = opts.scope.view.nodes.find((n) => n.id === id);
|
|
564
|
-
if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` };
|
|
565
|
-
if (!node.outRef)
|
|
566
|
-
return { error: `worker ${JSON.stringify(id)} has not settled \u2014 no trace to analyze yet` };
|
|
567
|
-
const trace = await opts.blobs.get(node.outRef);
|
|
568
|
-
return { findings: await opts.analysts?.run(str(a.kind, "kind"), trace) };
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
return {
|
|
573
|
-
tools,
|
|
574
|
-
isStopped: () => stopped,
|
|
575
|
-
stopReason: () => reason,
|
|
576
|
-
settled: () => ledger,
|
|
577
|
-
questions: () => questions
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
260
|
export {
|
|
581
261
|
DELEGATE_CODE_DESCRIPTION,
|
|
582
262
|
DELEGATE_CODE_INPUT_SCHEMA,
|
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/tools/checks.ts","../../src/mcp/tools/coordination.ts"],"sourcesContent":["/**\n * @experimental\n *\n * The trace-analyst KIND directory — the operator's lenses, as composable DATA.\n *\n * An analyst is not one question. A kind is ONE lens (completeness, correctness, policy, efficiency,\n * tool-use, …); each emits `AnalystFinding`s tagged by its `area`. The driver `list_analysts` to see\n * the menu, `run_analyst(kind, worker)` to apply a lens, and `define_analyst` to author a new one —\n * so at test time you compose the exact lenses a domain needs (maximum specificity), not one generic\n * reviewer. The kinds are data, the runner is generic, and the finding shape + firewall are reused\n * from agent-eval / the keystone — never re-derived.\n *\n * A kind here is a lightweight lens (`Check`); it is a deliberate SUBSET of agent-eval's full\n * `TraceAnalystKindSpec`, so a kind that needs the heavy agentic actor (sub-agent recursion, tools,\n * goldens) upgrades to `createTraceAnalystKind` without changing this directory's surface.\n */\n\nimport {\n type AnalystFinding,\n type AnalystSeverity,\n type EvidenceRef,\n makeFinding,\n} from '@tangle-network/agent-eval'\nimport { assertTraceDerivedFindings } from '../../runtime'\n\n// agent-eval's root entry exports the lift (`makeFinding`) + the `AnalystFinding`/`EvidenceRef` shapes\n// but NOT the raw-row validator / schema prompt (kind-factory-internal). We inline a minimal,\n// equivalent pair so a lens emits the SAME finding shape without reaching into an unstable internal.\nconst ANALYST_SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'] as const\n\nconst FINDING_SCHEMA_PROMPT = [\n 'Each finding is a JSON object with these fields:',\n '- severity: one of \"critical\" | \"high\" | \"medium\" | \"low\" | \"info\"',\n '- claim: one-sentence statement',\n '- evidence_uri: REQUIRED, never blank — exactly one of \"span://<trace>/<span>\", \"artifact://<path>\",',\n ' or \"metric://<name>\"; ALWAYS cite a real id from the trace. No citable id ⇒ omit the finding.',\n '- evidence_excerpt?: a short quote from the cited evidence',\n '- confidence: number 0..1',\n '- rationale?: one sentence of reasoning',\n '- recommended_action?: a concrete imperative (\"Add ...\", \"Replace ...\", \"Stop ...\")',\n 'Emit an empty array when there is nothing to report. Never fabricate evidence.',\n].join('\\n')\n\ninterface RawRow {\n severity: AnalystSeverity\n claim: string\n evidence_uri: string\n confidence: number\n evidence_excerpt?: string\n rationale?: string\n recommended_action?: string\n subject?: string\n}\n\n/** Validate one raw finding row (the lightweight equivalent of agent-eval's `parseRawFinding`):\n * require a claim + a real trace evidence_uri; drop anything else. Returns null to discard. */\nfunction validateRawFinding(row: unknown): RawRow | null {\n if (!row || typeof row !== 'object') return null\n const r = row as Record<string, unknown>\n if (typeof r.claim !== 'string' || r.claim.length === 0) return null\n if (typeof r.evidence_uri !== 'string' || !/^(span|artifact|metric):\\/\\//.test(r.evidence_uri))\n return null\n const sev = (ANALYST_SEVERITIES as readonly string[]).includes(r.severity as string)\n ? (r.severity as AnalystSeverity)\n : 'medium'\n return {\n severity: sev,\n claim: r.claim,\n evidence_uri: r.evidence_uri,\n confidence: typeof r.confidence === 'number' ? r.confidence : 0.5,\n ...(typeof r.evidence_excerpt === 'string' ? { evidence_excerpt: r.evidence_excerpt } : {}),\n ...(typeof r.rationale === 'string' ? { rationale: r.rationale } : {}),\n ...(typeof r.recommended_action === 'string'\n ? { recommended_action: r.recommended_action }\n : {}),\n ...(typeof r.subject === 'string' ? { subject: r.subject } : {}),\n }\n}\n\n/** One lens — a composable analyst kind. Identity fields mirror `TraceAnalystKindSpec` so a kind is\n * upgradeable to the full agentic factory; `lookFor` is the lens question the actor applies. */\nexport interface Check {\n readonly id: string\n readonly description: string\n /** Coarse classification stamped on every finding this kind emits (the renderer groups by it). */\n readonly area: string\n readonly version: string\n /** The lens — what this analyst looks for in the trace. */\n readonly lookFor: string\n}\n\n/** The built-in lens directory. Domain-blind (about any agent trace); compose at test time. */\nexport const defaultChecks: Record<string, Check> = {\n completeness: {\n id: 'completeness',\n description: 'Required work the trace does not yet show done or verified.',\n area: 'failure-mode',\n version: '1',\n lookFor:\n 'every change the task requires that the trace does NOT yet show completed AND verified by a ' +\n 'tool result. One finding per missing/unverified requirement.',\n },\n correctness: {\n id: 'correctness',\n description: 'Tool calls that produced wrong, erroring, or contradicted results.',\n area: 'correctness',\n version: '1',\n lookFor:\n 'tool calls whose RESULT shows an error, a wrong value, or contradicts what the task required ' +\n '(e.g. set the wrong field, value did not take, an error was ignored).',\n },\n policy: {\n id: 'policy',\n description: 'Actions that violate a stated policy, constraint, or allow-list.',\n area: 'safety',\n version: '1',\n lookFor:\n 'actions in the trace that violate a policy/constraint stated in the task or system prompt ' +\n '(forbidden tool, missing approval, out-of-scope mutation, skipped precondition).',\n },\n efficiency: {\n id: 'efficiency',\n description: 'Wasted, redundant, or looping work.',\n area: 'cost',\n version: '1',\n lookFor:\n 'redundant or wasted actions — repeated identical calls, a stalled line retried the same way, ' +\n 'work that produced no progress toward the goal.',\n },\n 'tool-use': {\n id: 'tool-use',\n description: 'Malformed or misused tool calls.',\n area: 'tool-use',\n version: '1',\n lookFor:\n 'tool calls with malformed/invalid arguments, the wrong tool for the intent, or a tool used ' +\n 'against its contract — judged from the call + its result.',\n },\n}\n\n/** Lift validated raw rows into `AnalystFinding`s (agent-eval `makeFinding` stamps `finding_id`/\n * `produced_at`), then enforce the trace-derived firewall (selector ≠ judge). Pure — no LLM. */\nexport function liftFindings(kind: Check, rows: unknown[], producedAt: string): AnalystFinding[] {\n const findings: AnalystFinding[] = []\n for (const row of rows) {\n const raw = validateRawFinding(row)\n if (!raw) continue\n findings.push(\n makeFinding({\n analyst_id: kind.id,\n area: kind.area,\n severity: raw.severity,\n claim: raw.claim,\n confidence: raw.confidence,\n produced_at: producedAt,\n evidence_refs: evidenceRefs(raw.evidence_uri, raw.evidence_excerpt),\n ...(raw.rationale ? { rationale: raw.rationale } : {}),\n ...(raw.recommended_action ? { recommended_action: raw.recommended_action } : {}),\n ...(raw.subject ? { subject: raw.subject } : {}),\n metadata: { kind_version: kind.version },\n }),\n )\n }\n assertTraceDerivedFindings(findings) // throws if a finding cites judge/verdict/score evidence\n return findings\n}\n\n/** Map a raw `evidence_uri` (span:// | artifact:// | metric://<name>) to a typed `EvidenceRef`. A\n * metric ref carries the bare NAME (the firewall checks the metric name for judge/verdict/score —\n * so a finding that cites a judge metric is rejected as not trace-derived). */\nfunction evidenceRefs(uri: string, excerpt?: string): EvidenceRef[] {\n const scheme = uri.split('://', 1)[0]\n if (scheme === 'metric')\n return [\n { kind: 'metric', uri: uri.replace(/^metric:\\/\\//, ''), ...(excerpt ? { excerpt } : {}) },\n ]\n const kind: EvidenceRef['kind'] = scheme === 'span' ? 'span' : 'artifact'\n return [{ kind, uri, ...(excerpt ? { excerpt } : {}) }]\n}\n\n/** Render a worker's trace (tool calls + results) into the text an analyst lens reads. Generic over\n * the trace shape: a `{ messages }` conversation, a bare message array, else stringified. */\nexport function renderTrace(trace: unknown): string {\n const messages = Array.isArray(trace)\n ? trace\n : trace &&\n typeof trace === 'object' &&\n Array.isArray((trace as { messages?: unknown[] }).messages)\n ? (trace as { messages: unknown[] }).messages\n : undefined\n if (!messages) return JSON.stringify(trace ?? {}).slice(0, 8000)\n return messages\n .map((m) => {\n const r = m as {\n role?: string\n content?: unknown\n tool_calls?: Array<{ function?: { name?: string; arguments?: string } }>\n }\n if (r.role === 'tool') return `RESULT ${String(r.content).slice(0, 300)}`\n const calls = r.tool_calls\n ?.map((c) => `${c.function?.name}(${c.function?.arguments})`)\n .join(', ')\n return calls ? `CALL ${calls}` : `SAY ${String(r.content ?? '').slice(0, 200)}`\n })\n .join('\\n')\n .slice(0, 8000)\n}\n\nexport interface CheckRunnerOptions {\n routerBaseUrl: string\n routerKey: string\n model: string\n /** Test/override seam — replace the LLM call. Default: a router chat completion. */\n chat?: (system: string, user: string) => Promise<string>\n}\n\n/** Run ONE lens over a trace → findings. Generic over any kind: prompt = the lens + the agent-eval\n * finding schema; the model's JSON array is parsed (`parseRawFinding`), lifted, and firewalled. */\nexport async function runCheck(\n kind: Check,\n trace: unknown,\n opts: CheckRunnerOptions,\n producedAt: string,\n): Promise<AnalystFinding[]> {\n const sys =\n `You are a trace analyst applying ONE lens: look for ${kind.lookFor}\\n\\n` +\n `${FINDING_SCHEMA_PROMPT}\\n\\nReturn ONLY a fenced \\`\\`\\`json array of finding objects (possibly empty).`\n const user = `WORKER TRACE:\\n${renderTrace(trace)}\\n\\nApply your lens and emit the findings array.`\n const chat = opts.chat ?? defaultChat(opts)\n const content = await chat(sys, user)\n const match = content.match(/```(?:json)?\\s*([\\s\\S]*?)```/)\n let rows: unknown[] = []\n try {\n const parsed = JSON.parse((match?.[1] ?? content).trim())\n rows = Array.isArray(parsed)\n ? parsed\n : Array.isArray((parsed as { findings?: unknown[] })?.findings)\n ? (parsed as { findings: unknown[] }).findings\n : []\n } catch {\n rows = []\n }\n return liftFindings(kind, rows, producedAt)\n}\n\nfunction defaultChat(opts: CheckRunnerOptions): (system: string, user: string) => Promise<string> {\n return async (system, user) => {\n const res = await fetch(`${opts.routerBaseUrl.replace(/\\/$/, '')}/chat/completions`, {\n method: 'POST',\n headers: { 'content-type': 'application/json', authorization: `Bearer ${opts.routerKey}` },\n body: JSON.stringify({\n model: opts.model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n temperature: 0.3,\n }),\n })\n if (!res.ok) throw new Error(`analyst router ${res.status}`)\n const data = (await res.json()) as { choices?: Array<{ message?: { content?: string } }> }\n return data.choices?.[0]?.message?.content ?? ''\n }\n}\n\n/**\n * Build a `run_analyst` runner over a kind directory.\n * Returns findings, or a typed error for an unknown kind. `producedAt` is\n * passed in because replay-safe paths must not read `Date.now`.\n */\nexport function makeCheckRunner(\n kinds: Record<string, Check>,\n opts: CheckRunnerOptions,\n): (\n kindId: string,\n trace: unknown,\n producedAt: string,\n) => Promise<AnalystFinding[] | { error: string }> {\n return async (kindId, trace, producedAt) => {\n const kind = kinds[kindId]\n if (!kind)\n return {\n error: `unknown analyst kind ${JSON.stringify(kindId)} (have: ${Object.keys(kinds).join(', ')})`,\n }\n return runCheck(kind, trace, opts, producedAt)\n }\n}\n","/**\n * @experimental\n *\n * MCP binding for a live `Scope`. A sandbox driver gets the same small verbs\n * the in-process driver has: spawn, observe, await, steer, ask/answer, analyze,\n * and stop. Settled outputs remain Scope artifacts; product code can project\n * them into any UI/report envelope it needs.\n */\n\nimport type {\n Budget,\n ResultBlobStore,\n Scope,\n Settled,\n Agent as SuperviseAgent,\n} from '../../runtime'\nimport type { McpToolDescriptor } from '../server'\n\n/** A worker the driver has drained via `await_next`. */\nexport interface SettledWorker {\n readonly id: string\n readonly status: 'done' | 'down'\n readonly score?: number\n readonly valid?: boolean\n readonly outRef?: string\n readonly reason?: string\n}\n\nexport type QuestionLevel = 'worker' | 'driver' | 'loop'\nexport type QuestionUrgency = 'continue-without' | 'blocks-step' | 'blocks-run'\n\nexport interface QuestionOption {\n readonly label: string\n readonly tradeoff: string\n}\n\nexport interface Question {\n readonly id: string\n readonly from: string\n readonly level: QuestionLevel\n readonly question: string\n readonly reason: string\n readonly urgency: QuestionUrgency\n readonly options?: ReadonlyArray<QuestionOption>\n}\n\nexport type QuestionDecision =\n | { readonly kind: 'answer'; readonly answer: string; readonly by: string }\n | { readonly kind: 'defer'; readonly reason: string }\n | { readonly kind: 'escalate'; readonly to: 'parent' | 'user' | string; readonly reason: string }\n\nexport interface QuestionRecord extends Question {\n readonly status: 'open' | 'answered' | 'deferred' | 'escalated'\n readonly decision?: QuestionDecision\n readonly openedAt: number\n}\n\ntype QuestionInput = Omit<Question, 'id'> & { readonly id?: string }\nexport type QuestionPolicy = 'auto' | 'mustDecide' | 'bubble' | 'failClosed'\n\nexport interface AnalystRegistry {\n readonly kinds: ReadonlyArray<{ id: string; description: string; area: string }>\n readonly run: (kindId: string, trace: unknown) => Promise<unknown>\n}\n\nexport type CoordinationEvent = { readonly type: 'question'; readonly question: QuestionRecord }\n\nexport type MakeWorkerAgent = (profile: unknown) => SuperviseAgent<unknown, unknown>\n\nexport interface CoordinationToolsOptions {\n readonly scope: Scope<unknown>\n readonly blobs: ResultBlobStore\n readonly makeWorkerAgent: MakeWorkerAgent\n readonly perWorker: Budget\n readonly analysts?: AnalystRegistry\n readonly onEvent?: (event: CoordinationEvent) => void | Promise<void>\n readonly questionPolicy?: QuestionPolicy\n}\n\nexport interface CoordinationTools {\n readonly tools: McpToolDescriptor[]\n isStopped(): boolean\n stopReason(): string | undefined\n settled(): ReadonlyArray<SettledWorker>\n questions(): ReadonlyArray<QuestionRecord>\n}\n\nconst idArg = { type: 'string', description: 'The workerId returned by spawn_worker.' } as const\n\n/** Build the driver's MCP tools over a live scope. */\nexport function createCoordinationTools(opts: CoordinationToolsOptions): CoordinationTools {\n let stopped = false\n let reason: string | undefined\n let questionSeq = 0\n const ledger: SettledWorker[] = []\n const questions: QuestionRecord[] = []\n const questionPolicy = opts.questionPolicy ?? 'auto'\n\n const str = (v: unknown, field: string): string => {\n if (typeof v !== 'string' || v.length === 0)\n throw new Error(`coordination tools: \"${field}\" must be a non-empty string`)\n return v\n }\n const obj = (raw: unknown): Record<string, unknown> => {\n if (!raw || typeof raw !== 'object')\n throw new Error('coordination tools: arguments must be an object')\n return raw as Record<string, unknown>\n }\n const level = (v: unknown): Question['level'] => {\n if (v === 'worker' || v === 'driver' || v === 'loop') return v\n throw new Error('coordination tools: \"level\" must be worker, driver, or loop')\n }\n const urgency = (v: unknown): Question['urgency'] => {\n if (v === 'continue-without' || v === 'blocks-step' || v === 'blocks-run') return v\n throw new Error(\n 'coordination tools: \"urgency\" must be continue-without, blocks-step, or blocks-run',\n )\n }\n\n const recordSettled = (s: Settled<unknown>): SettledWorker => {\n const w: SettledWorker =\n s.kind === 'done'\n ? {\n id: s.handle.id,\n status: 'done',\n score: s.verdict?.score ?? 0,\n valid: s.verdict?.valid ?? false,\n outRef: s.outRef,\n }\n : { id: s.handle.id, status: 'down', reason: s.reason }\n ledger.push(w)\n return w\n }\n\n const nextQuestionId = (from: string): string => `${from}:q${questionSeq++}`\n const normalizeQuestion = (q: QuestionInput, fallbackFrom: string): Question => {\n const from = str(q.from ?? fallbackFrom, 'from')\n return {\n id: typeof q.id === 'string' && q.id.length > 0 ? q.id : nextQuestionId(from),\n from,\n level: level(q.level),\n question: str(q.question, 'question'),\n reason: str(q.reason, 'reason'),\n ...(q.options ? { options: q.options } : {}),\n urgency: urgency(q.urgency),\n }\n }\n const addQuestion = (\n raw: QuestionInput,\n fallbackFrom: string,\n decision?: QuestionDecision,\n ): { question: QuestionRecord; added: boolean } => {\n const q = normalizeQuestion(raw, fallbackFrom)\n const existing = questions.find((x) => x.id === q.id)\n if (existing) return { question: existing, added: false }\n const effectiveDecision =\n decision ??\n (questionPolicy === 'bubble'\n ? ({\n kind: 'escalate',\n to: 'parent',\n reason: 'question policy bubbled to parent',\n } as const)\n : undefined)\n const status: QuestionRecord['status'] =\n effectiveDecision?.kind === 'answer'\n ? 'answered'\n : effectiveDecision?.kind === 'defer'\n ? 'deferred'\n : effectiveDecision?.kind === 'escalate'\n ? 'escalated'\n : 'open'\n const record: QuestionRecord = {\n ...q,\n status,\n openedAt: Date.now(),\n ...(effectiveDecision ? { decision: effectiveDecision } : {}),\n }\n questions.push(record)\n return { question: record, added: true }\n }\n const emitNewQuestion = async (record: {\n question: QuestionRecord\n added: boolean\n }): Promise<QuestionRecord> => {\n if (record.added) await opts.onEvent?.({ type: 'question', question: record.question })\n return record.question\n }\n const decideQuestion = (questionId: string, decision: QuestionDecision): QuestionRecord => {\n const idx = questions.findIndex((q) => q.id === questionId)\n if (idx < 0) throw new Error(`unknown questionId ${JSON.stringify(questionId)}`)\n const prior = questions[idx] as QuestionRecord\n const status: QuestionRecord['status'] =\n decision.kind === 'answer' ? 'answered' : decision.kind === 'defer' ? 'deferred' : 'escalated'\n const next: QuestionRecord = { ...prior, status, decision }\n questions[idx] = next\n return next\n }\n const blockingQuestionsForStop = (): QuestionRecord[] => {\n if (questionPolicy === 'auto' || questionPolicy === 'bubble') return []\n return questions.filter((q) => {\n const blocking = q.urgency === 'blocks-step' || q.urgency === 'blocks-run'\n if (!blocking) return false\n if (questionPolicy === 'mustDecide') return q.status === 'open'\n return q.status !== 'answered' && q.status !== 'deferred'\n })\n }\n\n const tools: McpToolDescriptor[] = [\n {\n name: 'spawn_worker',\n description:\n 'Start a worker the driver will drive. `profile` is the worker or another driver; ' +\n '`task` is what it should do. Reserves budget from the conserved pool and fails closed.',\n inputSchema: {\n type: 'object',\n properties: {\n profile: { description: 'The worker/driver profile to run.' },\n task: { description: 'The task the worker should perform.' },\n label: { type: 'string', description: 'Optional trace label.' },\n },\n required: ['profile', 'task'],\n },\n handler: (raw) => {\n const a = obj(raw)\n const agent = opts.makeWorkerAgent(a.profile)\n const res = opts.scope.spawn(agent, a.task, {\n budget: opts.perWorker,\n label: typeof a.label === 'string' ? a.label : 'worker',\n })\n return Promise.resolve(res.ok ? { workerId: res.handle.id } : { error: res.reason })\n },\n },\n {\n name: 'observe_worker',\n description: 'Inspect a worker status, spend, and settled output artifact when available.',\n inputSchema: { type: 'object', properties: { workerId: idArg }, required: ['workerId'] },\n handler: async (raw) => {\n const id = str(obj(raw).workerId, 'workerId')\n const node = opts.scope.view.nodes.find((n) => n.id === id)\n if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` }\n const output = node.outRef ? await opts.blobs.get(node.outRef) : undefined\n return {\n status: node.status,\n spent: node.spent,\n outRef: node.outRef ?? null,\n output: output ?? null,\n }\n },\n },\n {\n name: 'steer_worker',\n description: 'Deliver an out-of-band instruction to a running worker inbox.',\n inputSchema: {\n type: 'object',\n properties: {\n workerId: idArg,\n instruction: { type: 'string', description: 'What the worker should do next.' },\n },\n required: ['workerId', 'instruction'],\n },\n handler: (raw) => {\n const a = obj(raw)\n const delivered = opts.scope.send(str(a.workerId, 'workerId'), {\n steer: str(a.instruction, 'instruction'),\n })\n return Promise.resolve({ delivered })\n },\n },\n {\n name: 'await_next',\n description:\n 'Wait for the next spawned worker to settle. Returns { idle: true } when none are live.',\n inputSchema: { type: 'object', properties: {} },\n handler: async () => {\n const s = await opts.scope.next()\n if (!s) return { idle: true }\n const w = recordSettled(s)\n return w.status === 'done'\n ? {\n settled: w.id,\n status: 'done',\n score: w.score,\n valid: w.valid,\n outRef: w.outRef,\n }\n : { settled: w.id, status: 'down', reason: w.reason }\n },\n },\n {\n name: 'list_questions',\n description:\n 'List questions raised by workers, drivers, or analysts. Blocking stop behavior follows questionPolicy.',\n inputSchema: { type: 'object', properties: {} },\n handler: () => Promise.resolve({ questions }),\n },\n {\n name: 'answer_question',\n description: 'Record an answer, deferral, or escalation for a loop question.',\n inputSchema: {\n type: 'object',\n properties: {\n questionId: { type: 'string' },\n answer: { type: 'string' },\n by: { type: 'string', description: 'Node id or \"user\".' },\n deferReason: { type: 'string' },\n escalateTo: { type: 'string', enum: ['parent', 'user'] },\n escalateReason: { type: 'string' },\n },\n required: ['questionId'],\n },\n handler: (raw) => {\n const a = obj(raw)\n const questionId = str(a.questionId, 'questionId')\n if (typeof a.answer === 'string' && a.answer.length > 0) {\n return Promise.resolve({\n question: decideQuestion(questionId, {\n kind: 'answer',\n answer: a.answer,\n by: typeof a.by === 'string' && a.by.length > 0 ? a.by : 'user',\n }),\n })\n }\n if (typeof a.deferReason === 'string' && a.deferReason.length > 0) {\n return Promise.resolve({\n question: decideQuestion(questionId, {\n kind: 'defer',\n reason: a.deferReason,\n }),\n })\n }\n if (a.escalateTo === 'parent' || a.escalateTo === 'user') {\n const escalateReason =\n typeof a.escalateReason === 'string' && a.escalateReason.length > 0\n ? a.escalateReason\n : 'driver escalated'\n return Promise.resolve({\n question: decideQuestion(questionId, {\n kind: 'escalate',\n to: a.escalateTo,\n reason: escalateReason,\n }),\n })\n }\n throw new Error('answer_question: provide answer, deferReason, or escalateTo')\n },\n },\n {\n name: 'ask_parent',\n description: 'Raise a question to the parent driver/Pi/user when this driver cannot decide.',\n inputSchema: {\n type: 'object',\n properties: {\n from: { type: 'string' },\n level: { type: 'string', enum: ['worker', 'driver', 'loop'] },\n question: { type: 'string' },\n reason: { type: 'string' },\n urgency: { type: 'string', enum: ['continue-without', 'blocks-step', 'blocks-run'] },\n },\n required: ['from', 'level', 'question', 'reason', 'urgency'],\n },\n handler: async (raw) => {\n const a = obj(raw)\n const from = str(a.from, 'from')\n const q = await emitNewQuestion(\n addQuestion(\n {\n from,\n level: level(a.level),\n question: str(a.question, 'question'),\n reason: str(a.reason, 'reason'),\n urgency: urgency(a.urgency),\n },\n from,\n { kind: 'escalate', to: 'parent', reason: 'asked parent' },\n ),\n )\n return { question: q }\n },\n },\n {\n name: 'stop',\n description: 'Declare the run complete.',\n inputSchema: {\n type: 'object',\n properties: { reason: { type: 'string', description: 'Why you are stopping.' } },\n },\n handler: (raw) => {\n const blocking = blockingQuestionsForStop()\n if (blocking.length) {\n return Promise.resolve({\n stopped: false,\n error: 'unresolved-blocking-questions',\n questions: blocking,\n })\n }\n stopped = true\n const r = obj(raw).reason\n reason = typeof r === 'string' ? r : undefined\n return Promise.resolve({ stopped: true })\n },\n },\n ]\n\n if (opts.analysts) {\n tools.push({\n name: 'list_analysts',\n description: 'List trace-analyst lenses available to run over a settled worker.',\n inputSchema: { type: 'object', properties: {} },\n handler: () => Promise.resolve({ analysts: opts.analysts?.kinds }),\n })\n tools.push({\n name: 'run_analyst',\n description: 'Apply an analyst lens to a settled worker trace.',\n inputSchema: {\n type: 'object',\n properties: {\n kind: { type: 'string', description: 'The analyst kind id.' },\n workerId: idArg,\n },\n required: ['kind', 'workerId'],\n },\n handler: async (raw) => {\n const a = obj(raw)\n const id = str(a.workerId, 'workerId')\n const node = opts.scope.view.nodes.find((n) => n.id === id)\n if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` }\n if (!node.outRef)\n return { error: `worker ${JSON.stringify(id)} has not settled — no trace to analyze yet` }\n const trace = await opts.blobs.get(node.outRef)\n return { findings: await opts.analysts?.run(str(a.kind, 'kind'), trace) }\n },\n })\n }\n\n return {\n tools,\n isStopped: () => stopped,\n stopReason: () => reason,\n settled: () => ledger,\n questions: () => questions,\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/tools/checks.ts"],"sourcesContent":["/**\n * @experimental\n *\n * The trace-analyst KIND directory — the operator's lenses, as composable DATA.\n *\n * An analyst is not one question. A kind is ONE lens (completeness, correctness, policy, efficiency,\n * tool-use, …); each emits `AnalystFinding`s tagged by its `area`. The driver `list_analysts` to see\n * the menu, `run_analyst(kind, worker)` to apply a lens, and `define_analyst` to author a new one —\n * so at test time you compose the exact lenses a domain needs (maximum specificity), not one generic\n * reviewer. The kinds are data, the runner is generic, and the finding shape + firewall are reused\n * from agent-eval / the keystone — never re-derived.\n *\n * A kind here is a lightweight lens (`Check`); it is a deliberate SUBSET of agent-eval's full\n * `TraceAnalystKindSpec`, so a kind that needs the heavy agentic actor (sub-agent recursion, tools,\n * goldens) upgrades to `createTraceAnalystKind` without changing this directory's surface.\n */\n\nimport {\n type AnalystFinding,\n type AnalystSeverity,\n type EvidenceRef,\n makeFinding,\n} from '@tangle-network/agent-eval'\nimport { assertTraceDerivedFindings } from '../../runtime'\n\n// agent-eval's root entry exports the lift (`makeFinding`) + the `AnalystFinding`/`EvidenceRef` shapes\n// but NOT the raw-row validator / schema prompt (kind-factory-internal). We inline a minimal,\n// equivalent pair so a lens emits the SAME finding shape without reaching into an unstable internal.\nconst ANALYST_SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'] as const\n\nconst FINDING_SCHEMA_PROMPT = [\n 'Each finding is a JSON object with these fields:',\n '- severity: one of \"critical\" | \"high\" | \"medium\" | \"low\" | \"info\"',\n '- claim: one-sentence statement',\n '- evidence_uri: REQUIRED, never blank — exactly one of \"span://<trace>/<span>\", \"artifact://<path>\",',\n ' or \"metric://<name>\"; ALWAYS cite a real id from the trace. No citable id ⇒ omit the finding.',\n '- evidence_excerpt?: a short quote from the cited evidence',\n '- confidence: number 0..1',\n '- rationale?: one sentence of reasoning',\n '- recommended_action?: a concrete imperative (\"Add ...\", \"Replace ...\", \"Stop ...\")',\n 'Emit an empty array when there is nothing to report. Never fabricate evidence.',\n].join('\\n')\n\ninterface RawRow {\n severity: AnalystSeverity\n claim: string\n evidence_uri: string\n confidence: number\n evidence_excerpt?: string\n rationale?: string\n recommended_action?: string\n subject?: string\n}\n\n/** Validate one raw finding row (the lightweight equivalent of agent-eval's `parseRawFinding`):\n * require a claim + a real trace evidence_uri; drop anything else. Returns null to discard. */\nfunction validateRawFinding(row: unknown): RawRow | null {\n if (!row || typeof row !== 'object') return null\n const r = row as Record<string, unknown>\n if (typeof r.claim !== 'string' || r.claim.length === 0) return null\n if (typeof r.evidence_uri !== 'string' || !/^(span|artifact|metric):\\/\\//.test(r.evidence_uri))\n return null\n const sev = (ANALYST_SEVERITIES as readonly string[]).includes(r.severity as string)\n ? (r.severity as AnalystSeverity)\n : 'medium'\n return {\n severity: sev,\n claim: r.claim,\n evidence_uri: r.evidence_uri,\n confidence: typeof r.confidence === 'number' ? r.confidence : 0.5,\n ...(typeof r.evidence_excerpt === 'string' ? { evidence_excerpt: r.evidence_excerpt } : {}),\n ...(typeof r.rationale === 'string' ? { rationale: r.rationale } : {}),\n ...(typeof r.recommended_action === 'string'\n ? { recommended_action: r.recommended_action }\n : {}),\n ...(typeof r.subject === 'string' ? { subject: r.subject } : {}),\n }\n}\n\n/** One lens — a composable analyst kind. Identity fields mirror `TraceAnalystKindSpec` so a kind is\n * upgradeable to the full agentic factory; `lookFor` is the lens question the actor applies. */\nexport interface Check {\n readonly id: string\n readonly description: string\n /** Coarse classification stamped on every finding this kind emits (the renderer groups by it). */\n readonly area: string\n readonly version: string\n /** The lens — what this analyst looks for in the trace. */\n readonly lookFor: string\n}\n\n/** The built-in lens directory. Domain-blind (about any agent trace); compose at test time. */\nexport const defaultChecks: Record<string, Check> = {\n completeness: {\n id: 'completeness',\n description: 'Required work the trace does not yet show done or verified.',\n area: 'failure-mode',\n version: '1',\n lookFor:\n 'every change the task requires that the trace does NOT yet show completed AND verified by a ' +\n 'tool result. One finding per missing/unverified requirement.',\n },\n correctness: {\n id: 'correctness',\n description: 'Tool calls that produced wrong, erroring, or contradicted results.',\n area: 'correctness',\n version: '1',\n lookFor:\n 'tool calls whose RESULT shows an error, a wrong value, or contradicts what the task required ' +\n '(e.g. set the wrong field, value did not take, an error was ignored).',\n },\n policy: {\n id: 'policy',\n description: 'Actions that violate a stated policy, constraint, or allow-list.',\n area: 'safety',\n version: '1',\n lookFor:\n 'actions in the trace that violate a policy/constraint stated in the task or system prompt ' +\n '(forbidden tool, missing approval, out-of-scope mutation, skipped precondition).',\n },\n efficiency: {\n id: 'efficiency',\n description: 'Wasted, redundant, or looping work.',\n area: 'cost',\n version: '1',\n lookFor:\n 'redundant or wasted actions — repeated identical calls, a stalled line retried the same way, ' +\n 'work that produced no progress toward the goal.',\n },\n 'tool-use': {\n id: 'tool-use',\n description: 'Malformed or misused tool calls.',\n area: 'tool-use',\n version: '1',\n lookFor:\n 'tool calls with malformed/invalid arguments, the wrong tool for the intent, or a tool used ' +\n 'against its contract — judged from the call + its result.',\n },\n}\n\n/** Lift validated raw rows into `AnalystFinding`s (agent-eval `makeFinding` stamps `finding_id`/\n * `produced_at`), then enforce the trace-derived firewall (selector ≠ judge). Pure — no LLM. */\nexport function liftFindings(kind: Check, rows: unknown[], producedAt: string): AnalystFinding[] {\n const findings: AnalystFinding[] = []\n for (const row of rows) {\n const raw = validateRawFinding(row)\n if (!raw) continue\n findings.push(\n makeFinding({\n analyst_id: kind.id,\n area: kind.area,\n severity: raw.severity,\n claim: raw.claim,\n confidence: raw.confidence,\n produced_at: producedAt,\n evidence_refs: evidenceRefs(raw.evidence_uri, raw.evidence_excerpt),\n ...(raw.rationale ? { rationale: raw.rationale } : {}),\n ...(raw.recommended_action ? { recommended_action: raw.recommended_action } : {}),\n ...(raw.subject ? { subject: raw.subject } : {}),\n metadata: { kind_version: kind.version },\n }),\n )\n }\n assertTraceDerivedFindings(findings) // throws if a finding cites judge/verdict/score evidence\n return findings\n}\n\n/** Map a raw `evidence_uri` (span:// | artifact:// | metric://<name>) to a typed `EvidenceRef`. A\n * metric ref carries the bare NAME (the firewall checks the metric name for judge/verdict/score —\n * so a finding that cites a judge metric is rejected as not trace-derived). */\nfunction evidenceRefs(uri: string, excerpt?: string): EvidenceRef[] {\n const scheme = uri.split('://', 1)[0]\n if (scheme === 'metric')\n return [\n { kind: 'metric', uri: uri.replace(/^metric:\\/\\//, ''), ...(excerpt ? { excerpt } : {}) },\n ]\n const kind: EvidenceRef['kind'] = scheme === 'span' ? 'span' : 'artifact'\n return [{ kind, uri, ...(excerpt ? { excerpt } : {}) }]\n}\n\n/** Render a worker's trace (tool calls + results) into the text an analyst lens reads. Generic over\n * the trace shape: a `{ messages }` conversation, a bare message array, else stringified. */\nexport function renderTrace(trace: unknown): string {\n const messages = Array.isArray(trace)\n ? trace\n : trace &&\n typeof trace === 'object' &&\n Array.isArray((trace as { messages?: unknown[] }).messages)\n ? (trace as { messages: unknown[] }).messages\n : undefined\n if (!messages) return JSON.stringify(trace ?? {}).slice(0, 8000)\n return messages\n .map((m) => {\n const r = m as {\n role?: string\n content?: unknown\n tool_calls?: Array<{ function?: { name?: string; arguments?: string } }>\n }\n if (r.role === 'tool') return `RESULT ${String(r.content).slice(0, 300)}`\n const calls = r.tool_calls\n ?.map((c) => `${c.function?.name}(${c.function?.arguments})`)\n .join(', ')\n return calls ? `CALL ${calls}` : `SAY ${String(r.content ?? '').slice(0, 200)}`\n })\n .join('\\n')\n .slice(0, 8000)\n}\n\nexport interface CheckRunnerOptions {\n routerBaseUrl: string\n routerKey: string\n model: string\n /** Test/override seam — replace the LLM call. Default: a router chat completion. */\n chat?: (system: string, user: string) => Promise<string>\n}\n\n/** Run ONE lens over a trace → findings. Generic over any kind: prompt = the lens + the agent-eval\n * finding schema; the model's JSON array is parsed (`parseRawFinding`), lifted, and firewalled. */\nexport async function runCheck(\n kind: Check,\n trace: unknown,\n opts: CheckRunnerOptions,\n producedAt: string,\n): Promise<AnalystFinding[]> {\n const sys =\n `You are a trace analyst applying ONE lens: look for ${kind.lookFor}\\n\\n` +\n `${FINDING_SCHEMA_PROMPT}\\n\\nReturn ONLY a fenced \\`\\`\\`json array of finding objects (possibly empty).`\n const user = `WORKER TRACE:\\n${renderTrace(trace)}\\n\\nApply your lens and emit the findings array.`\n const chat = opts.chat ?? defaultChat(opts)\n const content = await chat(sys, user)\n const match = content.match(/```(?:json)?\\s*([\\s\\S]*?)```/)\n let rows: unknown[] = []\n try {\n const parsed = JSON.parse((match?.[1] ?? content).trim())\n rows = Array.isArray(parsed)\n ? parsed\n : Array.isArray((parsed as { findings?: unknown[] })?.findings)\n ? (parsed as { findings: unknown[] }).findings\n : []\n } catch {\n rows = []\n }\n return liftFindings(kind, rows, producedAt)\n}\n\nfunction defaultChat(opts: CheckRunnerOptions): (system: string, user: string) => Promise<string> {\n return async (system, user) => {\n const res = await fetch(`${opts.routerBaseUrl.replace(/\\/$/, '')}/chat/completions`, {\n method: 'POST',\n headers: { 'content-type': 'application/json', authorization: `Bearer ${opts.routerKey}` },\n body: JSON.stringify({\n model: opts.model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n temperature: 0.3,\n }),\n })\n if (!res.ok) throw new Error(`analyst router ${res.status}`)\n const data = (await res.json()) as { choices?: Array<{ message?: { content?: string } }> }\n return data.choices?.[0]?.message?.content ?? ''\n }\n}\n\n/**\n * Build a `run_analyst` runner over a kind directory.\n * Returns findings, or a typed error for an unknown kind. `producedAt` is\n * passed in because replay-safe paths must not read `Date.now`.\n */\nexport function makeCheckRunner(\n kinds: Record<string, Check>,\n opts: CheckRunnerOptions,\n): (\n kindId: string,\n trace: unknown,\n producedAt: string,\n) => Promise<AnalystFinding[] | { error: string }> {\n return async (kindId, trace, producedAt) => {\n const kind = kinds[kindId]\n if (!kind)\n return {\n error: `unknown analyst kind ${JSON.stringify(kindId)} (have: ${Object.keys(kinds).join(', ')})`,\n }\n return runCheck(kind, trace, opts, producedAt)\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/profiles.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as CoderOutput, a as CoderProfileOptions, b as CoderTask, M as MultiHarnessCoderFanoutOptions, c as coderProfile, d as createCoderValidator, m as multiHarnessCoderFanout } from './coder-
|
|
2
|
-
import { S as SandboxClient, O as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-
|
|
1
|
+
export { C as CoderOutput, a as CoderProfileOptions, b as CoderTask, M as MultiHarnessCoderFanoutOptions, c as coderProfile, d as createCoderValidator, m as multiHarnessCoderFanout } from './coder-CEkUFv8h.js';
|
|
2
|
+
import { S as SandboxClient, O as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-C8rNlxfV.js';
|
|
3
3
|
import { a as UiLens, U as UiFinding } from './substrate-CUgk7F7s.js';
|
|
4
4
|
export { b as UI_FINDING_SEVERITIES, c as UI_LENSES, d as UiFindingScreenshot, e as UiFindingSeverity } from './substrate-CUgk7F7s.js';
|
|
5
5
|
import { SandboxEvent, AgentProfile } from '@tangle-network/sandbox';
|
package/dist/profiles.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
slugify
|
|
3
3
|
} from "./chunk-4B6U4CVQ.js";
|
|
4
|
-
import {
|
|
5
|
-
UI_FINDING_SEVERITIES,
|
|
6
|
-
UI_LENSES
|
|
7
|
-
} from "./chunk-WIR4HOOJ.js";
|
|
8
4
|
import {
|
|
9
5
|
coderProfile,
|
|
10
6
|
createCoderValidator,
|
|
11
7
|
multiHarnessCoderFanout
|
|
12
8
|
} from "./chunk-KADIJAD4.js";
|
|
9
|
+
import {
|
|
10
|
+
UI_FINDING_SEVERITIES,
|
|
11
|
+
UI_LENSES
|
|
12
|
+
} from "./chunk-WIR4HOOJ.js";
|
|
13
13
|
import "./chunk-DGUM43GV.js";
|
|
14
14
|
|
|
15
15
|
// src/profiles/ui-auditor/prompt.ts
|
|
@@ -117,4 +117,4 @@ declare function routerToolLoop(cfg: RouterConfig, system: string, user: string,
|
|
|
117
117
|
initialMessages?: ReadonlyArray<Record<string, unknown>>;
|
|
118
118
|
}): Promise<RouterToolLoopResult>;
|
|
119
119
|
|
|
120
|
-
export { type
|
|
120
|
+
export { type RouterConfig as R, type ToolSpec as T, type RouterChatResult as a, type RouterChatToolsResult as b, type RouterToolCall as c, type RouterToolLoopResult as d, routerChatWithUsage as e, routerToolLoop as f, routerChatWithTools as r };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SandboxInstance } from '@tangle-network/sandbox';
|
|
2
|
-
import { D as Driver, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, I as Iteration, L as LoopWinner, a as LoopLineageOptions, S as SandboxClient, b as LoopResult } from './types-
|
|
2
|
+
import { D as Driver, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, I as Iteration, L as LoopWinner, a as LoopLineageOptions, S as SandboxClient, b as LoopResult } from './types-C8rNlxfV.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @experimental
|