@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/loops.d.ts
CHANGED
|
@@ -1,395 +1,9 @@
|
|
|
1
|
-
import { AgentProfile, SandboxEvent, SandboxInstance, CreateSandboxOptions } from '@tangle-network/sandbox';
|
|
2
1
|
export { AgentProfile, CreateSandboxOptions, SandboxEvent, SandboxInstance } from '@tangle-network/sandbox';
|
|
3
|
-
|
|
4
|
-
export { C as
|
|
5
|
-
|
|
6
|
-
export { E as
|
|
7
|
-
|
|
2
|
+
export { AssertTraceDerivedFindings, BridgeSeam, BudgetPool, BudgetReadout, CheckpointCapableBox, CliSeam, CombinatorShape, Corpus, CorpusFilter, CorpusRecord, CreateScopeAnalystOptions, CriuCapableClient, DefinePersona, DefinePersonaInput, Deliverable, EqualKArm, EqualKOnCost, EqualKOnCostOptions, EqualKVerdict, ExecutorConfig, Fanout, FanoutOptions, FanoutSynthesis, FileCorpus, FileResultBlobStore, FileSpawnJournal, FlatWidenGate, ForkCapableBox, InMemoryCorpus, InMemoryResultBlobStore, InMemorySpawnJournal, LoopDispatchOptions, LoopOptionsForDispatch, LoopShape, LoopUntil, LoopUntilSpec, LoopUntilState, OpenSandboxRunOptions, Outcome, Panel, PanelJudge, PanelSpec, PanelVerdict, Persona, PersonaContext, PersonaExecutors, Pipeline, PipelineStage, RenderCorpusToInstructions, RenderCorpusToInstructionsOptions, ReservationTicket, RouterSeam, RunPersonified, RunPersonifiedOptions, SandboxCapabilities, SandboxLineage, SandboxLineageHandle, SandboxRun, SandboxSeam, ScopeAnalyst, ScopeAnalyzeInput, ScopeWidenGate, SessionCapableBox, ShapeBudget, ShapeContext, ShapeRegistry, SteerContext, TrajectoryNode, TrajectoryReport, TrajectoryReportFn, TrajectoryReportOptions, TurnResult, UsageSink, Verify, VerifySpec, Widen, WidenDecision, WidenLineage, WidenSpec, acquireSandbox, assertTraceDerivedFindings, buildSteerContext, builtinShapes, contentAddress, createBudgetPool, createExecutor, createExecutorRegistry, createRootHandle, createSandboxLineage, createScope, createScopeAnalyst, createShapeRegistry, createSupervisor, definePersona, equalKOnCost, extractLlmCallEvent, fanout, flatWidenGate, inlineSandboxClient, loopDispatch, loopUntil, mapSandboxEvent, materializeTreeView, openSandboxRun, panel, pipeline, probeSandboxCapabilities, registerShape, renderCorpusToInstructions, replaySpawnTree, reportLoopUsage, runPersonified, settledToIteration, spendFromUsageEvents, trajectoryReport, verify, widen } from './runtime.js';
|
|
3
|
+
export { A as AnalyzeInput, a as CompletionAnalyst, b as CompletionEvidence, c as CompletionPolicy, d as CompletionVerdict, C as CreateDriverOptions, D as DriverDecision, P as PlannerContext, e as TopologyMove, T as TopologyPlanner, f as completionAuthorizes, g as createDriver, h as deterministicCompletion, r as renderAnalyses, s as sentinelCompletion, i as stopSentinel } from './driver-C-mtBo7h.js';
|
|
4
|
+
export { R as RunLoopOptions, c as createSandboxForSpec, d as defaultSelectWinner, r as runLoop } from './run-loop-CU2Y00Si.js';
|
|
5
|
+
export { A as Agent, d as AgentSpec, B as Budget, j as Executor, k as ExecutorContext, E as ExecutorFactory, e as ExecutorRegistry, l as ExecutorResult, H as Handle, N as NodeId, m as NodeSnapshot, n as NodeStatus, o as Restart, R as ResultBlobStore, f as RootHandle, p as RootSignal, q as Runtime, S as Scope, c as Settled, b as SpawnEvent, a as SpawnJournal, r as SpawnOpts, h as Spend, g as SupervisedResult, i as Supervisor, s as SupervisorOpts, T as TreeView, U as UsageEvent, W as WidenGate } from './types-BfoeiQRZ.js';
|
|
6
|
+
export { A as AgentRunSpec, D as Driver, E as ExecCtx, I as Iteration, C as LoopDecisionPayload, F as LoopEndedPayload, G as LoopIterationDispatchPayload, H as LoopIterationEndedPayload, J as LoopIterationStartedPayload, a as LoopLineageOptions, M as LoopPlanDescription, N as LoopPlanPayload, b as LoopResult, f as LoopSandboxPlacement, P as LoopStartedPayload, Q as LoopTeardownFailedPayload, c as LoopTokenUsage, e as LoopTraceEmitter, T as LoopTraceEvent, L as LoopWinner, O as OutputAdapter, S as SandboxClient, U as ValidationCtx, V as Validator } from './types-DnYoHvvZ.js';
|
|
8
7
|
export { DefaultVerdict } from '@tangle-network/agent-eval';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
export { c as createSandboxForSpec, r as runLoop } from './run-loop-C4L1Sted.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @experimental
|
|
15
|
-
*
|
|
16
|
-
* FanoutVote driver — N parallel attempts in iteration 0, pick the highest-
|
|
17
|
-
* scoring valid output. No second iteration: the topology is "spawn N, score,
|
|
18
|
-
* pick winner". The kernel handles heterogeneous fanout via the
|
|
19
|
-
* `agentRuns: AgentRunSpec[]` form on `runLoop`.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
type FanoutVoteDecision = 'pick-winner' | 'fail';
|
|
23
|
-
/** @experimental */
|
|
24
|
-
interface FanoutVoteScored<Task, Output> {
|
|
25
|
-
task: Task;
|
|
26
|
-
output: Output;
|
|
27
|
-
verdict?: DefaultVerdict;
|
|
28
|
-
iterationIndex: number;
|
|
29
|
-
agentRunName: string;
|
|
30
|
-
}
|
|
31
|
-
/** @experimental */
|
|
32
|
-
interface CreateFanoutVoteDriverOptions<Task, Output> {
|
|
33
|
-
/** Number of parallel attempts. Must be >= 1. */
|
|
34
|
-
n: number;
|
|
35
|
-
/**
|
|
36
|
-
* Pick the winner from the scored set. Default: highest `verdict.score`
|
|
37
|
-
* among valid outputs (ties broken by smallest iteration index). When
|
|
38
|
-
* no valid outputs exist, returns `undefined` and `decide()` resolves
|
|
39
|
-
* to `'fail'`. The kernel still records winners structurally — this
|
|
40
|
-
* selector only feeds `decide()`'s pass/fail signal.
|
|
41
|
-
*/
|
|
42
|
-
selector?: (scored: FanoutVoteScored<Task, Output>[]) => FanoutVoteScored<Task, Output> | undefined;
|
|
43
|
-
/** Stable identifier surfaced in trace events. Default `'fanout-vote'`. */
|
|
44
|
-
name?: string;
|
|
45
|
-
}
|
|
46
|
-
/** @experimental */
|
|
47
|
-
declare function createFanoutVoteDriver<Task, Output>(options: CreateFanoutVoteDriverOptions<Task, Output>): Driver<Task, Output, FanoutVoteDecision>;
|
|
48
|
-
/**
|
|
49
|
-
* Test helper: surface the per-iteration scored view a custom `selector`
|
|
50
|
-
* would receive. Exposed so consumers writing a custom selector can test it
|
|
51
|
-
* standalone without driving the full kernel.
|
|
52
|
-
*
|
|
53
|
-
* @experimental
|
|
54
|
-
*/
|
|
55
|
-
declare function scoreFanoutVoteIterations<Task, Output>(iterations: ReadonlyArray<Iteration<Task, Output>>): FanoutVoteScored<Task, Output>[];
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @experimental
|
|
59
|
-
*
|
|
60
|
-
* Named driver policies — a registry, not a constructor zoo.
|
|
61
|
-
*
|
|
62
|
-
* A "driver variant" is just a `TopologyPlanner` chosen by name and run by the
|
|
63
|
-
* one interpreter (`createDynamicDriver`). The agentic variants are sandboxed
|
|
64
|
-
* agents (`createSandboxPlanner`) — an LLM/agent in a box that emits the next
|
|
65
|
-
* move; this registry holds the *deterministic* ones a benchmark needs as
|
|
66
|
-
* controls. Today that's `blind`: a single attempt, no steering — the baseline
|
|
67
|
-
* you measure a real driver against.
|
|
68
|
-
*
|
|
69
|
-
* Adding a variant is a line here (or a sandboxed planner registered by name),
|
|
70
|
-
* never a new `createXDriver` factory and never a spec schema.
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
|
-
/** A driver policy over prompt-shaped (string) tasks. Output is consulted only
|
|
74
|
-
* through the iteration's verdict, so it stays `unknown`. */
|
|
75
|
-
type PromptPlanner = TopologyPlanner<string, unknown>;
|
|
76
|
-
/**
|
|
77
|
-
* `blind` — one attempt, then stop. The no-driver control: a single worker run
|
|
78
|
-
* with no steering, so a benchmark can isolate what a real driver adds.
|
|
79
|
-
*/
|
|
80
|
-
declare const blind: PromptPlanner;
|
|
81
|
-
/** The registry. Pick a driver by name (e.g. `DRIVER=blind`); fail loud on an
|
|
82
|
-
* unknown key. Sandboxed-agent planners can be registered here too. */
|
|
83
|
-
declare const PROMPT_PLANNERS: Record<string, PromptPlanner>;
|
|
84
|
-
/** Resolve a planner by name; fail loud on an unknown variant. */
|
|
85
|
-
declare function resolvePlanner(name: string): PromptPlanner;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @experimental
|
|
89
|
-
*
|
|
90
|
-
* Refine driver — single task per iteration, validator-gated.
|
|
91
|
-
*
|
|
92
|
-
* `plan` returns `[task]` (possibly transformed via `refineTask`) until the
|
|
93
|
-
* prior verdict is valid OR the local cap is hit, then `[]`.
|
|
94
|
-
* `decide` returns `'stop'` once the latest verdict is valid OR the cap is
|
|
95
|
-
* reached. The kernel's `maxIterations` is an orthogonal safety cap;
|
|
96
|
-
* whichever is lower wins.
|
|
97
|
-
*/
|
|
98
|
-
|
|
99
|
-
type RefineDecision = 'continue' | 'stop';
|
|
100
|
-
/** @experimental */
|
|
101
|
-
interface CreateRefineDriverOptions<Task> {
|
|
102
|
-
/** Hard cap on iterations. Default 5. */
|
|
103
|
-
maxIterations?: number;
|
|
104
|
-
/**
|
|
105
|
-
* Optional task transform applied each round based on the prior verdict.
|
|
106
|
-
* When omitted, the same task is replayed and the agent is expected to
|
|
107
|
-
* inspect the sandbox session state for prior attempts.
|
|
108
|
-
*/
|
|
109
|
-
refineTask?: (task: Task, prior: DefaultVerdict) => Task;
|
|
110
|
-
/** Stable identifier surfaced in trace events. Default `'refine'`. */
|
|
111
|
-
name?: string;
|
|
112
|
-
}
|
|
113
|
-
/** @experimental */
|
|
114
|
-
declare function createRefineDriver<Task, Output>(options?: CreateRefineDriverOptions<Task>): Driver<Task, Output, RefineDecision>;
|
|
115
|
-
/**
|
|
116
|
-
* Test helper: select the last-valid iteration (or the last attempt if
|
|
117
|
-
* none passed). Mirrors the kernel's default selector ordering for refine
|
|
118
|
-
* topologies — the most recent successful attempt wins.
|
|
119
|
-
*
|
|
120
|
-
* @experimental
|
|
121
|
-
*/
|
|
122
|
-
declare function refineWinnerIndex<Task, Output>(iterations: ReadonlyArray<Iteration<Task, Output>>): number | undefined;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* @experimental
|
|
126
|
-
*
|
|
127
|
-
* `createSandboxPlanner` — wire the dynamic driver's `TopologyPlanner` to a
|
|
128
|
-
* real agent. Each round it spins a sandbox on `profile`, streams a prompt that
|
|
129
|
-
* carries the history summary, and decodes the agent's chosen `TopologyMove`
|
|
130
|
-
* from a JSON envelope it emits. This is the "agent authors its own loop
|
|
131
|
-
* topology" path: the planner profile can be any harness (claude-code, codex,
|
|
132
|
-
* opencode, pi) — its only job is to read what happened and emit the next move.
|
|
133
|
-
*
|
|
134
|
-
* The planner profile is deliberately distinct from the worker `agentRuns`: a
|
|
135
|
-
* cheap fast model can steer topology while expensive workers do the labor, and
|
|
136
|
-
* the planner never names which harness runs a branch — the kernel's
|
|
137
|
-
* `agentRuns` round-robin decides that.
|
|
138
|
-
*
|
|
139
|
-
* Three execution modes, all the same code path:
|
|
140
|
-
* - LLM call — a cheap-model `profile`; one prompt → one move.
|
|
141
|
-
* - different sandbox (default) — a fresh planner-owned box per round.
|
|
142
|
-
* - same sandbox — pass `reuseBox` to stream the move into the worker's
|
|
143
|
-
* own box (a session against its live filesystem/state),
|
|
144
|
-
* so the driver steers from what the worker actually did.
|
|
145
|
-
*
|
|
146
|
-
* Envelope contract the agent must emit (fenced ```json or a structured
|
|
147
|
-
* `result`/`final` event payload):
|
|
148
|
-
* { "kind": "refine" | "fanout" | "stop",
|
|
149
|
-
* "tasks"?: [ <task>, ... ], // decoded via `decodeTask`
|
|
150
|
-
* "n"?: number, // fanout shorthand: N copies of the root task
|
|
151
|
-
* "rationale"?: string }
|
|
152
|
-
*
|
|
153
|
-
* A missing / unparseable / unknown-kind envelope throws `PlannerError` — the
|
|
154
|
-
* loop never silently runs a topology the agent did not choose.
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
|
-
/** Raw, pre-decode envelope an agent emits to choose the next move. */
|
|
158
|
-
interface TopologyMoveEnvelope {
|
|
159
|
-
kind: string;
|
|
160
|
-
tasks?: unknown[];
|
|
161
|
-
n?: number;
|
|
162
|
-
rationale?: string;
|
|
163
|
-
}
|
|
164
|
-
/** @experimental */
|
|
165
|
-
interface CreateSandboxPlannerOptions<Task, Output> {
|
|
166
|
-
/** Sandbox client — the planner calls `.create()` once per round. */
|
|
167
|
-
client: LoopSandboxClient;
|
|
168
|
-
/** The planner agent. Steers topology; does not run the work. */
|
|
169
|
-
profile: AgentProfile;
|
|
170
|
-
/**
|
|
171
|
-
* Decode one raw task from the envelope's `tasks[]` into a domain `Task`.
|
|
172
|
-
* Required because `Task` is opaque to this module — only the caller knows
|
|
173
|
-
* its shape. Throw to reject a malformed task; the error surfaces as a
|
|
174
|
-
* `PlannerError`.
|
|
175
|
-
*/
|
|
176
|
-
decodeTask: (raw: unknown, ctx: PlannerContext<Task, Output>) => Task;
|
|
177
|
-
/** Override the default prompt (history summary + envelope contract). */
|
|
178
|
-
buildPrompt?: (ctx: PlannerContext<Task, Output>) => string | Promise<string>;
|
|
179
|
-
/** Override envelope extraction from the event stream. */
|
|
180
|
-
parseEnvelope?: (events: SandboxEvent[]) => TopologyMoveEnvelope | undefined;
|
|
181
|
-
/** Sandbox overrides for the planner sandbox (timeouts, env, etc.). */
|
|
182
|
-
sandboxOverrides?: AgentRunSpec<Task>['sandboxOverrides'];
|
|
183
|
-
/** Cancellation for the planner's own LLM call. */
|
|
184
|
-
signal?: AbortSignal;
|
|
185
|
-
/**
|
|
186
|
-
* Same-sandbox mode. Return an existing box and the planner streams its move
|
|
187
|
-
* INTO that box (a session against the worker's environment) instead of
|
|
188
|
-
* spinning its own — so the driver can inspect the worker's real filesystem
|
|
189
|
-
* and state, not just the history summary. The returned box's lifecycle is
|
|
190
|
-
* the CALLER's: the planner neither creates nor deletes it. Return
|
|
191
|
-
* `undefined` to fall back to the default (a fresh, planner-owned box =
|
|
192
|
-
* different-sandbox mode). Omit entirely for the default.
|
|
193
|
-
*/
|
|
194
|
-
reuseBox?: () => SandboxInstance | undefined | Promise<SandboxInstance | undefined>;
|
|
195
|
-
}
|
|
196
|
-
/** @experimental */
|
|
197
|
-
declare function createSandboxPlanner<Task, Output>(opts: CreateSandboxPlannerOptions<Task, Output>): TopologyPlanner<Task, Output>;
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* `loopDispatch` — turn `runLoop` into an agent-eval campaign dispatch.
|
|
201
|
-
*
|
|
202
|
-
* Without this adapter a consumer wiring `runLoop` into `runProfileMatrix` /
|
|
203
|
-
* `runCampaign` has to, by hand, every time: (a) build an `ExecCtx` with a
|
|
204
|
-
* sandbox client, (b) adapt the campaign `DispatchContext.trace` into a
|
|
205
|
-
* `LoopTraceEmitter` (or lose all loop trace correlation), and (c) remember to
|
|
206
|
-
* forward the loop's cost + tokens via `ctx.cost` (forgetting it yields a
|
|
207
|
-
* `{0,0}` cell the backend-integrity guard reads as a stub). Three foot-guns,
|
|
208
|
-
* the third silent. The fleet's products skipped (c) and fell back to a
|
|
209
|
-
* `workerRecords[]` side-channel — the exact anti-pattern the substrate exists
|
|
210
|
-
* to kill.
|
|
211
|
-
*
|
|
212
|
-
* `loopDispatch` collapses all three into one typed call:
|
|
213
|
-
*
|
|
214
|
-
* const dispatch = loopDispatch({
|
|
215
|
-
* sandboxClient,
|
|
216
|
-
* toLoopOptions: (scenario, profile) => ({ driver, agentRun, output, validator, task }),
|
|
217
|
-
* })
|
|
218
|
-
* await runProfileMatrix({ profiles, scenarios, dispatch, judges, commitSha })
|
|
219
|
-
*
|
|
220
|
-
* Usage is reported automatically; trace events are forwarded automatically;
|
|
221
|
-
* the ctx is built automatically. The seam becomes impossible to mis-wire.
|
|
222
|
-
*
|
|
223
|
-
* Typed structurally against the campaign `DispatchContext` (imported type-only
|
|
224
|
-
* from `@tangle-network/agent-eval/campaign`) — a downward dependency, never an
|
|
225
|
-
* inversion.
|
|
226
|
-
*/
|
|
227
|
-
|
|
228
|
-
/** runLoop options minus the `ctx` (loopDispatch builds the ctx). */
|
|
229
|
-
type LoopOptionsForDispatch<Task, Output, Decision> = Omit<RunLoopOptions<Task, Output, Decision>, 'ctx'>;
|
|
230
|
-
interface LoopDispatchOptions<Task, Output, Decision, TScenario extends Scenario, TArtifact> {
|
|
231
|
-
/** Sandbox client used for every cell's `runLoop`. Supplied once. */
|
|
232
|
-
sandboxClient: LoopSandboxClient;
|
|
233
|
-
/** Build the per-cell runLoop options from the scenario (+ profile, when
|
|
234
|
-
* used with `runProfileMatrix`). */
|
|
235
|
-
toLoopOptions: (scenario: TScenario, profile: AgentProfile$1) => LoopOptionsForDispatch<Task, Output, Decision>;
|
|
236
|
-
/** Map the finished loop to the artifact the judges score. Default:
|
|
237
|
-
* `result.winner?.output`. A loop with no winner yields `undefined` (judges
|
|
238
|
-
* skip the cell) — but the loop's token usage is STILL reported, so the
|
|
239
|
-
* integrity guard sees real activity. */
|
|
240
|
-
toArtifact?: (result: LoopResult<Task, Output, Decision>) => TArtifact;
|
|
241
|
-
/** Forward `loop.*` trace events into the campaign's scoped trace so loop
|
|
242
|
-
* spans correlate with the cell. Default true. */
|
|
243
|
-
forwardTrace?: boolean;
|
|
244
|
-
/** Cost-meter source label for the loop's spend. Default `'loop'`. */
|
|
245
|
-
costSource?: string;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Adapter for `runProfileMatrix` (profile is an axis). Returns a
|
|
249
|
-
* `ProfileDispatchFn` that runs `runLoop` per (profile, scenario) cell and
|
|
250
|
-
* reports usage automatically.
|
|
251
|
-
*/
|
|
252
|
-
declare function loopDispatch<Task, Output, Decision, TScenario extends Scenario, TArtifact>(opts: LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact>): ProfileDispatchFn<TScenario, TArtifact>;
|
|
253
|
-
/**
|
|
254
|
-
* Adapter for `runCampaign` (no profile axis). `toLoopOptions` receives only
|
|
255
|
-
* the scenario; the `profile` passed to the shared core is a stable sentinel
|
|
256
|
-
* so a single `runLoop` config is reused across cells.
|
|
257
|
-
*/
|
|
258
|
-
declare function loopCampaignDispatch<Task, Output, Decision, TScenario extends Scenario, TArtifact>(opts: Omit<LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact>, 'toLoopOptions'> & {
|
|
259
|
-
toLoopOptions: (scenario: TScenario) => LoopOptionsForDispatch<Task, Output, Decision>;
|
|
260
|
-
}): DispatchFn<TScenario, TArtifact>;
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Bridge a finished `runLoop` into an agent-eval campaign / profile-matrix
|
|
264
|
-
* dispatch.
|
|
265
|
-
*
|
|
266
|
-
* `runProfileMatrix` (and `runCampaign`) run the backend-integrity guard over
|
|
267
|
-
* the token usage a dispatch reports through `ctx.cost`. A dispatch that wraps
|
|
268
|
-
* `runLoop` must forward the loop's cost AND token usage, or the guard reads
|
|
269
|
-
* the run as a stub and throws. `reportLoopUsage` is that one line:
|
|
270
|
-
*
|
|
271
|
-
* const dispatch: ProfileDispatchFn<S, A> = async (profile, scenario, ctx) => {
|
|
272
|
-
* const result = await runLoop({ ...optsFor(profile, scenario), ctx: loopCtx })
|
|
273
|
-
* reportLoopUsage(ctx, result)
|
|
274
|
-
* return result.winner?.output as A
|
|
275
|
-
* }
|
|
276
|
-
*
|
|
277
|
-
* Typed structurally against the campaign `DispatchContext.cost` so this module
|
|
278
|
-
* stays free of an agent-eval import — it works with any cost meter exposing
|
|
279
|
-
* `observe` + `observeTokens`.
|
|
280
|
-
*/
|
|
281
|
-
|
|
282
|
-
/** The slice of an agent-eval campaign `DispatchContext.cost` this needs. */
|
|
283
|
-
interface UsageSink {
|
|
284
|
-
observe(amountUsd: number, source: string): void;
|
|
285
|
-
observeTokens(usage: {
|
|
286
|
-
input: number;
|
|
287
|
-
output: number;
|
|
288
|
-
}): void;
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Forward a `LoopResult`'s aggregated cost + token usage into a campaign cost
|
|
292
|
-
* meter so the backend-integrity guard sees real LLM activity. `source`
|
|
293
|
-
* defaults to `'loop'`.
|
|
294
|
-
*/
|
|
295
|
-
declare function reportLoopUsage<Task, Output, Decision>(cost: UsageSink, result: Pick<LoopResult<Task, Output, Decision>, 'costUsd' | 'tokenUsage'>, source?: string): void;
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* @experimental
|
|
299
|
-
*
|
|
300
|
-
* `acquireSandbox` — cold-start-resilient sandbox acquisition. Eliminates the
|
|
301
|
-
* "create timed out at the proxy" failure mode conceptually by DECOUPLING "the
|
|
302
|
-
* create HTTP call returned" from "the sandbox is ready":
|
|
303
|
-
*
|
|
304
|
-
* - Create is initiated with a known `name`.
|
|
305
|
-
* - Readiness is observed from the sandbox's own `status` (`refresh()` polls
|
|
306
|
-
* true state), NOT from whether the create call returned in time.
|
|
307
|
-
* - If the create call itself times out at a gateway (502/503/504/522/524 or
|
|
308
|
-
* a transport timeout), provisioning is still running server-side — so we
|
|
309
|
-
* find the named sandbox via `list()` and wait for it to reach `running`.
|
|
310
|
-
*
|
|
311
|
-
* Result: a scale-from-zero cold start (node boot + host-agent registration,
|
|
312
|
-
* minutes) can no longer surface as a create failure behind a ~100s proxy
|
|
313
|
-
* limit. The loop becomes indifferent to whether the host pool is warm or cold.
|
|
314
|
-
*
|
|
315
|
-
* Backward-compatible: an instance that reports no `status` (the minimal fakes
|
|
316
|
-
* the loop tests use) is treated as ready — only an explicit `pending`/
|
|
317
|
-
* `provisioning` status triggers waiting, and only a retryable THROW triggers
|
|
318
|
-
* the find-by-name path. Real errors (auth, validation, budget) fail loud.
|
|
319
|
-
*/
|
|
320
|
-
|
|
321
|
-
/** @experimental */
|
|
322
|
-
interface AcquireOptions {
|
|
323
|
-
/**
|
|
324
|
-
* Total budget for the sandbox to reach `running`, covering on-demand node
|
|
325
|
-
* cold-start. Default 600_000ms — matches the orchestrator's pending-host
|
|
326
|
-
* registration window so we never give up before the platform itself would.
|
|
327
|
-
*/
|
|
328
|
-
readyTimeoutMs?: number;
|
|
329
|
-
/** Poll interval while waiting for `running` / for the named sandbox to appear. */
|
|
330
|
-
pollIntervalMs?: number;
|
|
331
|
-
/** Cancellation (user abort). Distinct from create-call timeouts. */
|
|
332
|
-
signal?: AbortSignal;
|
|
333
|
-
/** Stamp a name so a timed-out create is recoverable by lookup. Auto-generated if absent. */
|
|
334
|
-
name?: string;
|
|
335
|
-
/** Clock override for deterministic tests. */
|
|
336
|
-
now?: () => number;
|
|
337
|
-
/** Sleep override for deterministic tests. */
|
|
338
|
-
sleep?: (ms: number) => Promise<void>;
|
|
339
|
-
}
|
|
340
|
-
/** @experimental */
|
|
341
|
-
declare function acquireSandbox(client: LoopSandboxClient, options: CreateSandboxOptions, acquire?: AcquireOptions): Promise<SandboxInstance>;
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Sandbox-event → runtime-event mapping.
|
|
345
|
-
*
|
|
346
|
-
* The sandbox SDK emits a polymorphic `SandboxEvent = { type, data, id? }`
|
|
347
|
-
* whose `type` vocabulary is backend-determined (opencode, etc.) rather than
|
|
348
|
-
* enumerated by the SDK. Two consumers project it:
|
|
349
|
-
* - the loop kernel's cost ledger (`extractLlmCallEvent`) — sums usage off
|
|
350
|
-
* every cost-bearing event, regardless of stream shape;
|
|
351
|
-
* - the `AgentRuntime.act` streaming contract (`mapSandboxEvent`) — projects
|
|
352
|
-
* incremental events to the `RuntimeStreamEvent` chat-UX vocabulary.
|
|
353
|
-
*
|
|
354
|
-
* Both live here so the empirically-observed `type` vocabulary has one home.
|
|
355
|
-
*/
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Extract a `RuntimeStreamEvent`-shaped `llm_call` from a sandbox event when
|
|
359
|
-
* the event carries usage/cost data. Returns `undefined` for non-cost events
|
|
360
|
-
* so the kernel can iterate the full stream without branching.
|
|
361
|
-
*
|
|
362
|
-
* Canonical cost-carrying types observed in the wild:
|
|
363
|
-
* - `llm_call` — `data: { model, tokensIn, tokensOut, costUsd, ... }`
|
|
364
|
-
* - `message.completed` / `result` — `data: { usage: { inputTokens,
|
|
365
|
-
* outputTokens, totalCostUsd? } }`
|
|
366
|
-
* - `cost.usage` / `usage` — same shape under a dedicated type
|
|
367
|
-
*
|
|
368
|
-
* Numeric coercion is strict: `Number.isFinite` gates every accumulator write
|
|
369
|
-
* so a sentinel `NaN` from a misbehaving backend cannot poison the ledger.
|
|
370
|
-
*/
|
|
371
|
-
declare function extractLlmCallEvent(event: SandboxEvent, agentRunName: string): (RuntimeStreamEvent & {
|
|
372
|
-
type: 'llm_call';
|
|
373
|
-
}) | undefined;
|
|
374
|
-
/**
|
|
375
|
-
* Project one `SandboxEvent` onto the `RuntimeStreamEvent` chat-UX vocabulary,
|
|
376
|
-
* for runtimes that bridge a sandbox `streamPrompt` into the
|
|
377
|
-
* `AgentRuntime.act` streaming contract. Returns `undefined` for events that
|
|
378
|
-
* have no faithful projection — the raw stream is preserved separately for the
|
|
379
|
-
* `OutputAdapter`, so an unmapped event never loses data.
|
|
380
|
-
*
|
|
381
|
-
* Mapped (the task-optional incremental variants — no synthesized task
|
|
382
|
-
* lifecycle, no guessed tool-part shapes):
|
|
383
|
-
* - `message.part.updated` text part → `text_delta`
|
|
384
|
-
* - `message.part.updated` reasoning/thinking part → `reasoning_delta`
|
|
385
|
-
* - cost-bearing events → `llm_call` (shared with the ledger extractor)
|
|
386
|
-
*
|
|
387
|
-
* The opencode backend emits incremental text as
|
|
388
|
-
* `{ type: 'message.part.updated', data: { part: { type, text }, delta } }`;
|
|
389
|
-
* `delta` is the increment, `part.text` the running accumulation.
|
|
390
|
-
*/
|
|
391
|
-
declare function mapSandboxEvent(event: SandboxEvent, opts?: {
|
|
392
|
-
agentRunName?: string;
|
|
393
|
-
}): RuntimeStreamEvent | undefined;
|
|
394
|
-
|
|
395
|
-
export { type AcquireOptions, AgentRunSpec, type CreateFanoutVoteDriverOptions, type CreateRefineDriverOptions, type CreateSandboxPlannerOptions, Driver, type FanoutVoteDecision, type FanoutVoteScored, Iteration, type LoopDispatchOptions, type LoopOptionsForDispatch, LoopResult, LoopSandboxClient, PROMPT_PLANNERS, PlannerContext, type PromptPlanner, type RefineDecision, RunLoopOptions, type TopologyMoveEnvelope, TopologyPlanner, type UsageSink, acquireSandbox, blind, createFanoutVoteDriver, createRefineDriver, createSandboxPlanner, extractLlmCallEvent, loopCampaignDispatch, loopDispatch, mapSandboxEvent, refineWinnerIndex, reportLoopUsage, resolvePlanner, scoreFanoutVoteIterations };
|
|
8
|
+
import '@tangle-network/agent-eval/campaign';
|
|
9
|
+
import './runtime-hooks-C7JwKb9E.js';
|
package/dist/loops.js
CHANGED
|
@@ -1,45 +1,114 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
FileCorpus,
|
|
3
|
+
FileResultBlobStore,
|
|
4
|
+
FileSpawnJournal,
|
|
5
|
+
InMemoryCorpus,
|
|
6
|
+
InMemoryResultBlobStore,
|
|
7
|
+
InMemorySpawnJournal,
|
|
3
8
|
acquireSandbox,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
assertTraceDerivedFindings,
|
|
10
|
+
buildSteerContext,
|
|
11
|
+
builtinShapes,
|
|
12
|
+
completionAuthorizes,
|
|
13
|
+
contentAddress,
|
|
14
|
+
createBudgetPool,
|
|
15
|
+
createDriver,
|
|
16
|
+
createExecutor,
|
|
17
|
+
createExecutorRegistry,
|
|
18
|
+
createRootHandle,
|
|
7
19
|
createSandboxForSpec,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
createSandboxLineage,
|
|
21
|
+
createScope,
|
|
22
|
+
createScopeAnalyst,
|
|
23
|
+
createShapeRegistry,
|
|
24
|
+
createSupervisor,
|
|
25
|
+
defaultSelectWinner,
|
|
26
|
+
definePersona,
|
|
27
|
+
deterministicCompletion,
|
|
28
|
+
equalKOnCost,
|
|
29
|
+
fanout,
|
|
30
|
+
flatWidenGate,
|
|
31
|
+
inlineSandboxClient,
|
|
11
32
|
loopDispatch,
|
|
12
|
-
|
|
13
|
-
|
|
33
|
+
loopUntil,
|
|
34
|
+
materializeTreeView,
|
|
35
|
+
openSandboxRun,
|
|
36
|
+
panel,
|
|
37
|
+
pipeline,
|
|
38
|
+
probeSandboxCapabilities,
|
|
39
|
+
registerShape,
|
|
40
|
+
renderAnalyses,
|
|
41
|
+
renderCorpusToInstructions,
|
|
42
|
+
replaySpawnTree,
|
|
14
43
|
reportLoopUsage,
|
|
15
|
-
resolvePlanner,
|
|
16
44
|
runLoop,
|
|
17
|
-
|
|
18
|
-
|
|
45
|
+
runPersonified,
|
|
46
|
+
sentinelCompletion,
|
|
47
|
+
settledToIteration,
|
|
48
|
+
spendFromUsageEvents,
|
|
49
|
+
stopSentinel,
|
|
50
|
+
trajectoryReport,
|
|
51
|
+
verify,
|
|
52
|
+
widen
|
|
53
|
+
} from "./chunk-65FQLI4V.js";
|
|
19
54
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-SQSCRJ7U.js";
|
|
55
|
+
extractLlmCallEvent,
|
|
56
|
+
mapSandboxEvent
|
|
57
|
+
} from "./chunk-GSUO5QS6.js";
|
|
24
58
|
import "./chunk-DGUM43GV.js";
|
|
25
59
|
export {
|
|
26
|
-
|
|
60
|
+
FileCorpus,
|
|
61
|
+
FileResultBlobStore,
|
|
62
|
+
FileSpawnJournal,
|
|
63
|
+
InMemoryCorpus,
|
|
64
|
+
InMemoryResultBlobStore,
|
|
65
|
+
InMemorySpawnJournal,
|
|
27
66
|
acquireSandbox,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
67
|
+
assertTraceDerivedFindings,
|
|
68
|
+
buildSteerContext,
|
|
69
|
+
builtinShapes,
|
|
70
|
+
completionAuthorizes,
|
|
71
|
+
contentAddress,
|
|
72
|
+
createBudgetPool,
|
|
73
|
+
createDriver,
|
|
74
|
+
createExecutor,
|
|
75
|
+
createExecutorRegistry,
|
|
76
|
+
createRootHandle,
|
|
32
77
|
createSandboxForSpec,
|
|
33
|
-
|
|
78
|
+
createSandboxLineage,
|
|
79
|
+
createScope,
|
|
80
|
+
createScopeAnalyst,
|
|
81
|
+
createShapeRegistry,
|
|
82
|
+
createSupervisor,
|
|
83
|
+
defaultSelectWinner,
|
|
84
|
+
definePersona,
|
|
85
|
+
deterministicCompletion,
|
|
86
|
+
equalKOnCost,
|
|
34
87
|
extractLlmCallEvent,
|
|
35
|
-
|
|
88
|
+
fanout,
|
|
89
|
+
flatWidenGate,
|
|
90
|
+
inlineSandboxClient,
|
|
36
91
|
loopDispatch,
|
|
92
|
+
loopUntil,
|
|
37
93
|
mapSandboxEvent,
|
|
38
|
-
|
|
94
|
+
materializeTreeView,
|
|
95
|
+
openSandboxRun,
|
|
96
|
+
panel,
|
|
97
|
+
pipeline,
|
|
98
|
+
probeSandboxCapabilities,
|
|
99
|
+
registerShape,
|
|
100
|
+
renderAnalyses,
|
|
101
|
+
renderCorpusToInstructions,
|
|
102
|
+
replaySpawnTree,
|
|
39
103
|
reportLoopUsage,
|
|
40
|
-
resolvePlanner,
|
|
41
104
|
runLoop,
|
|
42
|
-
|
|
43
|
-
|
|
105
|
+
runPersonified,
|
|
106
|
+
sentinelCompletion,
|
|
107
|
+
settledToIteration,
|
|
108
|
+
spendFromUsageEvents,
|
|
109
|
+
stopSentinel,
|
|
110
|
+
trajectoryReport,
|
|
111
|
+
verify,
|
|
112
|
+
widen
|
|
44
113
|
};
|
|
45
114
|
//# sourceMappingURL=loops.js.map
|
package/dist/mcp/bin.js
CHANGED
|
@@ -4,18 +4,18 @@ import {
|
|
|
4
4
|
createPropagatingTraceEmitter,
|
|
5
5
|
detectExecutor,
|
|
6
6
|
readTraceContextFromEnv
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-KPN7OQ64.js";
|
|
8
|
+
import "../chunk-WIR4HOOJ.js";
|
|
9
|
+
import "../chunk-JNPK46YH.js";
|
|
9
10
|
import {
|
|
10
11
|
createDefaultCoderDelegate
|
|
11
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-I42NHLKX.js";
|
|
13
|
+
import "../chunk-KADIJAD4.js";
|
|
12
14
|
import "../chunk-GLR25NG7.js";
|
|
13
15
|
import {
|
|
14
16
|
runLoop
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-PY6NMZYX.js";
|
|
18
|
-
import "../chunk-SQSCRJ7U.js";
|
|
17
|
+
} from "../chunk-65FQLI4V.js";
|
|
18
|
+
import "../chunk-GSUO5QS6.js";
|
|
19
19
|
import "../chunk-DGUM43GV.js";
|
|
20
20
|
|
|
21
21
|
// src/mcp/bin.ts
|
package/dist/mcp/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @experimental\n *\n * `agent-runtime-mcp` — stdio MCP server entry point.\n *\n * Spins up a server with the default coder delegate (wired against the\n * real `@tangle-network/sandbox` client) and, when the optional\n * `@tangle-network/agent-knowledge` peer is installed, a researcher\n * delegate against `multiHarnessResearcherFanout`.\n *\n * Environment variables:\n * TANGLE_API_KEY required — passed to `new Sandbox({ apiKey })`\n * SANDBOX_BASE_URL optional — sandbox-SDK base URL override\n * TANGLE_FLEET_ID optional — when set, delegations dispatch\n * INTO this fleet's shared workspace instead\n * of creating sibling sandboxes. Set by the\n * parent sandbox when launching this MCP\n * server so worker diffs land on the caller's\n * filesystem with no cross-sandbox boundary.\n * TANGLE_FLEET_EXCLUDE_MACHINES optional — comma-separated machine ids to\n * skip during fleet-mode round-robin\n * (typically the coordinator machine this\n * MCP server is running on).\n * MCP_MAX_CONCURRENT_SANDBOXES default 4 — kernel maxConcurrency cap\n * MCP_CODER_FANOUT_HARNESSES comma-separated harness ids to use for variants > 1\n * MCP_DISABLE_CODER set to `1` to omit `delegate_code`\n * MCP_DISABLE_RESEARCHER set to `1` to omit `delegate_research` even when peer is present\n */\n\nimport type { LoopSandboxClient, LoopTraceEmitter } from '../loops'\nimport { runLoop } from '../loops'\nimport { detectExecutor } from './bin-helpers'\nimport { createDefaultCoderDelegate, type ResearcherDelegate } from './delegates'\nimport type { DelegationExecutor } from './executor'\nimport { createMcpServer } from './server'\nimport { createPropagatingTraceEmitter, readTraceContextFromEnv } from './trace-propagation'\nimport type { ResearchOutputShape } from './types'\n\nasync function main(): Promise<void> {\n const fanoutHarnesses = parseHarnesses(process.env.MCP_CODER_FANOUT_HARNESSES)\n const maxConcurrency = parseConcurrency(process.env.MCP_MAX_CONCURRENT_SANDBOXES)\n const wantCoder = !process.env.MCP_DISABLE_CODER\n const wantResearcher = !process.env.MCP_DISABLE_RESEARCHER\n const fleetId = parseFleetId(process.env.TANGLE_FLEET_ID)\n\n // Skip the sandbox client load entirely when no profile delegate needs it —\n // the feedback + status + history tools are queue-bound and require no\n // sandbox. Useful for tooling that mounts the MCP server purely for\n // self-introspection.\n const needsSandbox = wantCoder || wantResearcher\n let sandboxClient: LoopSandboxClient | undefined\n let executor: DelegationExecutor | undefined\n if (needsSandbox) {\n const apiKey = process.env.TANGLE_API_KEY\n if (!apiKey && !process.env.AGENT_RUNTIME_MCP_ALLOW_NO_KEY) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_API_KEY is required. Set AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 to run without it for diagnostics, or MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to run the queue-only subset.\\n',\n )\n process.exit(2)\n }\n // Fleet mode against a diagnostic stub is meaningless — the stub can't\n // resolve a real fleet handle. Refuse rather than silently degrading,\n // otherwise a fleet-mounted MCP would behave differently than configured.\n if (fleetId && !apiKey) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_FLEET_ID was set but TANGLE_API_KEY is missing; cannot resolve fleet handle. Provide an api key or unset TANGLE_FLEET_ID.\\n',\n )\n process.exit(2)\n }\n sandboxClient = await loadSandboxClient(apiKey)\n executor = await detectExecutor({ sandboxClient })\n if (fleetId) {\n process.stderr.write(`agent-runtime-mcp: fleet-aware delegation: fleetId=${fleetId}\\n`)\n }\n process.stderr.write(`agent-runtime-mcp: delegation placement → ${executor.describe()}\\n`)\n }\n\n // Export delegated-loop topology spans to the OTLP / Tangle Intelligence sink\n // when OTEL_EXPORTER_OTLP_ENDPOINT is set (+ TRACE_ID / PARENT_SPAN_ID for\n // correlation with the caller's trace). A cheap no-op when the endpoint is\n // unset — the fleet forwards the env into this MCP's process to turn it on.\n const { emitter: traceEmitter, exporter: traceExporter } = createPropagatingTraceEmitter(\n readTraceContextFromEnv(),\n )\n if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n process.stderr.write(\n `agent-runtime-mcp: exporting loop topology → ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}\\n`,\n )\n }\n\n const coderDelegate =\n wantCoder && executor\n ? createDefaultCoderDelegate({\n executor,\n fanoutHarnesses,\n maxConcurrency,\n traceEmitter,\n })\n : undefined\n\n const researcherDelegate =\n wantResearcher && executor\n ? await loadResearcherDelegate(executor.client, maxConcurrency, traceEmitter)\n : undefined\n\n const server = createMcpServer({ coderDelegate, researcherDelegate })\n\n const shutdown = () => {\n server.stop()\n void traceExporter?.shutdown().finally(() => process.exit(0))\n if (!traceExporter) process.exit(0)\n }\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n\n await server.serve()\n}\n\nasync function loadSandboxClient(apiKey: string | undefined): Promise<LoopSandboxClient> {\n // Diagnostic mode: AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 enables tools/list + the\n // queue-bound tools (status / history / feedback) without sandbox creds.\n // Coder + researcher delegations require a real client; the stub fails loud\n // at create() so the agent observes the cause instead of silent success.\n if (!apiKey) {\n return {\n async create() {\n throw new Error(\n 'agent-runtime-mcp: TANGLE_API_KEY is unset; coder/researcher delegations are disabled in diagnostic mode. Set TANGLE_API_KEY or use MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to remove the unsupported tools from the tool list.',\n )\n },\n } satisfies LoopSandboxClient\n }\n // Dynamic import keeps the bin importable in environments that haven't\n // installed `@tangle-network/sandbox` yet (the runtime package lists it\n // as a peer dep, not a hard dep).\n const mod = await import('@tangle-network/sandbox').catch((err) => {\n process.stderr.write(\n `agent-runtime-mcp: failed to load @tangle-network/sandbox (${err.message}); install the peer dependency\\n`,\n )\n process.exit(2)\n })\n const SandboxCtor = (mod as { Sandbox?: new (config: unknown) => LoopSandboxClient }).Sandbox\n if (!SandboxCtor) {\n process.stderr.write(\n 'agent-runtime-mcp: @tangle-network/sandbox does not export Sandbox; cannot construct client\\n',\n )\n process.exit(2)\n }\n const baseUrl = process.env.SANDBOX_BASE_URL\n return new SandboxCtor({\n apiKey,\n ...(baseUrl ? { baseUrl } : {}),\n })\n}\n\ninterface ResearcherProfilePreset {\n agentRunSpec: Parameters<typeof runLoop>[0]['agentRun'] extends infer T ? NonNullable<T> : never\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n}\n\ninterface ResearcherFanoutPreset {\n agentRuns: NonNullable<Parameters<typeof runLoop>[0]['agentRuns']>\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n driver: Parameters<typeof runLoop>[0]['driver']\n}\n\nasync function loadResearcherDelegate(\n sandboxClient: LoopSandboxClient,\n maxConcurrency: number,\n traceEmitter?: LoopTraceEmitter,\n): Promise<ResearcherDelegate | undefined> {\n // Optional peer — when `@tangle-network/agent-knowledge` isn't installed,\n // we silently omit the researcher tool from the advertisement. The\n // dynamic-import path is resolved at runtime; TypeScript cannot see the\n // peer, so we type the module structurally rather than via its own\n // declaration file.\n const profilesSpecifier = '@tangle-network/agent-knowledge/profiles'\n const mod = await import(profilesSpecifier).catch(() => undefined)\n if (!mod) return undefined\n type SingleFactory = (opts: { task: unknown }) => ResearcherProfilePreset\n type FanoutFactory = (opts: { task: unknown }) => ResearcherFanoutPreset\n const fanoutFactory = (mod as { multiHarnessResearcherFanout?: FanoutFactory })\n .multiHarnessResearcherFanout\n const singleFactory = (mod as { researcherProfile?: SingleFactory }).researcherProfile\n if (!fanoutFactory || !singleFactory) return undefined\n\n return async (args, ctx) => {\n const task = {\n question: args.question,\n knowledgeNamespace: args.namespace,\n scope: args.scope,\n sources: args.sources,\n recencyWindow: args.config?.recencyWindow\n ? {\n since: args.config.recencyWindow.since\n ? new Date(args.config.recencyWindow.since)\n : undefined,\n until: args.config.recencyWindow.until\n ? new Date(args.config.recencyWindow.until)\n : undefined,\n }\n : undefined,\n maxItems: args.config?.maxItems,\n minConfidence: args.config?.minConfidence,\n }\n const variants = Math.max(1, Math.trunc(args.variants ?? 1))\n ctx.report({ iteration: 0, phase: 'starting' })\n if (variants <= 1) {\n const preset = singleFactory({ task })\n const result = await runLoop({\n driver: {\n name: 'mcp-researcher-single',\n async plan(t, history) {\n return history.length === 0 ? [t] : []\n },\n decide(history) {\n return history.length > 0 ? 'pick-winner' : 'fail'\n },\n },\n agentRun: preset.agentRunSpec,\n output: preset.output,\n validator: preset.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal, ...(traceEmitter ? { traceEmitter } : {}) },\n maxIterations: 1,\n maxConcurrency,\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate produced no winner')\n ctx.report({ iteration: 1, phase: 'completed' })\n return output as ResearchOutputShape\n }\n const fanout = fanoutFactory({ task })\n const result = await runLoop({\n driver: fanout.driver,\n agentRuns: fanout.agentRuns.slice(0, variants),\n output: fanout.output,\n validator: fanout.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal, ...(traceEmitter ? { traceEmitter } : {}) },\n maxIterations: variants,\n maxConcurrency: Math.min(maxConcurrency, variants),\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate fanout produced no winner')\n ctx.report({ iteration: result.iterations.length, phase: 'completed' })\n return output as ResearchOutputShape\n }\n}\n\nfunction parseHarnesses(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const list = raw\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n return list.length > 0 ? list : undefined\n}\n\nfunction parseFleetId(raw: string | undefined): string | undefined {\n if (typeof raw !== 'string') return undefined\n const trimmed = raw.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction parseConcurrency(raw: string | undefined): number {\n if (!raw) return 4\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 1) return 4\n return Math.min(Math.trunc(n), 32)\n}\n\nmain().catch((err) => {\n process.stderr.write(`agent-runtime-mcp: ${err instanceof Error ? err.stack : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwCA,eAAe,OAAsB;AACnC,QAAM,kBAAkB,eAAe,QAAQ,IAAI,0BAA0B;AAC7E,QAAM,iBAAiB,iBAAiB,QAAQ,IAAI,4BAA4B;AAChF,QAAM,YAAY,CAAC,QAAQ,IAAI;AAC/B,QAAM,iBAAiB,CAAC,QAAQ,IAAI;AACpC,QAAM,UAAU,aAAa,QAAQ,IAAI,eAAe;AAMxD,QAAM,eAAe,aAAa;AAClC,MAAI;AACJ,MAAI;AACJ,MAAI,cAAc;AAChB,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,gCAAgC;AAC1D,cAAQ,OAAO;AAAA,QACb;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAIA,QAAI,WAAW,CAAC,QAAQ;AACtB,cAAQ,OAAO;AAAA,QACb;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,oBAAgB,MAAM,kBAAkB,MAAM;AAC9C,eAAW,MAAM,eAAe,EAAE,cAAc,CAAC;AACjD,QAAI,SAAS;AACX,cAAQ,OAAO,MAAM,sDAAsD,OAAO;AAAA,CAAI;AAAA,IACxF;AACA,YAAQ,OAAO,MAAM,kDAA6C,SAAS,SAAS,CAAC;AAAA,CAAI;AAAA,EAC3F;AAMA,QAAM,EAAE,SAAS,cAAc,UAAU,cAAc,IAAI;AAAA,IACzD,wBAAwB;AAAA,EAC1B;AACA,MAAI,QAAQ,IAAI,6BAA6B;AAC3C,YAAQ,OAAO;AAAA,MACb,qDAAgD,QAAQ,IAAI,2BAA2B;AAAA;AAAA,IACzF;AAAA,EACF;AAEA,QAAM,gBACJ,aAAa,WACT,2BAA2B;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,IACD;AAEN,QAAM,qBACJ,kBAAkB,WACd,MAAM,uBAAuB,SAAS,QAAQ,gBAAgB,YAAY,IAC1E;AAEN,QAAM,SAAS,gBAAgB,EAAE,eAAe,mBAAmB,CAAC;AAEpE,QAAM,WAAW,MAAM;AACrB,WAAO,KAAK;AACZ,SAAK,eAAe,SAAS,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAC5D,QAAI,CAAC,cAAe,SAAQ,KAAK,CAAC;AAAA,EACpC;AACA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAE9B,QAAM,OAAO,MAAM;AACrB;AAEA,eAAe,kBAAkB,QAAwD;AAKvF,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,MAAM,SAAS;AACb,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,QAAM,MAAM,MAAM,OAAO,yBAAyB,EAAE,MAAM,CAAC,QAAQ;AACjE,YAAQ,OAAO;AAAA,MACb,8DAA8D,IAAI,OAAO;AAAA;AAAA,IAC3E;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACD,QAAM,cAAe,IAAiE;AACtF,MAAI,CAAC,aAAa;AAChB,YAAQ,OAAO;AAAA,MACb;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,UAAU,QAAQ,IAAI;AAC5B,SAAO,IAAI,YAAY;AAAA,IACrB;AAAA,IACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B,CAAC;AACH;AAeA,eAAe,uBACb,eACA,gBACA,cACyC;AAMzC,QAAM,oBAAoB;AAC1B,QAAM,MAAM,MAAM,OAAO,mBAAmB,MAAM,MAAM,MAAS;AACjE,MAAI,CAAC,IAAK,QAAO;AAGjB,QAAM,gBAAiB,IACpB;AACH,QAAM,gBAAiB,IAA8C;AACrE,MAAI,CAAC,iBAAiB,CAAC,cAAe,QAAO;AAE7C,SAAO,OAAO,MAAM,QAAQ;AAC1B,UAAM,OAAO;AAAA,MACX,UAAU,KAAK;AAAA,MACf,oBAAoB,KAAK;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,eAAe,KAAK,QAAQ,gBACxB;AAAA,QACE,OAAO,KAAK,OAAO,cAAc,QAC7B,IAAI,KAAK,KAAK,OAAO,cAAc,KAAK,IACxC;AAAA,QACJ,OAAO,KAAK,OAAO,cAAc,QAC7B,IAAI,KAAK,KAAK,OAAO,cAAc,KAAK,IACxC;AAAA,MACN,IACA;AAAA,MACJ,UAAU,KAAK,QAAQ;AAAA,MACvB,eAAe,KAAK,QAAQ;AAAA,IAC9B;AACA,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,YAAY,CAAC,CAAC;AAC3D,QAAI,OAAO,EAAE,WAAW,GAAG,OAAO,WAAW,CAAC;AAC9C,QAAI,YAAY,GAAG;AACjB,YAAM,SAAS,cAAc,EAAE,KAAK,CAAC;AACrC,YAAMA,UAAS,MAAM,QAAQ;AAAA,QAC3B,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,KAAK,GAAG,SAAS;AACrB,mBAAO,QAAQ,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;AAAA,UACvC;AAAA,UACA,OAAO,SAAS;AACd,mBAAO,QAAQ,SAAS,IAAI,gBAAgB;AAAA,UAC9C;AAAA,QACF;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,KAAK,EAAE,eAAe,QAAQ,IAAI,QAAQ,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC,EAAG;AAAA,QACpF,eAAe;AAAA,QACf;AAAA,MACF,CAAC;AACD,YAAMC,UAASD,QAAO,QAAQ;AAC9B,UAAI,CAACC,QAAQ,OAAM,IAAI,MAAM,wCAAwC;AACrE,UAAI,OAAO,EAAE,WAAW,GAAG,OAAO,YAAY,CAAC;AAC/C,aAAOA;AAAA,IACT;AACA,UAAM,SAAS,cAAc,EAAE,KAAK,CAAC;AACrC,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO,UAAU,MAAM,GAAG,QAAQ;AAAA,MAC7C,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO;AAAA,MAClB;AAAA,MACA,KAAK,EAAE,eAAe,QAAQ,IAAI,QAAQ,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC,EAAG;AAAA,MACpF,eAAe;AAAA,MACf,gBAAgB,KAAK,IAAI,gBAAgB,QAAQ;AAAA,IACnD,CAAC;AACD,UAAM,SAAS,OAAO,QAAQ;AAC9B,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,+CAA+C;AAC5E,QAAI,OAAO,EAAE,WAAW,OAAO,WAAW,QAAQ,OAAO,YAAY,CAAC;AACtE,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,KAA+C;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,OAAO,IACV,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACjB,SAAO,KAAK,SAAS,IAAI,OAAO;AAClC;AAEA,SAAS,aAAa,KAA6C;AACjE,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,UAAU,IAAI,KAAK;AACzB,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,iBAAiB,KAAiC;AACzD,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,OAAO,GAAG;AACpB,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,QAAO;AACzC,SAAO,KAAK,IAAI,KAAK,MAAM,CAAC,GAAG,EAAE;AACnC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,OAAO,MAAM,sBAAsB,eAAe,QAAQ,IAAI,QAAQ,OAAO,GAAG,CAAC;AAAA,CAAI;AAC7F,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["result","output"]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @experimental\n *\n * `agent-runtime-mcp` — stdio MCP server entry point.\n *\n * Spins up a server with the default coder delegate (wired against the\n * real `@tangle-network/sandbox` client) and, when the optional\n * `@tangle-network/agent-knowledge` peer is installed, a researcher\n * delegate against `multiHarnessResearcherFanout`.\n *\n * Environment variables:\n * TANGLE_API_KEY required — passed to `new Sandbox({ apiKey })`\n * SANDBOX_BASE_URL optional — sandbox-SDK base URL override\n * TANGLE_FLEET_ID optional — when set, delegations dispatch\n * INTO this fleet's shared workspace instead\n * of creating sibling sandboxes. Set by the\n * parent sandbox when launching this MCP\n * server so worker diffs land on the caller's\n * filesystem with no cross-sandbox boundary.\n * TANGLE_FLEET_EXCLUDE_MACHINES optional — comma-separated machine ids to\n * skip during fleet-mode round-robin\n * (typically the coordinator machine this\n * MCP server is running on).\n * MCP_MAX_CONCURRENT_SANDBOXES default 4 — kernel maxConcurrency cap\n * MCP_CODER_FANOUT_HARNESSES comma-separated harness ids to use for variants > 1\n * MCP_DISABLE_CODER set to `1` to omit `delegate_code`\n * MCP_DISABLE_RESEARCHER set to `1` to omit `delegate_research` even when peer is present\n */\n\nimport type { LoopTraceEmitter, SandboxClient } from '../runtime'\nimport { runLoop } from '../runtime'\nimport { detectExecutor } from './bin-helpers'\nimport { createDefaultCoderDelegate, type ResearcherDelegate } from './delegates'\nimport type { DelegationExecutor } from './executor'\nimport { createMcpServer } from './server'\nimport { createPropagatingTraceEmitter, readTraceContextFromEnv } from './trace-propagation'\nimport type { ResearchOutputShape } from './types'\n\nasync function main(): Promise<void> {\n const fanoutHarnesses = parseHarnesses(process.env.MCP_CODER_FANOUT_HARNESSES)\n const maxConcurrency = parseConcurrency(process.env.MCP_MAX_CONCURRENT_SANDBOXES)\n const wantCoder = !process.env.MCP_DISABLE_CODER\n const wantResearcher = !process.env.MCP_DISABLE_RESEARCHER\n const fleetId = parseFleetId(process.env.TANGLE_FLEET_ID)\n\n // Skip the sandbox client load entirely when no profile delegate needs it —\n // the feedback + status + history tools are queue-bound and require no\n // sandbox. Useful for tooling that mounts the MCP server purely for\n // self-introspection.\n const needsSandbox = wantCoder || wantResearcher\n let sandboxClient: SandboxClient | undefined\n let executor: DelegationExecutor | undefined\n if (needsSandbox) {\n const apiKey = process.env.TANGLE_API_KEY\n if (!apiKey && !process.env.AGENT_RUNTIME_MCP_ALLOW_NO_KEY) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_API_KEY is required. Set AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 to run without it for diagnostics, or MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to run the queue-only subset.\\n',\n )\n process.exit(2)\n }\n // Fleet mode against a diagnostic stub is meaningless — the stub can't\n // resolve a real fleet handle. Refuse rather than silently degrading,\n // otherwise a fleet-mounted MCP would behave differently than configured.\n if (fleetId && !apiKey) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_FLEET_ID was set but TANGLE_API_KEY is missing; cannot resolve fleet handle. Provide an api key or unset TANGLE_FLEET_ID.\\n',\n )\n process.exit(2)\n }\n sandboxClient = await loadSandboxClient(apiKey)\n executor = await detectExecutor({ sandboxClient })\n if (fleetId) {\n process.stderr.write(`agent-runtime-mcp: fleet-aware delegation: fleetId=${fleetId}\\n`)\n }\n process.stderr.write(`agent-runtime-mcp: delegation placement → ${executor.describe()}\\n`)\n }\n\n // Export delegated-loop topology spans to the OTLP / Tangle Intelligence sink\n // when OTEL_EXPORTER_OTLP_ENDPOINT is set (+ TRACE_ID / PARENT_SPAN_ID for\n // correlation with the caller's trace). A cheap no-op when the endpoint is\n // unset — the fleet forwards the env into this MCP's process to turn it on.\n const { emitter: traceEmitter, exporter: traceExporter } = createPropagatingTraceEmitter(\n readTraceContextFromEnv(),\n )\n if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n process.stderr.write(\n `agent-runtime-mcp: exporting loop topology → ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}\\n`,\n )\n }\n\n const coderDelegate =\n wantCoder && executor\n ? createDefaultCoderDelegate({\n executor,\n fanoutHarnesses,\n maxConcurrency,\n traceEmitter,\n })\n : undefined\n\n const researcherDelegate =\n wantResearcher && executor\n ? await loadResearcherDelegate(executor.client, maxConcurrency, traceEmitter)\n : undefined\n\n const server = createMcpServer({ coderDelegate, researcherDelegate })\n\n const shutdown = () => {\n server.stop()\n void traceExporter?.shutdown().finally(() => process.exit(0))\n if (!traceExporter) process.exit(0)\n }\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n\n await server.serve()\n}\n\nasync function loadSandboxClient(apiKey: string | undefined): Promise<SandboxClient> {\n // Diagnostic mode: AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 enables tools/list + the\n // queue-bound tools (status / history / feedback) without sandbox creds.\n // Coder + researcher delegations require a real client; the stub fails loud\n // at create() so the agent observes the cause instead of silent success.\n if (!apiKey) {\n return {\n async create() {\n throw new Error(\n 'agent-runtime-mcp: TANGLE_API_KEY is unset; coder/researcher delegations are disabled in diagnostic mode. Set TANGLE_API_KEY or use MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to remove the unsupported tools from the tool list.',\n )\n },\n } satisfies SandboxClient\n }\n // Dynamic import keeps the bin importable in environments that haven't\n // installed `@tangle-network/sandbox` yet (the runtime package lists it\n // as a peer dep, not a hard dep).\n const mod = await import('@tangle-network/sandbox').catch((err) => {\n process.stderr.write(\n `agent-runtime-mcp: failed to load @tangle-network/sandbox (${err.message}); install the peer dependency\\n`,\n )\n process.exit(2)\n })\n const SandboxCtor = (mod as { Sandbox?: new (config: unknown) => SandboxClient }).Sandbox\n if (!SandboxCtor) {\n process.stderr.write(\n 'agent-runtime-mcp: @tangle-network/sandbox does not export Sandbox; cannot construct client\\n',\n )\n process.exit(2)\n }\n const baseUrl = process.env.SANDBOX_BASE_URL\n return new SandboxCtor({\n apiKey,\n ...(baseUrl ? { baseUrl } : {}),\n })\n}\n\ninterface ResearcherProfilePreset {\n agentRunSpec: Parameters<typeof runLoop>[0]['agentRun'] extends infer T ? NonNullable<T> : never\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n}\n\ninterface ResearcherFanoutPreset {\n agentRuns: NonNullable<Parameters<typeof runLoop>[0]['agentRuns']>\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n driver: Parameters<typeof runLoop>[0]['driver']\n}\n\nasync function loadResearcherDelegate(\n sandboxClient: SandboxClient,\n maxConcurrency: number,\n traceEmitter?: LoopTraceEmitter,\n): Promise<ResearcherDelegate | undefined> {\n // Optional peer — when `@tangle-network/agent-knowledge` isn't installed,\n // we silently omit the researcher tool from the advertisement. The\n // dynamic-import path is resolved at runtime; TypeScript cannot see the\n // peer, so we type the module structurally rather than via its own\n // declaration file.\n const profilesSpecifier = '@tangle-network/agent-knowledge/profiles'\n const mod = await import(profilesSpecifier).catch(() => undefined)\n if (!mod) return undefined\n type SingleFactory = (opts: { task: unknown }) => ResearcherProfilePreset\n type FanoutFactory = (opts: { task: unknown }) => ResearcherFanoutPreset\n const fanoutFactory = (mod as { multiHarnessResearcherFanout?: FanoutFactory })\n .multiHarnessResearcherFanout\n const singleFactory = (mod as { researcherProfile?: SingleFactory }).researcherProfile\n if (!fanoutFactory || !singleFactory) return undefined\n\n return async (args, ctx) => {\n const task = {\n question: args.question,\n knowledgeNamespace: args.namespace,\n scope: args.scope,\n sources: args.sources,\n recencyWindow: args.config?.recencyWindow\n ? {\n since: args.config.recencyWindow.since\n ? new Date(args.config.recencyWindow.since)\n : undefined,\n until: args.config.recencyWindow.until\n ? new Date(args.config.recencyWindow.until)\n : undefined,\n }\n : undefined,\n maxItems: args.config?.maxItems,\n minConfidence: args.config?.minConfidence,\n }\n const variants = Math.max(1, Math.trunc(args.variants ?? 1))\n ctx.report({ iteration: 0, phase: 'starting' })\n if (variants <= 1) {\n const preset = singleFactory({ task })\n const result = await runLoop({\n driver: {\n name: 'mcp-researcher-single',\n async plan(t, history) {\n return history.length === 0 ? [t] : []\n },\n decide(history) {\n return history.length > 0 ? 'pick-winner' : 'fail'\n },\n },\n agentRun: preset.agentRunSpec,\n output: preset.output,\n validator: preset.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal, ...(traceEmitter ? { traceEmitter } : {}) },\n maxIterations: 1,\n maxConcurrency,\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate produced no winner')\n ctx.report({ iteration: 1, phase: 'completed' })\n return output as ResearchOutputShape\n }\n const fanout = fanoutFactory({ task })\n const result = await runLoop({\n driver: fanout.driver,\n agentRuns: fanout.agentRuns.slice(0, variants),\n output: fanout.output,\n validator: fanout.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal, ...(traceEmitter ? { traceEmitter } : {}) },\n maxIterations: variants,\n maxConcurrency: Math.min(maxConcurrency, variants),\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate fanout produced no winner')\n ctx.report({ iteration: result.iterations.length, phase: 'completed' })\n return output as ResearchOutputShape\n }\n}\n\nfunction parseHarnesses(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const list = raw\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n return list.length > 0 ? list : undefined\n}\n\nfunction parseFleetId(raw: string | undefined): string | undefined {\n if (typeof raw !== 'string') return undefined\n const trimmed = raw.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction parseConcurrency(raw: string | undefined): number {\n if (!raw) return 4\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 1) return 4\n return Math.min(Math.trunc(n), 32)\n}\n\nmain().catch((err) => {\n process.stderr.write(`agent-runtime-mcp: ${err instanceof Error ? err.stack : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":"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","names":["result","output"]}
|