@tangle-network/agent-runtime 0.44.0 → 0.46.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 +95 -203
- package/dist/agent.d.ts +3 -2
- package/dist/agent.js +5 -7
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +28 -2
- package/dist/analyst-loop.js +4 -1
- package/dist/audit.d.ts +93 -0
- package/dist/audit.js +312 -0
- package/dist/audit.js.map +1 -0
- package/dist/chunk-4B6U4CVQ.js +15 -0
- package/dist/chunk-4B6U4CVQ.js.map +1 -0
- package/dist/chunk-65FQLI4V.js +4089 -0
- package/dist/chunk-65FQLI4V.js.map +1 -0
- package/dist/{chunk-GFKVVRQ7.js → chunk-GN75RGM6.js} +13 -12
- package/dist/chunk-GN75RGM6.js.map +1 -0
- package/dist/chunk-GSUO5QS6.js +146 -0
- package/dist/chunk-GSUO5QS6.js.map +1 -0
- package/dist/chunk-HNUXAZIJ.js +580 -0
- package/dist/chunk-HNUXAZIJ.js.map +1 -0
- package/dist/{chunk-SKUZZCHE.js → chunk-I42NHLKX.js} +5 -5
- package/dist/chunk-I42NHLKX.js.map +1 -0
- package/dist/{chunk-HVYOHJHK.js → chunk-JNPK46YH.js} +2 -2
- package/dist/chunk-JNPK46YH.js.map +1 -0
- package/dist/{chunk-3HMHSN22.js → chunk-KADIJAD4.js} +38 -24
- package/dist/chunk-KADIJAD4.js.map +1 -0
- package/dist/{chunk-KDMRUD2P.js → chunk-KPN7OQ64.js} +296 -8
- package/dist/chunk-KPN7OQ64.js.map +1 -0
- package/dist/{chunk-NRZOXCJK.js → chunk-VR4JIC5H.js} +2 -2
- package/dist/chunk-WIR4HOOJ.js +27 -0
- package/dist/chunk-WIR4HOOJ.js.map +1 -0
- package/dist/coder-DCWFQpmJ.d.ts +114 -0
- package/dist/driver-C-mtBo7h.d.ts +221 -0
- package/dist/improvement.d.ts +0 -1
- package/dist/improvement.js +0 -5
- package/dist/improvement.js.map +1 -1
- package/dist/index.d.ts +122 -9
- package/dist/index.js +398 -10
- package/dist/index.js.map +1 -1
- package/dist/{kb-gate-D0ZIhFOU.d.ts → kb-gate-2Gwpz_27.d.ts} +86 -9
- package/dist/{loop-runner-bin-BLMa8He3.d.ts → loop-runner-bin-D-K6bRp3.d.ts} +17 -13
- package/dist/loop-runner-bin.d.ts +8 -6
- package/dist/loop-runner-bin.js +6 -8
- package/dist/loops.d.ts +7 -393
- package/dist/loops.js +96 -27
- package/dist/mcp/bin.js +7 -7
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +286 -13
- package/dist/mcp/index.js +341 -9
- package/dist/mcp/index.js.map +1 -1
- package/dist/{otel-export-wFDmmurL.d.ts → otel-export-nurzFwuJ.d.ts} +1 -1
- package/dist/profiles.d.ts +385 -86
- package/dist/profiles.js +549 -4
- package/dist/profiles.js.map +1 -1
- package/dist/{run-loop-C4L1Sted.d.ts → run-loop-CU2Y00Si.d.ts} +36 -13
- package/dist/runtime-hooks-C7JwKb9E.d.ts +70 -0
- package/dist/runtime.d.ts +1964 -0
- package/dist/runtime.js +114 -0
- package/dist/runtime.js.map +1 -0
- package/dist/substrate-CUgk7F7s.d.ts +77 -0
- package/dist/topology.d.ts +73 -0
- package/dist/topology.js +111 -0
- package/dist/topology.js.map +1 -0
- package/dist/types-BfoeiQRZ.d.ts +438 -0
- package/dist/{types-DbJzz2uf.d.ts → types-DnYoHvvZ.d.ts} +110 -4
- package/dist/workflow.d.ts +4 -3
- package/dist/workflow.js +4 -5
- package/dist/workflow.js.map +1 -1
- package/package.json +37 -28
- package/skills/agent-runtime-adoption/SKILL.md +32 -29
- package/skills/generate-eval/SKILL.md +60 -0
- package/dist/chunk-3HMHSN22.js.map +0 -1
- package/dist/chunk-GFKVVRQ7.js.map +0 -1
- package/dist/chunk-HVYOHJHK.js.map +0 -1
- package/dist/chunk-KDMRUD2P.js.map +0 -1
- package/dist/chunk-PY6NMZYX.js +0 -52
- package/dist/chunk-PY6NMZYX.js.map +0 -1
- package/dist/chunk-S7JXV32P.js +0 -947
- package/dist/chunk-S7JXV32P.js.map +0 -1
- package/dist/chunk-SKUZZCHE.js.map +0 -1
- package/dist/chunk-SQSCRJ7U.js +0 -65
- package/dist/chunk-SQSCRJ7U.js.map +0 -1
- package/dist/chunk-VOX6Z3II.js +0 -90
- package/dist/chunk-VOX6Z3II.js.map +0 -1
- package/dist/chunk-XBUG326M.js +0 -261
- package/dist/chunk-XBUG326M.js.map +0 -1
- package/dist/dynamic-wUgp6UKs.d.ts +0 -108
- package/dist/optimize-prompt-D-urF2wW.d.ts +0 -129
- /package/dist/{chunk-NRZOXCJK.js.map → chunk-VR4JIC5H.js.map} +0 -0
package/dist/mcp/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DELEGATE_UI_AUDIT_DESCRIPTION,
|
|
3
|
+
DELEGATE_UI_AUDIT_INPUT_SCHEMA,
|
|
4
|
+
DELEGATE_UI_AUDIT_TOOL_NAME,
|
|
2
5
|
captureWorktreeDiff,
|
|
6
|
+
createDelegateUiAuditHandler,
|
|
3
7
|
createInProcessExecutor,
|
|
4
8
|
createInProcessTransport,
|
|
5
9
|
createMcpServer,
|
|
@@ -8,12 +12,14 @@ import {
|
|
|
8
12
|
detectExecutor,
|
|
9
13
|
readTraceContextFromEnv,
|
|
10
14
|
removeWorktree,
|
|
11
|
-
traceContextToEnv
|
|
12
|
-
|
|
15
|
+
traceContextToEnv,
|
|
16
|
+
validateDelegateUiAuditArgs
|
|
17
|
+
} from "../chunk-KPN7OQ64.js";
|
|
18
|
+
import "../chunk-WIR4HOOJ.js";
|
|
13
19
|
import {
|
|
14
20
|
mcpToolsForRuntimeMcp,
|
|
15
21
|
mcpToolsForRuntimeMcpSubset
|
|
16
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-VR4JIC5H.js";
|
|
17
23
|
import {
|
|
18
24
|
DELEGATE_CODE_DESCRIPTION,
|
|
19
25
|
DELEGATE_CODE_INPUT_SCHEMA,
|
|
@@ -44,7 +50,7 @@ import {
|
|
|
44
50
|
validateDelegateResearchArgs,
|
|
45
51
|
validateDelegationHistoryArgs,
|
|
46
52
|
validateDelegationStatusArgs
|
|
47
|
-
} from "../chunk-
|
|
53
|
+
} from "../chunk-JNPK46YH.js";
|
|
48
54
|
import {
|
|
49
55
|
createKbGate
|
|
50
56
|
} from "../chunk-FNMGYYSS.js";
|
|
@@ -52,7 +58,8 @@ import {
|
|
|
52
58
|
createDefaultCoderDelegate,
|
|
53
59
|
createFleetWorkspaceExecutor,
|
|
54
60
|
createSiblingSandboxExecutor
|
|
55
|
-
} from "../chunk-
|
|
61
|
+
} from "../chunk-I42NHLKX.js";
|
|
62
|
+
import "../chunk-KADIJAD4.js";
|
|
56
63
|
import {
|
|
57
64
|
runLocalHarness
|
|
58
65
|
} from "../chunk-GLR25NG7.js";
|
|
@@ -61,11 +68,325 @@ import {
|
|
|
61
68
|
buildDelegationMcpServer,
|
|
62
69
|
composeProductionAgentProfile
|
|
63
70
|
} from "../chunk-7JITYN6T.js";
|
|
64
|
-
import
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
import "../chunk-
|
|
71
|
+
import {
|
|
72
|
+
assertTraceDerivedFindings
|
|
73
|
+
} from "../chunk-65FQLI4V.js";
|
|
74
|
+
import "../chunk-GSUO5QS6.js";
|
|
68
75
|
import "../chunk-DGUM43GV.js";
|
|
76
|
+
|
|
77
|
+
// src/mcp/tools/checks.ts
|
|
78
|
+
import {
|
|
79
|
+
makeFinding
|
|
80
|
+
} from "@tangle-network/agent-eval";
|
|
81
|
+
var ANALYST_SEVERITIES = ["critical", "high", "medium", "low", "info"];
|
|
82
|
+
var FINDING_SCHEMA_PROMPT = [
|
|
83
|
+
"Each finding is a JSON object with these fields:",
|
|
84
|
+
'- severity: one of "critical" | "high" | "medium" | "low" | "info"',
|
|
85
|
+
"- claim: one-sentence statement",
|
|
86
|
+
'- evidence_uri: REQUIRED, never blank \u2014 exactly one of "span://<trace>/<span>", "artifact://<path>",',
|
|
87
|
+
' or "metric://<name>"; ALWAYS cite a real id from the trace. No citable id \u21D2 omit the finding.',
|
|
88
|
+
"- evidence_excerpt?: a short quote from the cited evidence",
|
|
89
|
+
"- confidence: number 0..1",
|
|
90
|
+
"- rationale?: one sentence of reasoning",
|
|
91
|
+
'- recommended_action?: a concrete imperative ("Add ...", "Replace ...", "Stop ...")',
|
|
92
|
+
"Emit an empty array when there is nothing to report. Never fabricate evidence."
|
|
93
|
+
].join("\n");
|
|
94
|
+
function validateRawFinding(row) {
|
|
95
|
+
if (!row || typeof row !== "object") return null;
|
|
96
|
+
const r = row;
|
|
97
|
+
if (typeof r.claim !== "string" || r.claim.length === 0) return null;
|
|
98
|
+
if (typeof r.evidence_uri !== "string" || !/^(span|artifact|metric):\/\//.test(r.evidence_uri))
|
|
99
|
+
return null;
|
|
100
|
+
const sev = ANALYST_SEVERITIES.includes(r.severity) ? r.severity : "medium";
|
|
101
|
+
return {
|
|
102
|
+
severity: sev,
|
|
103
|
+
claim: r.claim,
|
|
104
|
+
evidence_uri: r.evidence_uri,
|
|
105
|
+
confidence: typeof r.confidence === "number" ? r.confidence : 0.5,
|
|
106
|
+
...typeof r.evidence_excerpt === "string" ? { evidence_excerpt: r.evidence_excerpt } : {},
|
|
107
|
+
...typeof r.rationale === "string" ? { rationale: r.rationale } : {},
|
|
108
|
+
...typeof r.recommended_action === "string" ? { recommended_action: r.recommended_action } : {},
|
|
109
|
+
...typeof r.subject === "string" ? { subject: r.subject } : {}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
var defaultChecks = {
|
|
113
|
+
completeness: {
|
|
114
|
+
id: "completeness",
|
|
115
|
+
description: "Required work the trace does not yet show done or verified.",
|
|
116
|
+
area: "failure-mode",
|
|
117
|
+
version: "1",
|
|
118
|
+
lookFor: "every change the task requires that the trace does NOT yet show completed AND verified by a tool result. One finding per missing/unverified requirement."
|
|
119
|
+
},
|
|
120
|
+
correctness: {
|
|
121
|
+
id: "correctness",
|
|
122
|
+
description: "Tool calls that produced wrong, erroring, or contradicted results.",
|
|
123
|
+
area: "correctness",
|
|
124
|
+
version: "1",
|
|
125
|
+
lookFor: "tool calls whose RESULT shows an error, a wrong value, or contradicts what the task required (e.g. set the wrong field, value did not take, an error was ignored)."
|
|
126
|
+
},
|
|
127
|
+
policy: {
|
|
128
|
+
id: "policy",
|
|
129
|
+
description: "Actions that violate a stated policy, constraint, or allow-list.",
|
|
130
|
+
area: "safety",
|
|
131
|
+
version: "1",
|
|
132
|
+
lookFor: "actions in the trace that violate a policy/constraint stated in the task or system prompt (forbidden tool, missing approval, out-of-scope mutation, skipped precondition)."
|
|
133
|
+
},
|
|
134
|
+
efficiency: {
|
|
135
|
+
id: "efficiency",
|
|
136
|
+
description: "Wasted, redundant, or looping work.",
|
|
137
|
+
area: "cost",
|
|
138
|
+
version: "1",
|
|
139
|
+
lookFor: "redundant or wasted actions \u2014 repeated identical calls, a stalled line retried the same way, work that produced no progress toward the goal."
|
|
140
|
+
},
|
|
141
|
+
"tool-use": {
|
|
142
|
+
id: "tool-use",
|
|
143
|
+
description: "Malformed or misused tool calls.",
|
|
144
|
+
area: "tool-use",
|
|
145
|
+
version: "1",
|
|
146
|
+
lookFor: "tool calls with malformed/invalid arguments, the wrong tool for the intent, or a tool used against its contract \u2014 judged from the call + its result."
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
function liftFindings(kind, rows, producedAt) {
|
|
150
|
+
const findings = [];
|
|
151
|
+
for (const row of rows) {
|
|
152
|
+
const raw = validateRawFinding(row);
|
|
153
|
+
if (!raw) continue;
|
|
154
|
+
findings.push(
|
|
155
|
+
makeFinding({
|
|
156
|
+
analyst_id: kind.id,
|
|
157
|
+
area: kind.area,
|
|
158
|
+
severity: raw.severity,
|
|
159
|
+
claim: raw.claim,
|
|
160
|
+
confidence: raw.confidence,
|
|
161
|
+
produced_at: producedAt,
|
|
162
|
+
evidence_refs: evidenceRefs(raw.evidence_uri, raw.evidence_excerpt),
|
|
163
|
+
...raw.rationale ? { rationale: raw.rationale } : {},
|
|
164
|
+
...raw.recommended_action ? { recommended_action: raw.recommended_action } : {},
|
|
165
|
+
...raw.subject ? { subject: raw.subject } : {},
|
|
166
|
+
metadata: { kind_version: kind.version }
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
assertTraceDerivedFindings(findings);
|
|
171
|
+
return findings;
|
|
172
|
+
}
|
|
173
|
+
function evidenceRefs(uri, excerpt) {
|
|
174
|
+
const scheme = uri.split("://", 1)[0];
|
|
175
|
+
if (scheme === "metric")
|
|
176
|
+
return [
|
|
177
|
+
{ kind: "metric", uri: uri.replace(/^metric:\/\//, ""), ...excerpt ? { excerpt } : {} }
|
|
178
|
+
];
|
|
179
|
+
const kind = scheme === "span" ? "span" : "artifact";
|
|
180
|
+
return [{ kind, uri, ...excerpt ? { excerpt } : {} }];
|
|
181
|
+
}
|
|
182
|
+
function renderTrace(trace) {
|
|
183
|
+
const messages = Array.isArray(trace) ? trace : trace && typeof trace === "object" && Array.isArray(trace.messages) ? trace.messages : void 0;
|
|
184
|
+
if (!messages) return JSON.stringify(trace ?? {}).slice(0, 8e3);
|
|
185
|
+
return messages.map((m) => {
|
|
186
|
+
const r = m;
|
|
187
|
+
if (r.role === "tool") return `RESULT ${String(r.content).slice(0, 300)}`;
|
|
188
|
+
const calls = r.tool_calls?.map((c) => `${c.function?.name}(${c.function?.arguments})`).join(", ");
|
|
189
|
+
return calls ? `CALL ${calls}` : `SAY ${String(r.content ?? "").slice(0, 200)}`;
|
|
190
|
+
}).join("\n").slice(0, 8e3);
|
|
191
|
+
}
|
|
192
|
+
async function runCheck(kind, trace, opts, producedAt) {
|
|
193
|
+
const sys = `You are a trace analyst applying ONE lens: look for ${kind.lookFor}
|
|
194
|
+
|
|
195
|
+
${FINDING_SCHEMA_PROMPT}
|
|
196
|
+
|
|
197
|
+
Return ONLY a fenced \`\`\`json array of finding objects (possibly empty).`;
|
|
198
|
+
const user = `WORKER TRACE:
|
|
199
|
+
${renderTrace(trace)}
|
|
200
|
+
|
|
201
|
+
Apply your lens and emit the findings array.`;
|
|
202
|
+
const chat = opts.chat ?? defaultChat(opts);
|
|
203
|
+
const content = await chat(sys, user);
|
|
204
|
+
const match = content.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
205
|
+
let rows = [];
|
|
206
|
+
try {
|
|
207
|
+
const parsed = JSON.parse((match?.[1] ?? content).trim());
|
|
208
|
+
rows = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.findings) ? parsed.findings : [];
|
|
209
|
+
} catch {
|
|
210
|
+
rows = [];
|
|
211
|
+
}
|
|
212
|
+
return liftFindings(kind, rows, producedAt);
|
|
213
|
+
}
|
|
214
|
+
function defaultChat(opts) {
|
|
215
|
+
return async (system, user) => {
|
|
216
|
+
const res = await fetch(`${opts.routerBaseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${opts.routerKey}` },
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
model: opts.model,
|
|
221
|
+
messages: [
|
|
222
|
+
{ role: "system", content: system },
|
|
223
|
+
{ role: "user", content: user }
|
|
224
|
+
],
|
|
225
|
+
temperature: 0.3
|
|
226
|
+
})
|
|
227
|
+
});
|
|
228
|
+
if (!res.ok) throw new Error(`analyst router ${res.status}`);
|
|
229
|
+
const data = await res.json();
|
|
230
|
+
return data.choices?.[0]?.message?.content ?? "";
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function makeCheckRunner(kinds, opts) {
|
|
234
|
+
return async (kindId, trace, producedAt) => {
|
|
235
|
+
const kind = kinds[kindId];
|
|
236
|
+
if (!kind)
|
|
237
|
+
return {
|
|
238
|
+
error: `unknown analyst kind ${JSON.stringify(kindId)} (have: ${Object.keys(kinds).join(", ")})`
|
|
239
|
+
};
|
|
240
|
+
return runCheck(kind, trace, opts, producedAt);
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/mcp/tools/coordination.ts
|
|
245
|
+
var idArg = { type: "string", description: "The workerId returned by spawn_worker." };
|
|
246
|
+
function createCoordinationTools(opts) {
|
|
247
|
+
let stopped = false;
|
|
248
|
+
let reason;
|
|
249
|
+
const ledger = [];
|
|
250
|
+
const recordSettled = (s) => {
|
|
251
|
+
const w = s.kind === "done" ? {
|
|
252
|
+
id: s.handle.id,
|
|
253
|
+
status: "done",
|
|
254
|
+
score: s.verdict?.score ?? 0,
|
|
255
|
+
valid: s.verdict?.valid ?? false,
|
|
256
|
+
outRef: s.outRef
|
|
257
|
+
} : { id: s.handle.id, status: "down", reason: s.reason };
|
|
258
|
+
ledger.push(w);
|
|
259
|
+
return w;
|
|
260
|
+
};
|
|
261
|
+
const str = (v, field) => {
|
|
262
|
+
if (typeof v !== "string" || v.length === 0)
|
|
263
|
+
throw new Error(`operator toolbox: "${field}" must be a non-empty string`);
|
|
264
|
+
return v;
|
|
265
|
+
};
|
|
266
|
+
const obj = (raw) => {
|
|
267
|
+
if (!raw || typeof raw !== "object")
|
|
268
|
+
throw new Error("operator toolbox: arguments must be an object");
|
|
269
|
+
return raw;
|
|
270
|
+
};
|
|
271
|
+
const tools = [
|
|
272
|
+
{
|
|
273
|
+
name: "spawn_worker",
|
|
274
|
+
description: 'Start a worker the operator will drive. `profile` is the worker (or another DRIVER \u2014 drivers-of-drivers are allowed); `task` is what it should do. Reserves the worker\u2019s budget from the conserved pool and FAILS CLOSED when the pool is dry \u2014 so spawning "at will" is bounded by the budget. Returns { workerId } or { error: "budget-exhausted" | "depth-exceeded" }.',
|
|
275
|
+
inputSchema: {
|
|
276
|
+
type: "object",
|
|
277
|
+
properties: {
|
|
278
|
+
profile: { description: "The worker/driver profile to run (passed to makeWorkerAgent)." },
|
|
279
|
+
task: { description: "The task the worker should perform." },
|
|
280
|
+
label: { type: "string", description: "Optional trace label." }
|
|
281
|
+
},
|
|
282
|
+
required: ["profile", "task"]
|
|
283
|
+
},
|
|
284
|
+
handler: (raw) => {
|
|
285
|
+
const a = obj(raw);
|
|
286
|
+
const agent = opts.makeWorkerAgent(a.profile);
|
|
287
|
+
const res = opts.scope.spawn(agent, a.task, {
|
|
288
|
+
budget: opts.perWorker,
|
|
289
|
+
label: typeof a.label === "string" ? a.label : "worker"
|
|
290
|
+
});
|
|
291
|
+
return Promise.resolve(res.ok ? { workerId: res.handle.id } : { error: res.reason });
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "observe_worker",
|
|
296
|
+
description: "Inspect a worker you are driving: its live status + conserved spend, and \u2014 once it has settled \u2014 its output artifact (rehydrated from the result blob). Use this to review work before deciding your next move. (In-flight token-level trace is surfaced via the analyst, not here.)",
|
|
297
|
+
inputSchema: { type: "object", properties: { workerId: idArg }, required: ["workerId"] },
|
|
298
|
+
handler: async (raw) => {
|
|
299
|
+
const id = str(obj(raw).workerId, "workerId");
|
|
300
|
+
const node = opts.scope.view.nodes.find((n) => n.id === id);
|
|
301
|
+
if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` };
|
|
302
|
+
const output = node.outRef ? await opts.blobs.get(node.outRef) : void 0;
|
|
303
|
+
return {
|
|
304
|
+
status: node.status,
|
|
305
|
+
spent: node.spent,
|
|
306
|
+
outRef: node.outRef ?? null,
|
|
307
|
+
output: output ?? null
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "steer_worker",
|
|
313
|
+
description: "Steer a RUNNING worker out-of-band \u2014 deliver your next instruction / a course-correction / an interrupt to its inbox. Returns { delivered } \u2014 false if the worker has finished or its harness cannot be steered mid-flight (then spawn a fresh one or wait and re-observe).",
|
|
314
|
+
inputSchema: {
|
|
315
|
+
type: "object",
|
|
316
|
+
properties: {
|
|
317
|
+
workerId: idArg,
|
|
318
|
+
instruction: { type: "string", description: "What the worker should do next." }
|
|
319
|
+
},
|
|
320
|
+
required: ["workerId", "instruction"]
|
|
321
|
+
},
|
|
322
|
+
handler: (raw) => {
|
|
323
|
+
const a = obj(raw);
|
|
324
|
+
const delivered = opts.scope.send(str(a.workerId, "workerId"), {
|
|
325
|
+
steer: str(a.instruction, "instruction")
|
|
326
|
+
});
|
|
327
|
+
return Promise.resolve({ delivered });
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: "await_next",
|
|
332
|
+
description: 'Wait for the next worker you spawned to FINISH, then read its deployable verdict. This is how you advance: spawn one or more workers, then call await_next to block until the next one settles. Returns { settled: workerId, status: "done"|"down", score, valid } for a finished worker, or { idle: true } when no worker is still running (then spawn more or stop). Workers run concurrently \u2014 spawn a batch, then await_next repeatedly to collect them.',
|
|
333
|
+
inputSchema: { type: "object", properties: {} },
|
|
334
|
+
handler: async () => {
|
|
335
|
+
const s = await opts.scope.next();
|
|
336
|
+
if (!s) return { idle: true };
|
|
337
|
+
const w = recordSettled(s);
|
|
338
|
+
return w.status === "done" ? { settled: w.id, status: "done", score: w.score, valid: w.valid } : { settled: w.id, status: "down", reason: w.reason };
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
name: "stop",
|
|
343
|
+
description: "Declare the run complete \u2014 every required change is made and verified. The terminal move.",
|
|
344
|
+
inputSchema: {
|
|
345
|
+
type: "object",
|
|
346
|
+
properties: { reason: { type: "string", description: "Why you are stopping." } }
|
|
347
|
+
},
|
|
348
|
+
handler: (raw) => {
|
|
349
|
+
stopped = true;
|
|
350
|
+
const r = obj(raw).reason;
|
|
351
|
+
reason = typeof r === "string" ? r : void 0;
|
|
352
|
+
return Promise.resolve({ stopped: true });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
];
|
|
356
|
+
if (opts.analystKinds) {
|
|
357
|
+
tools.push({
|
|
358
|
+
name: "list_analysts",
|
|
359
|
+
description: "List the trace-analyst lenses available to run over a worker \u2014 id, what each looks for, and its area.",
|
|
360
|
+
inputSchema: { type: "object", properties: {} },
|
|
361
|
+
handler: () => Promise.resolve({ analysts: opts.analystKinds })
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (opts.runAnalyst) {
|
|
365
|
+
tools.push({
|
|
366
|
+
name: "run_analyst",
|
|
367
|
+
description: "Apply an analyst LENS to a worker you are driving \u2014 run `kind` over the worker\u2019s trace and return its findings (trace-derived, never score-derived). Use `list_analysts` for the menu; run several lenses to triangulate. The worker must have settled (its trace is read from its output).",
|
|
368
|
+
inputSchema: {
|
|
369
|
+
type: "object",
|
|
370
|
+
properties: {
|
|
371
|
+
kind: { type: "string", description: "The analyst kind id (see list_analysts)." },
|
|
372
|
+
workerId: idArg
|
|
373
|
+
},
|
|
374
|
+
required: ["kind", "workerId"]
|
|
375
|
+
},
|
|
376
|
+
handler: async (raw) => {
|
|
377
|
+
const a = obj(raw);
|
|
378
|
+
const id = str(a.workerId, "workerId");
|
|
379
|
+
const node = opts.scope.view.nodes.find((n) => n.id === id);
|
|
380
|
+
if (!node) return { error: `unknown workerId ${JSON.stringify(id)}` };
|
|
381
|
+
if (!node.outRef)
|
|
382
|
+
return { error: `worker ${JSON.stringify(id)} has not settled \u2014 no trace to analyze yet` };
|
|
383
|
+
const trace = await opts.blobs.get(node.outRef);
|
|
384
|
+
return { findings: await opts.runAnalyst?.(str(a.kind, "kind"), trace) };
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return { tools, isStopped: () => stopped, stopReason: () => reason, settled: () => ledger };
|
|
389
|
+
}
|
|
69
390
|
export {
|
|
70
391
|
DELEGATE_CODE_DESCRIPTION,
|
|
71
392
|
DELEGATE_CODE_INPUT_SCHEMA,
|
|
@@ -76,6 +397,9 @@ export {
|
|
|
76
397
|
DELEGATE_RESEARCH_DESCRIPTION,
|
|
77
398
|
DELEGATE_RESEARCH_INPUT_SCHEMA,
|
|
78
399
|
DELEGATE_RESEARCH_TOOL_NAME,
|
|
400
|
+
DELEGATE_UI_AUDIT_DESCRIPTION,
|
|
401
|
+
DELEGATE_UI_AUDIT_INPUT_SCHEMA,
|
|
402
|
+
DELEGATE_UI_AUDIT_TOOL_NAME,
|
|
79
403
|
DELEGATION_HISTORY_DESCRIPTION,
|
|
80
404
|
DELEGATION_HISTORY_INPUT_SCHEMA,
|
|
81
405
|
DELEGATION_HISTORY_TOOL_NAME,
|
|
@@ -88,10 +412,12 @@ export {
|
|
|
88
412
|
buildDelegationMcpServer,
|
|
89
413
|
captureWorktreeDiff,
|
|
90
414
|
composeProductionAgentProfile,
|
|
415
|
+
createCoordinationTools,
|
|
91
416
|
createDefaultCoderDelegate,
|
|
92
417
|
createDelegateCodeHandler,
|
|
93
418
|
createDelegateFeedbackHandler,
|
|
94
419
|
createDelegateResearchHandler,
|
|
420
|
+
createDelegateUiAuditHandler,
|
|
95
421
|
createDelegationHistoryHandler,
|
|
96
422
|
createDelegationStatusHandler,
|
|
97
423
|
createFleetWorkspaceExecutor,
|
|
@@ -102,18 +428,24 @@ export {
|
|
|
102
428
|
createPropagatingTraceEmitter,
|
|
103
429
|
createSiblingSandboxExecutor,
|
|
104
430
|
createWorktree,
|
|
431
|
+
defaultChecks,
|
|
105
432
|
detectExecutor,
|
|
106
433
|
eventToSnapshot,
|
|
107
434
|
hashIdempotencyInput,
|
|
435
|
+
liftFindings,
|
|
436
|
+
makeCheckRunner,
|
|
108
437
|
mcpToolsForRuntimeMcp,
|
|
109
438
|
mcpToolsForRuntimeMcpSubset,
|
|
110
439
|
readTraceContextFromEnv,
|
|
111
440
|
removeWorktree,
|
|
441
|
+
renderTrace,
|
|
442
|
+
runCheck,
|
|
112
443
|
runLocalHarness,
|
|
113
444
|
traceContextToEnv,
|
|
114
445
|
validateDelegateCodeArgs,
|
|
115
446
|
validateDelegateFeedbackArgs,
|
|
116
447
|
validateDelegateResearchArgs,
|
|
448
|
+
validateDelegateUiAuditArgs,
|
|
117
449
|
validateDelegationHistoryArgs,
|
|
118
450
|
validateDelegationStatusArgs
|
|
119
451
|
};
|
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
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/** Build a `run_analyst` runner over a kind directory — the seam the operator toolbox is wired with.\n * Returns the findings, or a typed error for an unknown kind. `producedAt` is passed in (the runtime\n * forbids `Date.now` in replay-safe paths; the caller stamps it). */\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 * COORDINATION TOOLS — the verbs a parent agent uses to coordinate the child agents it spawns,\n * exposed as MCP tools backed by a live keystone `Scope`. This is `Scope`-as-MCP.\n *\n * NOT a transport. The cross-org message bus (`docs/agent-bus-protocol.md`) and the SDK's\n * `dispatchPrompt`/`SessionMessage` are the *transports* the `steer` verb rides; THIS file is the\n * verb set (the API). One verb, several bindings: in-process `Scope.send` is a direct call; across\n * sandboxes it rides SDK session-messaging; across orgs it rides the agent-bus protocol.\n *\n * spawn_worker → scope.spawn (budget-bounded, fail-closed — equal-k holds even for an LLM driver)\n * await_next → scope.next (THE wake event: block until the next spawned child settles)\n * observe_worker→ scope.view + the result blob (a child's status, spend, and settled output)\n * steer_worker → scope.send (deliver a next-instruction / interrupt to a RUNNING child)\n * list_analysts → the check menu (the trace lenses the agent can apply — see checks.ts)\n * run_analyst → apply a CHECK (run a kind over a child's trace → trace-derived findings)\n * stop → declare the run complete (the terminal move)\n *\n * The check verbs are present only when the check seam (`analystKinds` + `runAnalyst`) is wired —\n * an agent that does not review traces (a pure dispatcher) omits them. A trace check is a SEPARATE\n * lens (selector ≠ judge: it reads the trace, never the score); authoring a NEW check at runtime is\n * the next addition.\n *\n * A worker the driver spawns may itself carry the driver profile — `spawn_worker` does not care what\n * the profile is, so drivers-of-drivers fall out for free (each sub-driver gets its own sub-scope,\n * bounded by `maxDepth` + the conserved pool).\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` — the operator's running ledger of settled\n * workers + their DEPLOYABLE verdict (the driver IS the selector, so it legitimately reads the\n * verdict; the analyst, which reads only the trace, is the separate selector≠judge lens). The\n * driver picks its deliverable from this ledger at `stop`. */\nexport interface SettledWorker {\n readonly id: string\n readonly status: 'done' | 'down'\n /** Deployable score in [0,1] from the worker's verdict (done only). */\n readonly score?: number\n /** Whether the deployable verdict passed (done only). */\n readonly valid?: boolean\n /** Result-blob pointer for the worker's output/trace (done only). */\n readonly outRef?: string\n /** Failure reason (down only). */\n readonly reason?: string\n}\n\n/** How a `spawn_worker` profile becomes a spawnable leaf `Agent`. The caller wires this (e.g. the\n * surface registry turns a profile into a shot executor) so the toolbox stays domain-blind. */\nexport type MakeWorkerAgent = (profile: unknown) => SuperviseAgent<unknown, unknown>\n\nexport interface CoordinationToolsOptions {\n /** The DRIVER's live scope — spawn/observe/steer all act on this. */\n readonly scope: Scope<unknown>\n /** Result blobs, so `observe_worker` can rehydrate a settled worker's output. */\n readonly blobs: ResultBlobStore\n /** Turn a spawn_worker `profile` into a leaf agent (registry-resolved on spawn). */\n readonly makeWorkerAgent: MakeWorkerAgent\n /** Per-worker conserved budget the driver reserves on each spawn. */\n readonly perWorker: Budget\n /** The analyst lens menu (for `list_analysts`) — id + one-line + area. Injected so the toolbox\n * stays domain-blind; wire it from `analyst-kinds.ts`'s directory. Omit to disable analyst tools. */\n readonly analystKinds?: ReadonlyArray<{ id: string; description: string; area: string }>\n /** Run a lens over a worker's trace → findings (or a typed error). Wire it from\n * `makeCheckRunner(...)`. `run_analyst` fetches the worker's settled output and passes it here. */\n readonly runAnalyst?: (kindId: string, trace: unknown) => Promise<unknown>\n}\n\nexport interface CoordinationTools {\n /** MCP tools — register on an `McpServer`, or call the handlers directly in-process. */\n readonly tools: McpToolDescriptor[]\n /** True once the driver called `stop` — the operator loop reads this to terminate. */\n isStopped(): boolean\n /** The reason passed to `stop`, if any. */\n stopReason(): string | undefined\n /** The workers drained so far via `await_next` (the driver's selection ledger). */\n settled(): ReadonlyArray<SettledWorker>\n}\n\nconst idArg = { type: 'string', description: 'The workerId returned by spawn_worker.' } as const\n\n/** Build the operator toolbox over a live scope. The tools are the driver's verbs; their handlers\n * are thin wrappers over the keystone (spawn/view/send), so the budget/journal/abort discipline of\n * the Supervisor applies to a sandbox driver exactly as to the in-process one. */\nexport function createCoordinationTools(opts: CoordinationToolsOptions): CoordinationTools {\n let stopped = false\n let reason: string | undefined\n const ledger: SettledWorker[] = []\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 str = (v: unknown, field: string): string => {\n if (typeof v !== 'string' || v.length === 0)\n throw new Error(`operator toolbox: \"${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('operator toolbox: arguments must be an object')\n return raw as Record<string, unknown>\n }\n\n const tools: McpToolDescriptor[] = [\n {\n name: 'spawn_worker',\n description:\n 'Start a worker the operator will drive. `profile` is the worker (or another DRIVER — ' +\n 'drivers-of-drivers are allowed); `task` is what it should do. Reserves the worker’s budget ' +\n 'from the conserved pool and FAILS CLOSED when the pool is dry — so spawning \"at will\" is ' +\n 'bounded by the budget. Returns { workerId } or { error: \"budget-exhausted\" | \"depth-exceeded\" }.',\n inputSchema: {\n type: 'object',\n properties: {\n profile: { description: 'The worker/driver profile to run (passed to makeWorkerAgent).' },\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:\n 'Inspect a worker you are driving: its live status + conserved spend, and — once it has ' +\n 'settled — its output artifact (rehydrated from the result blob). Use this to review work ' +\n 'before deciding your next move. (In-flight token-level trace is surfaced via the analyst, ' +\n 'not here.)',\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:\n 'Steer a RUNNING worker out-of-band — deliver your next instruction / a course-correction / ' +\n 'an interrupt to its inbox. Returns { delivered } — false if the worker has finished or its ' +\n 'harness cannot be steered mid-flight (then spawn a fresh one or wait and re-observe).',\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 worker you spawned to FINISH, then read its deployable verdict. This is ' +\n 'how you advance: spawn one or more workers, then call await_next to block until the next ' +\n 'one settles. Returns { settled: workerId, status: \"done\"|\"down\", score, valid } for a ' +\n 'finished worker, or { idle: true } when no worker is still running (then spawn more or stop). ' +\n 'Workers run concurrently — spawn a batch, then await_next repeatedly to collect them.',\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 ? { settled: w.id, status: 'done', score: w.score, valid: w.valid }\n : { settled: w.id, status: 'down', reason: w.reason }\n },\n },\n {\n name: 'stop',\n description:\n 'Declare the run complete — every required change is made and verified. The terminal move.',\n inputSchema: {\n type: 'object',\n properties: { reason: { type: 'string', description: 'Why you are stopping.' } },\n },\n handler: (raw) => {\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 // list_analysts / run_analyst — present only when the analyst seam is wired. The driver picks a\n // kind from the menu and applies it to a worker it is driving; findings are trace-derived (the\n // firewall lives in the runner). (define_analyst — authoring a NEW kind at runtime — is deferred.)\n if (opts.analystKinds) {\n tools.push({\n name: 'list_analysts',\n description:\n 'List the trace-analyst lenses available to run over a worker — id, what each looks for, and its area.',\n inputSchema: { type: 'object', properties: {} },\n handler: () => Promise.resolve({ analysts: opts.analystKinds }),\n })\n }\n if (opts.runAnalyst) {\n tools.push({\n name: 'run_analyst',\n description:\n 'Apply an analyst LENS to a worker you are driving — run `kind` over the worker’s trace and ' +\n 'return its findings (trace-derived, never score-derived). Use `list_analysts` for the menu; ' +\n 'run several lenses to triangulate. The worker must have settled (its trace is read from its output).',\n inputSchema: {\n type: 'object',\n properties: {\n kind: { type: 'string', description: 'The analyst kind id (see list_analysts).' },\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.runAnalyst?.(str(a.kind, 'kind'), trace) }\n },\n })\n }\n\n return { tools, isStopped: () => stopped, stopReason: () => reason, settled: () => ledger }\n}\n"],"mappings":"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","names":[]}
|