@tangle-network/agent-runtime 0.19.0 → 0.20.1
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 +110 -0
- package/dist/agent.d.ts +1 -1
- package/dist/chunk-LPPM7EGS.js +1141 -0
- package/dist/chunk-LPPM7EGS.js.map +1 -0
- package/dist/chunk-VFUEE6DF.js +373 -0
- package/dist/chunk-VFUEE6DF.js.map +1 -0
- package/dist/chunk-Z5LKAYAS.js +248 -0
- package/dist/chunk-Z5LKAYAS.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/loops.d.ts +4 -4
- package/dist/loops.js +6 -366
- package/dist/loops.js.map +1 -1
- package/dist/mcp/bin.d.ts +1 -0
- package/dist/mcp/bin.js +159 -0
- package/dist/mcp/bin.js.map +1 -0
- package/dist/mcp/index.d.ts +827 -0
- package/dist/mcp/index.js +74 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/profiles.d.ts +3 -3
- package/dist/profiles.js +5 -240
- package/dist/profiles.js.map +1 -1
- package/dist/{runtime-run-4pbY3Jq5.d.ts → runtime-run-B2j-hvBj.d.ts} +1 -1
- package/dist/{types-EKcAHfxI.d.ts → types-Bx-tArkc.d.ts} +1 -1
- package/dist/{types-DlyPgeI0.d.ts → types-DvJIha6w.d.ts} +1 -1
- package/package.json +15 -1
|
@@ -0,0 +1,827 @@
|
|
|
1
|
+
import { CoderOutput } from '../profiles.js';
|
|
2
|
+
import { g as LoopSandboxClient } from '../types-Bx-tArkc.js';
|
|
3
|
+
import '@tangle-network/sandbox';
|
|
4
|
+
import '../runtime-run-B2j-hvBj.js';
|
|
5
|
+
import '../types-DvJIha6w.js';
|
|
6
|
+
import '@tangle-network/agent-eval';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @experimental
|
|
10
|
+
*
|
|
11
|
+
* MCP delegation tool surface — the typed inputs/outputs the product agent
|
|
12
|
+
* sees over the wire. These types are the contract; the JSON schemas under
|
|
13
|
+
* `tools/*` mirror them for the MCP `tools/list` advertisement.
|
|
14
|
+
*
|
|
15
|
+
* Async semantics: `delegate_code` + `delegate_research` return a `taskId`
|
|
16
|
+
* immediately. The product agent polls `delegation_status` until the task
|
|
17
|
+
* transitions to `completed` | `failed` | `cancelled`. `delegate_feedback`
|
|
18
|
+
* + `delegation_history` are synchronous reads / writes against the local
|
|
19
|
+
* task queue + feedback store.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** @experimental */
|
|
23
|
+
type DelegationProfile = 'coder' | 'researcher';
|
|
24
|
+
/** @experimental */
|
|
25
|
+
type DelegationStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
26
|
+
/**
|
|
27
|
+
* Minimal `CoderTask` overrides exposed over the MCP wire. The full
|
|
28
|
+
* `CoderTask` carries fields the kernel synthesizes from `goal` +
|
|
29
|
+
* `repoRoot` — the agent only edits the few that materially gate
|
|
30
|
+
* validator behavior.
|
|
31
|
+
*
|
|
32
|
+
* @experimental
|
|
33
|
+
*/
|
|
34
|
+
interface DelegateCodeConfig {
|
|
35
|
+
testCmd?: string;
|
|
36
|
+
typecheckCmd?: string;
|
|
37
|
+
forbiddenPaths?: string[];
|
|
38
|
+
maxDiffLines?: number;
|
|
39
|
+
}
|
|
40
|
+
/** @experimental */
|
|
41
|
+
interface DelegateCodeArgs {
|
|
42
|
+
/** Natural-language description of what the coder must accomplish. */
|
|
43
|
+
goal: string;
|
|
44
|
+
/** Absolute path inside the sandbox where the repo lives. */
|
|
45
|
+
repoRoot: string;
|
|
46
|
+
/** Optional free-form context the agent surfaces in the prompt prelude. */
|
|
47
|
+
contextHint?: string;
|
|
48
|
+
/**
|
|
49
|
+
* When > 1, dispatches `multiHarnessCoderFanout` across N harnesses
|
|
50
|
+
* (claude-code, codex, opencode-glm) and picks the highest-scoring
|
|
51
|
+
* passing patch. Default 1.
|
|
52
|
+
*/
|
|
53
|
+
variants?: number;
|
|
54
|
+
/** Validator + prompt overrides the agent knows for this repo. */
|
|
55
|
+
config?: DelegateCodeConfig;
|
|
56
|
+
/** Multi-tenant scope (customer-id, workspace-id). */
|
|
57
|
+
namespace?: string;
|
|
58
|
+
}
|
|
59
|
+
/** @experimental */
|
|
60
|
+
interface DelegateCodeResult {
|
|
61
|
+
taskId: string;
|
|
62
|
+
/** Best-effort hint — coder loops can take minutes-to-hours. */
|
|
63
|
+
estimatedDurationMs?: number;
|
|
64
|
+
}
|
|
65
|
+
/** @experimental */
|
|
66
|
+
type ResearchSource = 'web' | 'corpus' | 'twitter' | 'github' | 'docs';
|
|
67
|
+
/** @experimental */
|
|
68
|
+
interface DelegateResearchConfig {
|
|
69
|
+
recencyWindow?: {
|
|
70
|
+
since?: string;
|
|
71
|
+
until?: string;
|
|
72
|
+
};
|
|
73
|
+
maxItems?: number;
|
|
74
|
+
minConfidence?: number;
|
|
75
|
+
}
|
|
76
|
+
/** @experimental */
|
|
77
|
+
interface DelegateResearchArgs {
|
|
78
|
+
question: string;
|
|
79
|
+
namespace: string;
|
|
80
|
+
scope?: string;
|
|
81
|
+
sources?: ResearchSource[];
|
|
82
|
+
variants?: number;
|
|
83
|
+
config?: DelegateResearchConfig;
|
|
84
|
+
}
|
|
85
|
+
/** @experimental */
|
|
86
|
+
interface DelegateResearchResult {
|
|
87
|
+
taskId: string;
|
|
88
|
+
estimatedDurationMs?: number;
|
|
89
|
+
}
|
|
90
|
+
/** @experimental */
|
|
91
|
+
interface FeedbackRefersTo {
|
|
92
|
+
kind: 'delegation' | 'artifact' | 'outcome';
|
|
93
|
+
/** For `'delegation'`, this is the taskId. */
|
|
94
|
+
ref: string;
|
|
95
|
+
}
|
|
96
|
+
/** @experimental */
|
|
97
|
+
interface FeedbackRating {
|
|
98
|
+
/** [0, 1]. */
|
|
99
|
+
score: number;
|
|
100
|
+
label?: 'good' | 'bad' | 'neutral' | 'mixed';
|
|
101
|
+
notes: string;
|
|
102
|
+
}
|
|
103
|
+
/** @experimental */
|
|
104
|
+
interface DelegateFeedbackArgs {
|
|
105
|
+
refersTo: FeedbackRefersTo;
|
|
106
|
+
rating: FeedbackRating;
|
|
107
|
+
by: 'agent' | 'user' | 'downstream-judge';
|
|
108
|
+
/** ISO timestamp; defaults to server clock when omitted. */
|
|
109
|
+
capturedAt?: string;
|
|
110
|
+
namespace?: string;
|
|
111
|
+
}
|
|
112
|
+
/** @experimental */
|
|
113
|
+
interface DelegateFeedbackResult {
|
|
114
|
+
recorded: true;
|
|
115
|
+
id: string;
|
|
116
|
+
}
|
|
117
|
+
/** @experimental */
|
|
118
|
+
interface DelegationStatusArgs {
|
|
119
|
+
taskId: string;
|
|
120
|
+
}
|
|
121
|
+
/** @experimental */
|
|
122
|
+
interface DelegationProgress {
|
|
123
|
+
iteration: number;
|
|
124
|
+
phase: string;
|
|
125
|
+
}
|
|
126
|
+
/** @experimental */
|
|
127
|
+
interface DelegationError {
|
|
128
|
+
message: string;
|
|
129
|
+
kind: string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Polymorphic `result` field: `CoderOutput` when the underlying profile
|
|
133
|
+
* is `'coder'`, a structurally-typed research output when `'researcher'`.
|
|
134
|
+
* The MCP wire carries it as JSON either way.
|
|
135
|
+
*
|
|
136
|
+
* @experimental
|
|
137
|
+
*/
|
|
138
|
+
type DelegationResultPayload = {
|
|
139
|
+
profile: 'coder';
|
|
140
|
+
output: CoderOutput;
|
|
141
|
+
} | {
|
|
142
|
+
profile: 'researcher';
|
|
143
|
+
output: ResearchOutputShape;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Loose shape of a research output over the wire — the substrate cannot
|
|
147
|
+
* import the `ResearchOutput` type from agent-knowledge without inducing
|
|
148
|
+
* a dependency cycle, so the MCP layer treats it structurally.
|
|
149
|
+
*
|
|
150
|
+
* @experimental
|
|
151
|
+
*/
|
|
152
|
+
interface ResearchOutputShape {
|
|
153
|
+
items: unknown[];
|
|
154
|
+
citations: unknown[];
|
|
155
|
+
proposedWrites: unknown[];
|
|
156
|
+
gaps?: string[];
|
|
157
|
+
notes?: string;
|
|
158
|
+
[key: string]: unknown;
|
|
159
|
+
}
|
|
160
|
+
/** @experimental */
|
|
161
|
+
interface DelegationStatusResult {
|
|
162
|
+
taskId: string;
|
|
163
|
+
profile: DelegationProfile;
|
|
164
|
+
status: DelegationStatus;
|
|
165
|
+
progress?: DelegationProgress;
|
|
166
|
+
result?: DelegationResultPayload;
|
|
167
|
+
error?: DelegationError;
|
|
168
|
+
costUsd?: number;
|
|
169
|
+
startedAt: string;
|
|
170
|
+
completedAt?: string;
|
|
171
|
+
}
|
|
172
|
+
/** @experimental */
|
|
173
|
+
interface DelegationHistoryArgs {
|
|
174
|
+
namespace?: string;
|
|
175
|
+
profile?: DelegationProfile;
|
|
176
|
+
/** ISO date — only delegations started at-or-after `since` are returned. */
|
|
177
|
+
since?: string;
|
|
178
|
+
/** Default 50. Hard cap 500. */
|
|
179
|
+
limit?: number;
|
|
180
|
+
}
|
|
181
|
+
/** @experimental */
|
|
182
|
+
interface DelegationFeedbackSnapshot {
|
|
183
|
+
id: string;
|
|
184
|
+
score: number;
|
|
185
|
+
label?: FeedbackRating['label'];
|
|
186
|
+
by: DelegateFeedbackArgs['by'];
|
|
187
|
+
notes: string;
|
|
188
|
+
capturedAt: string;
|
|
189
|
+
}
|
|
190
|
+
/** @experimental */
|
|
191
|
+
interface DelegationHistoryEntry {
|
|
192
|
+
taskId: string;
|
|
193
|
+
profile: DelegationProfile;
|
|
194
|
+
namespace?: string;
|
|
195
|
+
args: DelegateCodeArgs | DelegateResearchArgs;
|
|
196
|
+
status: DelegationStatus;
|
|
197
|
+
feedback?: DelegationFeedbackSnapshot[];
|
|
198
|
+
costUsd?: number;
|
|
199
|
+
startedAt: string;
|
|
200
|
+
completedAt?: string;
|
|
201
|
+
}
|
|
202
|
+
/** @experimental */
|
|
203
|
+
interface DelegationHistoryResult {
|
|
204
|
+
delegations: DelegationHistoryEntry[];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** @experimental */
|
|
208
|
+
interface DelegateRunCtx {
|
|
209
|
+
signal: AbortSignal;
|
|
210
|
+
report(progress: DelegationProgress): void;
|
|
211
|
+
}
|
|
212
|
+
/** @experimental */
|
|
213
|
+
type CoderDelegate = (args: DelegateCodeArgs, ctx: DelegateRunCtx) => Promise<CoderOutput>;
|
|
214
|
+
/** @experimental */
|
|
215
|
+
type ResearcherDelegate = (args: DelegateResearchArgs, ctx: DelegateRunCtx) => Promise<ResearchOutputShape>;
|
|
216
|
+
/** @experimental */
|
|
217
|
+
interface CreateDefaultCoderDelegateOptions {
|
|
218
|
+
sandboxClient: LoopSandboxClient;
|
|
219
|
+
/** Default `['claude-code', 'codex', 'opencode/zai-coding-plan/glm-5.1']` when variants > 1. */
|
|
220
|
+
fanoutHarnesses?: string[];
|
|
221
|
+
/** Hard cap on the kernel's per-batch concurrency. Default 4. */
|
|
222
|
+
maxConcurrency?: number;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Build a coder delegate that drives `runLoop` against the project's
|
|
226
|
+
* sandbox client + coder profile. When `args.variants > 1` it switches
|
|
227
|
+
* to the multi-harness fanout topology.
|
|
228
|
+
*
|
|
229
|
+
* @experimental
|
|
230
|
+
*/
|
|
231
|
+
declare function createDefaultCoderDelegate(options: CreateDefaultCoderDelegateOptions): CoderDelegate;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @experimental
|
|
235
|
+
*
|
|
236
|
+
* Feedback persistence surface for the MCP layer.
|
|
237
|
+
*
|
|
238
|
+
* The substrate cannot import `@tangle-network/agent-knowledge` (it would
|
|
239
|
+
* induce a dependency cycle), so the store is an abstract interface. The
|
|
240
|
+
* default implementation is in-memory; consumers wire their own adapter
|
|
241
|
+
* (a real KbStore-backed sink, an HTTP relay to gtm-agent's knowledge
|
|
242
|
+
* service, etc.) via `createMcpServer({ feedbackStore })`.
|
|
243
|
+
*
|
|
244
|
+
* Feedback events are append-only: every rating is a new event with a
|
|
245
|
+
* fresh id, even when the same delegation is rated multiple times. The
|
|
246
|
+
* caller decides how to roll up scores downstream.
|
|
247
|
+
*/
|
|
248
|
+
|
|
249
|
+
/** @experimental */
|
|
250
|
+
interface FeedbackEvent {
|
|
251
|
+
id: string;
|
|
252
|
+
refersTo: DelegateFeedbackArgs['refersTo'];
|
|
253
|
+
rating: DelegateFeedbackArgs['rating'];
|
|
254
|
+
by: DelegateFeedbackArgs['by'];
|
|
255
|
+
capturedAt: string;
|
|
256
|
+
namespace?: string;
|
|
257
|
+
}
|
|
258
|
+
/** @experimental */
|
|
259
|
+
interface FeedbackStore {
|
|
260
|
+
/** Append a new event. Never dedupes — every rating is its own event. */
|
|
261
|
+
put(event: FeedbackEvent): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* List events filtered by `namespace`. When `namespace` is omitted, list
|
|
264
|
+
* across all namespaces. Returns events in insertion order.
|
|
265
|
+
*/
|
|
266
|
+
list(filter?: {
|
|
267
|
+
namespace?: string;
|
|
268
|
+
refersToRef?: string;
|
|
269
|
+
}): Promise<FeedbackEvent[]>;
|
|
270
|
+
}
|
|
271
|
+
/** @experimental */
|
|
272
|
+
declare class InMemoryFeedbackStore implements FeedbackStore {
|
|
273
|
+
private readonly events;
|
|
274
|
+
put(event: FeedbackEvent): Promise<void>;
|
|
275
|
+
list(filter?: {
|
|
276
|
+
namespace?: string;
|
|
277
|
+
refersToRef?: string;
|
|
278
|
+
}): Promise<FeedbackEvent[]>;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Project a `FeedbackEvent` down to the snapshot shape carried on
|
|
282
|
+
* `delegation_history` entries.
|
|
283
|
+
*
|
|
284
|
+
* @experimental
|
|
285
|
+
*/
|
|
286
|
+
declare function eventToSnapshot(event: FeedbackEvent): DelegationFeedbackSnapshot;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @experimental
|
|
290
|
+
*
|
|
291
|
+
* In-memory state for async MCP delegations. State machine:
|
|
292
|
+
*
|
|
293
|
+
* pending → running → completed | failed
|
|
294
|
+
* ↘ cancelled (from any non-terminal state via cancel())
|
|
295
|
+
*
|
|
296
|
+
* Each `submit` returns a `taskId` immediately and kicks the work off in the
|
|
297
|
+
* background. The work function receives an `AbortSignal` the queue fires
|
|
298
|
+
* when `cancel(taskId)` is called. The queue does NOT supervise runtime
|
|
299
|
+
* timeouts — the underlying `runLoop` driver / sandbox imposes those.
|
|
300
|
+
*
|
|
301
|
+
* Idempotency: callers may supply an `idempotencyKey` (hash of the input).
|
|
302
|
+
* A duplicate `submit` with a known key returns the existing task instead of
|
|
303
|
+
* starting a new one. Mutated input → different key → different task.
|
|
304
|
+
*
|
|
305
|
+
* Persistent state (sqlite) is a Phase 2 follow-up. The README documents the
|
|
306
|
+
* in-memory limitation explicitly so consumers know a worker restart drops
|
|
307
|
+
* pending delegations.
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
/** @experimental */
|
|
311
|
+
interface DelegationRecord {
|
|
312
|
+
taskId: string;
|
|
313
|
+
profile: DelegationProfile;
|
|
314
|
+
namespace?: string;
|
|
315
|
+
args: DelegateCodeArgs | DelegateResearchArgs;
|
|
316
|
+
status: DelegationStatus;
|
|
317
|
+
progress?: DelegationProgress;
|
|
318
|
+
result?: DelegationResultPayload;
|
|
319
|
+
error?: DelegationError;
|
|
320
|
+
costUsd?: number;
|
|
321
|
+
startedAt: string;
|
|
322
|
+
completedAt?: string;
|
|
323
|
+
/** Sha-prefix hash of the canonical input — used for idempotency lookup. */
|
|
324
|
+
idempotencyKey?: string;
|
|
325
|
+
/** Feedback events keyed by this delegation's taskId. */
|
|
326
|
+
feedback: DelegationFeedbackSnapshot[];
|
|
327
|
+
}
|
|
328
|
+
/** @experimental */
|
|
329
|
+
interface SubmitInput<Args extends DelegateCodeArgs | DelegateResearchArgs> {
|
|
330
|
+
profile: DelegationProfile;
|
|
331
|
+
args: Args;
|
|
332
|
+
namespace?: string;
|
|
333
|
+
idempotencyKey?: string;
|
|
334
|
+
/**
|
|
335
|
+
* Runs the underlying delegation. The queue passes a fresh `AbortSignal`
|
|
336
|
+
* and a `report` channel for incremental progress updates. The function
|
|
337
|
+
* MUST resolve with the typed `DelegationResultPayload['output']`; the
|
|
338
|
+
* queue wraps it with the profile tag.
|
|
339
|
+
*/
|
|
340
|
+
run: (ctx: {
|
|
341
|
+
signal: AbortSignal;
|
|
342
|
+
report(progress: DelegationProgress): void;
|
|
343
|
+
}) => Promise<DelegationResultPayload['output']>;
|
|
344
|
+
}
|
|
345
|
+
/** @experimental */
|
|
346
|
+
interface SubmitOutput {
|
|
347
|
+
taskId: string;
|
|
348
|
+
/** True when a prior matching `idempotencyKey` returned an existing record. */
|
|
349
|
+
reused: boolean;
|
|
350
|
+
}
|
|
351
|
+
/** @experimental */
|
|
352
|
+
interface DelegationTaskQueueOptions {
|
|
353
|
+
/** ID generator override; default `randomTaskId`. */
|
|
354
|
+
generateId?: () => string;
|
|
355
|
+
/** Clock override; default `() => new Date().toISOString()`. */
|
|
356
|
+
now?: () => string;
|
|
357
|
+
}
|
|
358
|
+
/** @experimental */
|
|
359
|
+
declare class DelegationTaskQueue {
|
|
360
|
+
private readonly records;
|
|
361
|
+
private readonly controllers;
|
|
362
|
+
private readonly byIdempotencyKey;
|
|
363
|
+
private readonly generateId;
|
|
364
|
+
private readonly now;
|
|
365
|
+
constructor(options?: DelegationTaskQueueOptions);
|
|
366
|
+
/**
|
|
367
|
+
* Kick off a delegation in the background. Returns immediately. The
|
|
368
|
+
* `taskId` is queryable via `status` once this method returns.
|
|
369
|
+
*/
|
|
370
|
+
submit<Args extends DelegateCodeArgs | DelegateResearchArgs>(input: SubmitInput<Args>): SubmitOutput;
|
|
371
|
+
/**
|
|
372
|
+
* Snapshot the current state of a delegation. Returns `undefined` for
|
|
373
|
+
* unknown ids so callers can distinguish missing from terminal.
|
|
374
|
+
*/
|
|
375
|
+
status(taskId: string): DelegationStatusResult | undefined;
|
|
376
|
+
/**
|
|
377
|
+
* Abort an in-flight delegation. Returns `false` if the task is unknown
|
|
378
|
+
* or already terminal. The underlying `run` function MUST honor the
|
|
379
|
+
* abort signal for the cancel to take effect; the queue marks the
|
|
380
|
+
* record `cancelled` regardless so a misbehaving runner cannot pin the
|
|
381
|
+
* UI on `running` forever.
|
|
382
|
+
*/
|
|
383
|
+
cancel(taskId: string): boolean;
|
|
384
|
+
/**
|
|
385
|
+
* Append a feedback event to the matching delegation. Returns `false`
|
|
386
|
+
* when `ref` does not name a known taskId — the caller should still
|
|
387
|
+
* record the feedback through a different surface (artifact/outcome
|
|
388
|
+
* kinds are not queue-bound).
|
|
389
|
+
*/
|
|
390
|
+
attachFeedback(taskId: string, snapshot: DelegationFeedbackSnapshot): boolean;
|
|
391
|
+
/**
|
|
392
|
+
* Query the recorded delegations. Returns entries newest-first (by
|
|
393
|
+
* `startedAt`), truncated to `limit`.
|
|
394
|
+
*/
|
|
395
|
+
history(args?: DelegationHistoryArgs): DelegationHistoryEntry[];
|
|
396
|
+
/** Test-only — number of in-flight (non-terminal) records. */
|
|
397
|
+
inflightCount(): number;
|
|
398
|
+
private execute;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Best-effort stable hash for use as `idempotencyKey`. Not cryptographic;
|
|
402
|
+
* collisions only affect dedupe, never correctness.
|
|
403
|
+
*
|
|
404
|
+
* @experimental
|
|
405
|
+
*/
|
|
406
|
+
declare function hashIdempotencyInput(value: unknown): string;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @experimental
|
|
410
|
+
*
|
|
411
|
+
* Stdio JSON-RPC MCP server exposing the 5 delegation tools to sandbox
|
|
412
|
+
* coding-harness agents (claude-code, codex, opencode, ...).
|
|
413
|
+
*
|
|
414
|
+
* The server is transport-bound but topology-free: tool execution is
|
|
415
|
+
* delegated to handler functions composed from a queue, a feedback
|
|
416
|
+
* store, and per-profile run delegates. Consumers wire those at
|
|
417
|
+
* construction time. The `agent-runtime-mcp` bin spins up a default
|
|
418
|
+
* configuration for the common case (real sandbox client + coder).
|
|
419
|
+
*
|
|
420
|
+
* Wire protocol: line-delimited JSON-RPC 2.0 over stdio. Each line is
|
|
421
|
+
* one request; each response is one line. `tools/list` and `tools/call`
|
|
422
|
+
* mirror the MCP 2024-11-05 spec; we do not pull in
|
|
423
|
+
* `@modelcontextprotocol/sdk` to keep the dependency footprint zero.
|
|
424
|
+
*/
|
|
425
|
+
|
|
426
|
+
/** @experimental */
|
|
427
|
+
interface McpServerOptions {
|
|
428
|
+
/** Required to enable delegate_code. */
|
|
429
|
+
coderDelegate?: CoderDelegate;
|
|
430
|
+
/**
|
|
431
|
+
* Required to enable delegate_research. The substrate cannot ship a
|
|
432
|
+
* default — wire one that closes over your `runLoop` + a
|
|
433
|
+
* researcher profile (typically `@tangle-network/agent-knowledge`'s
|
|
434
|
+
* `researcherProfile` / `multiHarnessResearcherFanout`).
|
|
435
|
+
*/
|
|
436
|
+
researcherDelegate?: ResearcherDelegate;
|
|
437
|
+
/** Override the default in-memory feedback store. */
|
|
438
|
+
feedbackStore?: FeedbackStore;
|
|
439
|
+
/** Override the default in-memory task queue. */
|
|
440
|
+
queue?: DelegationTaskQueue;
|
|
441
|
+
/** Server display name surfaced via `initialize`. Default `'agent-runtime-mcp'`. */
|
|
442
|
+
serverName?: string;
|
|
443
|
+
/** Server version surfaced via `initialize`. Default = the package version baked at build time. */
|
|
444
|
+
serverVersion?: string;
|
|
445
|
+
}
|
|
446
|
+
/** @experimental */
|
|
447
|
+
interface McpToolDescriptor {
|
|
448
|
+
name: string;
|
|
449
|
+
description: string;
|
|
450
|
+
inputSchema: Record<string, unknown>;
|
|
451
|
+
handler: (raw: unknown) => Promise<unknown>;
|
|
452
|
+
}
|
|
453
|
+
/** @experimental */
|
|
454
|
+
interface McpServer {
|
|
455
|
+
/** Tools currently registered (depend on which delegates were wired). */
|
|
456
|
+
readonly tools: ReadonlyMap<string, McpToolDescriptor>;
|
|
457
|
+
/** The underlying queue — exposed so tests can introspect it. */
|
|
458
|
+
readonly queue: DelegationTaskQueue;
|
|
459
|
+
/** The feedback store — exposed for the same reason. */
|
|
460
|
+
readonly feedbackStore: FeedbackStore;
|
|
461
|
+
/** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */
|
|
462
|
+
handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>;
|
|
463
|
+
/** Drive the server on a stdio-shaped transport until `stop()` is called. */
|
|
464
|
+
serve(transport?: McpTransport): Promise<void>;
|
|
465
|
+
/** Stop a `serve` call. Subsequent requests are rejected. */
|
|
466
|
+
stop(): void;
|
|
467
|
+
}
|
|
468
|
+
/** @experimental */
|
|
469
|
+
interface McpTransport {
|
|
470
|
+
input: NodeJS.ReadableStream;
|
|
471
|
+
output: NodeJS.WritableStream;
|
|
472
|
+
}
|
|
473
|
+
/** @experimental */
|
|
474
|
+
interface JsonRpcMessage {
|
|
475
|
+
jsonrpc: '2.0';
|
|
476
|
+
id?: number | string | null;
|
|
477
|
+
method: string;
|
|
478
|
+
params?: unknown;
|
|
479
|
+
}
|
|
480
|
+
/** @experimental */
|
|
481
|
+
interface JsonRpcResponse {
|
|
482
|
+
jsonrpc: '2.0';
|
|
483
|
+
id: number | string | null;
|
|
484
|
+
result?: unknown;
|
|
485
|
+
error?: {
|
|
486
|
+
code: number;
|
|
487
|
+
message: string;
|
|
488
|
+
data?: unknown;
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/** @experimental */
|
|
492
|
+
declare function createMcpServer(options?: McpServerOptions): McpServer;
|
|
493
|
+
/**
|
|
494
|
+
* In-process pair of `Readable` + `Writable` streams suitable for driving
|
|
495
|
+
* `server.serve(...)` from a test. Returns the agent-side stream (the
|
|
496
|
+
* client writes to it) and the server-side stream (the test reads from it).
|
|
497
|
+
*
|
|
498
|
+
* @experimental
|
|
499
|
+
*/
|
|
500
|
+
declare function createInProcessTransport(): {
|
|
501
|
+
transport: McpTransport;
|
|
502
|
+
clientWrite(line: string): void;
|
|
503
|
+
clientClose(): void;
|
|
504
|
+
readServer(): Promise<JsonRpcResponse[]>;
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* @experimental
|
|
509
|
+
*
|
|
510
|
+
* `delegate_code` MCP tool — async kickoff. The handler validates the
|
|
511
|
+
* input, computes an idempotency key over the canonical fields, hands
|
|
512
|
+
* the task to the queue, and returns `{ taskId, estimatedDurationMs }`.
|
|
513
|
+
*/
|
|
514
|
+
|
|
515
|
+
/** @experimental */
|
|
516
|
+
declare const DELEGATE_CODE_TOOL_NAME = "delegate_code";
|
|
517
|
+
/** @experimental */
|
|
518
|
+
declare const DELEGATE_CODE_DESCRIPTION: string;
|
|
519
|
+
/** @experimental */
|
|
520
|
+
declare const DELEGATE_CODE_INPUT_SCHEMA: {
|
|
521
|
+
readonly type: "object";
|
|
522
|
+
readonly properties: {
|
|
523
|
+
readonly goal: {
|
|
524
|
+
readonly type: "string";
|
|
525
|
+
readonly description: "Natural-language description of what the coder must accomplish.";
|
|
526
|
+
};
|
|
527
|
+
readonly repoRoot: {
|
|
528
|
+
readonly type: "string";
|
|
529
|
+
readonly description: "Absolute path inside the sandbox where the repo lives.";
|
|
530
|
+
};
|
|
531
|
+
readonly contextHint: {
|
|
532
|
+
readonly type: "string";
|
|
533
|
+
readonly description: "Optional free-form context the coder sees in the prompt prelude.";
|
|
534
|
+
};
|
|
535
|
+
readonly variants: {
|
|
536
|
+
readonly type: "integer";
|
|
537
|
+
readonly minimum: 1;
|
|
538
|
+
readonly maximum: 8;
|
|
539
|
+
readonly description: "Number of parallel coder harnesses. Default 1.";
|
|
540
|
+
};
|
|
541
|
+
readonly config: {
|
|
542
|
+
readonly type: "object";
|
|
543
|
+
readonly properties: {
|
|
544
|
+
readonly testCmd: {
|
|
545
|
+
readonly type: "string";
|
|
546
|
+
};
|
|
547
|
+
readonly typecheckCmd: {
|
|
548
|
+
readonly type: "string";
|
|
549
|
+
};
|
|
550
|
+
readonly forbiddenPaths: {
|
|
551
|
+
readonly type: "array";
|
|
552
|
+
readonly items: {
|
|
553
|
+
readonly type: "string";
|
|
554
|
+
};
|
|
555
|
+
};
|
|
556
|
+
readonly maxDiffLines: {
|
|
557
|
+
readonly type: "integer";
|
|
558
|
+
readonly minimum: 1;
|
|
559
|
+
};
|
|
560
|
+
};
|
|
561
|
+
readonly additionalProperties: false;
|
|
562
|
+
};
|
|
563
|
+
readonly namespace: {
|
|
564
|
+
readonly type: "string";
|
|
565
|
+
readonly description: "Multi-tenant scope (customer-id, workspace-id).";
|
|
566
|
+
};
|
|
567
|
+
};
|
|
568
|
+
readonly required: readonly ["goal", "repoRoot"];
|
|
569
|
+
readonly additionalProperties: false;
|
|
570
|
+
};
|
|
571
|
+
/** @experimental */
|
|
572
|
+
declare function validateDelegateCodeArgs(raw: unknown): DelegateCodeArgs;
|
|
573
|
+
/** @experimental */
|
|
574
|
+
interface DelegateCodeHandlerOptions {
|
|
575
|
+
queue: DelegationTaskQueue;
|
|
576
|
+
delegate: CoderDelegate;
|
|
577
|
+
/** Override the duration hint. */
|
|
578
|
+
estimateDurationMs?: (args: DelegateCodeArgs) => number;
|
|
579
|
+
}
|
|
580
|
+
/** @experimental */
|
|
581
|
+
declare function createDelegateCodeHandler(options: DelegateCodeHandlerOptions): (raw: unknown) => Promise<DelegateCodeResult>;
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* @experimental
|
|
585
|
+
*
|
|
586
|
+
* `delegate_feedback` MCP tool — synchronous record of agent / user /
|
|
587
|
+
* downstream-judge feedback on a delegation, artifact, or outcome.
|
|
588
|
+
*
|
|
589
|
+
* The store is append-only. Every rating is its own event; no dedupe.
|
|
590
|
+
* When `refersTo.kind === 'delegation'`, the snapshot is also attached
|
|
591
|
+
* to the matching queue record so `delegation_history` surfaces it
|
|
592
|
+
* inline without a join.
|
|
593
|
+
*/
|
|
594
|
+
|
|
595
|
+
/** @experimental */
|
|
596
|
+
declare const DELEGATE_FEEDBACK_TOOL_NAME = "delegate_feedback";
|
|
597
|
+
/** @experimental */
|
|
598
|
+
declare const DELEGATE_FEEDBACK_DESCRIPTION: string;
|
|
599
|
+
/** @experimental */
|
|
600
|
+
declare const DELEGATE_FEEDBACK_INPUT_SCHEMA: {
|
|
601
|
+
readonly type: "object";
|
|
602
|
+
readonly properties: {
|
|
603
|
+
readonly refersTo: {
|
|
604
|
+
readonly type: "object";
|
|
605
|
+
readonly properties: {
|
|
606
|
+
readonly kind: {
|
|
607
|
+
readonly type: "string";
|
|
608
|
+
readonly enum: readonly ["delegation", "artifact", "outcome"];
|
|
609
|
+
};
|
|
610
|
+
readonly ref: {
|
|
611
|
+
readonly type: "string";
|
|
612
|
+
};
|
|
613
|
+
};
|
|
614
|
+
readonly required: readonly ["kind", "ref"];
|
|
615
|
+
readonly additionalProperties: false;
|
|
616
|
+
};
|
|
617
|
+
readonly rating: {
|
|
618
|
+
readonly type: "object";
|
|
619
|
+
readonly properties: {
|
|
620
|
+
readonly score: {
|
|
621
|
+
readonly type: "number";
|
|
622
|
+
readonly minimum: 0;
|
|
623
|
+
readonly maximum: 1;
|
|
624
|
+
};
|
|
625
|
+
readonly label: {
|
|
626
|
+
readonly type: "string";
|
|
627
|
+
readonly enum: readonly ["good", "bad", "neutral", "mixed"];
|
|
628
|
+
};
|
|
629
|
+
readonly notes: {
|
|
630
|
+
readonly type: "string";
|
|
631
|
+
};
|
|
632
|
+
};
|
|
633
|
+
readonly required: readonly ["score", "notes"];
|
|
634
|
+
readonly additionalProperties: false;
|
|
635
|
+
};
|
|
636
|
+
readonly by: {
|
|
637
|
+
readonly type: "string";
|
|
638
|
+
readonly enum: readonly ["agent", "user", "downstream-judge"];
|
|
639
|
+
};
|
|
640
|
+
readonly capturedAt: {
|
|
641
|
+
readonly type: "string";
|
|
642
|
+
};
|
|
643
|
+
readonly namespace: {
|
|
644
|
+
readonly type: "string";
|
|
645
|
+
};
|
|
646
|
+
};
|
|
647
|
+
readonly required: readonly ["refersTo", "rating", "by"];
|
|
648
|
+
readonly additionalProperties: false;
|
|
649
|
+
};
|
|
650
|
+
/** @experimental */
|
|
651
|
+
declare function validateDelegateFeedbackArgs(raw: unknown): DelegateFeedbackArgs;
|
|
652
|
+
/** @experimental */
|
|
653
|
+
interface DelegateFeedbackHandlerOptions {
|
|
654
|
+
queue: DelegationTaskQueue;
|
|
655
|
+
store: FeedbackStore;
|
|
656
|
+
generateId?: () => string;
|
|
657
|
+
now?: () => string;
|
|
658
|
+
}
|
|
659
|
+
/** @experimental */
|
|
660
|
+
declare function createDelegateFeedbackHandler(options: DelegateFeedbackHandlerOptions): (raw: unknown) => Promise<DelegateFeedbackResult>;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* @experimental
|
|
664
|
+
*
|
|
665
|
+
* `delegate_research` MCP tool — async kickoff for source-grounded
|
|
666
|
+
* research tasks. Same async semantics as `delegate_code`: returns a
|
|
667
|
+
* taskId immediately, idempotent on canonical inputs.
|
|
668
|
+
*
|
|
669
|
+
* The handler does not import a researcher profile directly — consumers
|
|
670
|
+
* inject a `ResearcherDelegate` via `createMcpServer({ researcherDelegate })`.
|
|
671
|
+
* The substrate cannot depend on `@tangle-network/agent-knowledge`
|
|
672
|
+
* without inducing a dependency cycle.
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
/** @experimental */
|
|
676
|
+
declare const DELEGATE_RESEARCH_TOOL_NAME = "delegate_research";
|
|
677
|
+
/** @experimental */
|
|
678
|
+
declare const DELEGATE_RESEARCH_DESCRIPTION: string;
|
|
679
|
+
/** @experimental */
|
|
680
|
+
declare const DELEGATE_RESEARCH_INPUT_SCHEMA: {
|
|
681
|
+
readonly type: "object";
|
|
682
|
+
readonly properties: {
|
|
683
|
+
readonly question: {
|
|
684
|
+
readonly type: "string";
|
|
685
|
+
readonly description: "The research question to answer.";
|
|
686
|
+
};
|
|
687
|
+
readonly namespace: {
|
|
688
|
+
readonly type: "string";
|
|
689
|
+
readonly description: "Multi-tenant scope (customer-id, workspace-id). REQUIRED.";
|
|
690
|
+
};
|
|
691
|
+
readonly scope: {
|
|
692
|
+
readonly type: "string";
|
|
693
|
+
readonly description: "Bound, e.g. \"audience for cpg-founder ICP\".";
|
|
694
|
+
};
|
|
695
|
+
readonly sources: {
|
|
696
|
+
readonly type: "array";
|
|
697
|
+
readonly items: {
|
|
698
|
+
readonly type: "string";
|
|
699
|
+
readonly enum: readonly ResearchSource[];
|
|
700
|
+
};
|
|
701
|
+
};
|
|
702
|
+
readonly variants: {
|
|
703
|
+
readonly type: "integer";
|
|
704
|
+
readonly minimum: 1;
|
|
705
|
+
readonly maximum: 8;
|
|
706
|
+
};
|
|
707
|
+
readonly config: {
|
|
708
|
+
readonly type: "object";
|
|
709
|
+
readonly properties: {
|
|
710
|
+
readonly recencyWindow: {
|
|
711
|
+
readonly type: "object";
|
|
712
|
+
readonly properties: {
|
|
713
|
+
readonly since: {
|
|
714
|
+
readonly type: "string";
|
|
715
|
+
readonly description: "ISO datetime";
|
|
716
|
+
};
|
|
717
|
+
readonly until: {
|
|
718
|
+
readonly type: "string";
|
|
719
|
+
readonly description: "ISO datetime";
|
|
720
|
+
};
|
|
721
|
+
};
|
|
722
|
+
readonly additionalProperties: false;
|
|
723
|
+
};
|
|
724
|
+
readonly maxItems: {
|
|
725
|
+
readonly type: "integer";
|
|
726
|
+
readonly minimum: 1;
|
|
727
|
+
};
|
|
728
|
+
readonly minConfidence: {
|
|
729
|
+
readonly type: "number";
|
|
730
|
+
readonly minimum: 0;
|
|
731
|
+
readonly maximum: 1;
|
|
732
|
+
};
|
|
733
|
+
};
|
|
734
|
+
readonly additionalProperties: false;
|
|
735
|
+
};
|
|
736
|
+
};
|
|
737
|
+
readonly required: readonly ["question", "namespace"];
|
|
738
|
+
readonly additionalProperties: false;
|
|
739
|
+
};
|
|
740
|
+
/** @experimental */
|
|
741
|
+
declare function validateDelegateResearchArgs(raw: unknown): DelegateResearchArgs;
|
|
742
|
+
/** @experimental */
|
|
743
|
+
interface DelegateResearchHandlerOptions {
|
|
744
|
+
queue: DelegationTaskQueue;
|
|
745
|
+
delegate: ResearcherDelegate;
|
|
746
|
+
estimateDurationMs?: (args: DelegateResearchArgs) => number;
|
|
747
|
+
}
|
|
748
|
+
/** @experimental */
|
|
749
|
+
declare function createDelegateResearchHandler(options: DelegateResearchHandlerOptions): (raw: unknown) => Promise<DelegateResearchResult>;
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* @experimental
|
|
753
|
+
*
|
|
754
|
+
* `delegation_history` MCP tool — synchronous read of past delegations.
|
|
755
|
+
* The agent uses this for self-introspection — "have I delegated this
|
|
756
|
+
* kind of task before? did it work?" — and calibration.
|
|
757
|
+
*/
|
|
758
|
+
|
|
759
|
+
/** @experimental */
|
|
760
|
+
declare const DELEGATION_HISTORY_TOOL_NAME = "delegation_history";
|
|
761
|
+
/** @experimental */
|
|
762
|
+
declare const DELEGATION_HISTORY_DESCRIPTION: string;
|
|
763
|
+
/** @experimental */
|
|
764
|
+
declare const DELEGATION_HISTORY_INPUT_SCHEMA: {
|
|
765
|
+
readonly type: "object";
|
|
766
|
+
readonly properties: {
|
|
767
|
+
readonly namespace: {
|
|
768
|
+
readonly type: "string";
|
|
769
|
+
};
|
|
770
|
+
readonly profile: {
|
|
771
|
+
readonly type: "string";
|
|
772
|
+
readonly enum: readonly ["coder", "researcher"];
|
|
773
|
+
};
|
|
774
|
+
readonly since: {
|
|
775
|
+
readonly type: "string";
|
|
776
|
+
readonly description: "ISO datetime — earliest startedAt to include.";
|
|
777
|
+
};
|
|
778
|
+
readonly limit: {
|
|
779
|
+
readonly type: "integer";
|
|
780
|
+
readonly minimum: 1;
|
|
781
|
+
readonly maximum: 500;
|
|
782
|
+
};
|
|
783
|
+
};
|
|
784
|
+
readonly additionalProperties: false;
|
|
785
|
+
};
|
|
786
|
+
/** @experimental */
|
|
787
|
+
declare function validateDelegationHistoryArgs(raw: unknown): DelegationHistoryArgs;
|
|
788
|
+
/** @experimental */
|
|
789
|
+
interface DelegationHistoryHandlerOptions {
|
|
790
|
+
queue: DelegationTaskQueue;
|
|
791
|
+
}
|
|
792
|
+
/** @experimental */
|
|
793
|
+
declare function createDelegationHistoryHandler(options: DelegationHistoryHandlerOptions): (raw: unknown) => Promise<DelegationHistoryResult>;
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* @experimental
|
|
797
|
+
*
|
|
798
|
+
* `delegation_status` MCP tool — synchronous poll. Returns the current
|
|
799
|
+
* state machine + optional progress + final result (when terminal).
|
|
800
|
+
*/
|
|
801
|
+
|
|
802
|
+
/** @experimental */
|
|
803
|
+
declare const DELEGATION_STATUS_TOOL_NAME = "delegation_status";
|
|
804
|
+
/** @experimental */
|
|
805
|
+
declare const DELEGATION_STATUS_DESCRIPTION: string;
|
|
806
|
+
/** @experimental */
|
|
807
|
+
declare const DELEGATION_STATUS_INPUT_SCHEMA: {
|
|
808
|
+
readonly type: "object";
|
|
809
|
+
readonly properties: {
|
|
810
|
+
readonly taskId: {
|
|
811
|
+
readonly type: "string";
|
|
812
|
+
readonly description: "Returned by delegate_code / delegate_research.";
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
readonly required: readonly ["taskId"];
|
|
816
|
+
readonly additionalProperties: false;
|
|
817
|
+
};
|
|
818
|
+
/** @experimental */
|
|
819
|
+
declare function validateDelegationStatusArgs(raw: unknown): DelegationStatusArgs;
|
|
820
|
+
/** @experimental */
|
|
821
|
+
interface DelegationStatusHandlerOptions {
|
|
822
|
+
queue: DelegationTaskQueue;
|
|
823
|
+
}
|
|
824
|
+
/** @experimental */
|
|
825
|
+
declare function createDelegationStatusHandler(options: DelegationStatusHandlerOptions): (raw: unknown) => Promise<DelegationStatusResult>;
|
|
826
|
+
|
|
827
|
+
export { type CoderDelegate, type CreateDefaultCoderDelegateOptions, DELEGATE_CODE_DESCRIPTION, DELEGATE_CODE_INPUT_SCHEMA, DELEGATE_CODE_TOOL_NAME, DELEGATE_FEEDBACK_DESCRIPTION, DELEGATE_FEEDBACK_INPUT_SCHEMA, DELEGATE_FEEDBACK_TOOL_NAME, DELEGATE_RESEARCH_DESCRIPTION, DELEGATE_RESEARCH_INPUT_SCHEMA, DELEGATE_RESEARCH_TOOL_NAME, DELEGATION_HISTORY_DESCRIPTION, DELEGATION_HISTORY_INPUT_SCHEMA, DELEGATION_HISTORY_TOOL_NAME, DELEGATION_STATUS_DESCRIPTION, DELEGATION_STATUS_INPUT_SCHEMA, DELEGATION_STATUS_TOOL_NAME, type DelegateCodeArgs, type DelegateCodeConfig, type DelegateCodeResult, type DelegateFeedbackArgs, type DelegateFeedbackResult, type DelegateResearchArgs, type DelegateResearchConfig, type DelegateResearchResult, type DelegateRunCtx, type DelegationError, type DelegationFeedbackSnapshot, type DelegationHistoryArgs, type DelegationHistoryEntry, type DelegationHistoryResult, type DelegationProfile, type DelegationProgress, type DelegationRecord, type DelegationResultPayload, type DelegationStatus, type DelegationStatusArgs, type DelegationStatusResult, DelegationTaskQueue, type DelegationTaskQueueOptions, type FeedbackEvent, type FeedbackRating, type FeedbackRefersTo, type FeedbackStore, InMemoryFeedbackStore, type JsonRpcMessage, type JsonRpcResponse, type McpServer, type McpServerOptions, type McpToolDescriptor, type McpTransport, type ResearchOutputShape, type ResearchSource, type ResearcherDelegate, type SubmitInput, type SubmitOutput, createDefaultCoderDelegate, createDelegateCodeHandler, createDelegateFeedbackHandler, createDelegateResearchHandler, createDelegationHistoryHandler, createDelegationStatusHandler, createInProcessTransport, createMcpServer, eventToSnapshot, hashIdempotencyInput, validateDelegateCodeArgs, validateDelegateFeedbackArgs, validateDelegateResearchArgs, validateDelegationHistoryArgs, validateDelegationStatusArgs };
|