@tangle-network/agent-runtime 0.23.0 → 0.25.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 +85 -498
- package/dist/agent.d.ts +5 -206
- package/dist/chunk-GLR25NG7.js +92 -0
- package/dist/chunk-GLR25NG7.js.map +1 -0
- package/dist/{chunk-7HN72MF3.js → chunk-QZEDHTT2.js} +2 -2
- package/dist/chunk-QZEDHTT2.js.map +1 -0
- package/dist/{chunk-IQHYOJU3.js → chunk-ZJACJZF7.js} +289 -1
- package/dist/chunk-ZJACJZF7.js.map +1 -0
- package/dist/improvement-adapter-CaZxFxTd.d.ts +207 -0
- package/dist/improvement.d.ts +120 -0
- package/dist/improvement.js +161 -0
- package/dist/improvement.js.map +1 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/local-harness-KrdFTY5R.d.ts +82 -0
- package/dist/mcp/bin.js +2 -1
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +190 -2
- package/dist/mcp/index.js +21 -13
- package/dist/mcp/index.js.map +1 -1
- package/package.json +17 -23
- package/dist/chunk-7HN72MF3.js.map +0 -1
- package/dist/chunk-IQHYOJU3.js.map +0 -1
package/dist/agent.d.ts
CHANGED
|
@@ -1,103 +1,9 @@
|
|
|
1
1
|
import * as _tangle_network_agent_eval from '@tangle-network/agent-eval';
|
|
2
|
-
import {
|
|
2
|
+
import { TraceAnalystKindSpec, AnalystFinding } from '@tangle-network/agent-eval';
|
|
3
3
|
import { R as RuntimeStreamEvent } from './types-BFgFD_sl.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* `AgentSurfaces` — declarative map of the mutable file/directory paths
|
|
8
|
-
* the self-improvement loop can edit on behalf of an agent.
|
|
9
|
-
*
|
|
10
|
-
* The substrate uses this map to resolve every parsed `FindingSubject`
|
|
11
|
-
* (from agent-eval) to a real on-disk path. No per-vertical glue;
|
|
12
|
-
* no fabricated paths; no silent `existsSync(...)` skips that hide
|
|
13
|
-
* misconfiguration from the operator.
|
|
14
|
-
*
|
|
15
|
-
* Surfaces are validated at `defineAgent` time — missing paths fail
|
|
16
|
-
* loud with a list of every offender. A surface that's not needed
|
|
17
|
-
* (e.g. an agent with no RAG corpora) is simply omitted; the loop
|
|
18
|
-
* refuses to route those subjects rather than fabricating a target.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Surface declarations. Every path is repo-relative (or absolute) at
|
|
23
|
-
* `defineAgent` time. At resolution time, paths are joined against the
|
|
24
|
-
* agent's `repoRoot`.
|
|
25
|
-
*
|
|
26
|
-
* `systemPrompt`, `tools`, `personas` are DIRECTORIES; the loop appends
|
|
27
|
-
* `<section>.md`, `<tool>/README.md`, `<persona-id>.yaml` etc.
|
|
28
|
-
* `rubric`, `outputSchema` are SINGLE FILES; the loop edits them in
|
|
29
|
-
* place.
|
|
30
|
-
*
|
|
31
|
-
* `knowledge` is the agent-knowledge root (typically `.agent-knowledge`);
|
|
32
|
-
* `applyKnowledgeWriteBlocks` writes pages relative to it.
|
|
33
|
-
*
|
|
34
|
-
* Optional surfaces (`scaffolding`, `memory`, `rag`, `outputSchema`)
|
|
35
|
-
* can be omitted — the loop will reject findings targeting them with a
|
|
36
|
-
* clear log message instead of fabricating a path.
|
|
37
|
-
*/
|
|
38
|
-
interface AgentSurfaces {
|
|
39
|
-
/** Directory containing one markdown file per system-prompt section. */
|
|
40
|
-
systemPrompt: string;
|
|
41
|
-
/** Directory containing one subdir per tool (`<tool>/README.md`). */
|
|
42
|
-
tools: string;
|
|
43
|
-
/** Single file (TypeScript module) defining the rubric weights + dimensions. */
|
|
44
|
-
rubric: string;
|
|
45
|
-
/** Knowledge-base root; typically `.agent-knowledge`. */
|
|
46
|
-
knowledge: string;
|
|
47
|
-
/** Directory containing one YAML/JSON file per persona. */
|
|
48
|
-
personas: string;
|
|
49
|
-
/** Optional: directory containing scaffolding rules (precondition checks, retry policies). */
|
|
50
|
-
scaffolding?: string;
|
|
51
|
-
/** Optional: memory store path (JSONL / SQLite / DB). */
|
|
52
|
-
memory?: string;
|
|
53
|
-
/** Optional: directory containing RAG corpora (`<corpus>/<doc-id>.md`). */
|
|
54
|
-
rag?: string;
|
|
55
|
-
/** Optional: single file defining the output schema (Zod / JSON Schema). */
|
|
56
|
-
outputSchema?: string;
|
|
57
|
-
}
|
|
58
|
-
interface ResolvedSurface {
|
|
59
|
-
/** Absolute filesystem path the operator can `cat` / `vim`. */
|
|
60
|
-
absolutePath: string;
|
|
61
|
-
/** Repo-relative path for PR descriptions, diffs, audit logs. */
|
|
62
|
-
repoRelativePath: string;
|
|
63
|
-
/** Whether the path currently exists on disk. */
|
|
64
|
-
exists: boolean;
|
|
65
|
-
/** The substrate's intent: edit an existing file or create a new one. */
|
|
66
|
-
intent: 'edit-existing' | 'create-new';
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Resolve a parsed `FindingSubject` to the file path the substrate
|
|
70
|
-
* should edit (or create) on disk.
|
|
71
|
-
*
|
|
72
|
-
* Returns `null` when:
|
|
73
|
-
* - the subject targets a surface the agent didn't declare
|
|
74
|
-
* (e.g. `rag:*` when `surfaces.rag` is undefined), OR
|
|
75
|
-
* - the subject is a `cluster` (failure-mode emits these as evidence,
|
|
76
|
-
* not actionable mutations — they don't route to a file).
|
|
77
|
-
*
|
|
78
|
-
* Returns a `ResolvedSurface` with `intent: 'create-new'` when the
|
|
79
|
-
* subject names a path that doesn't yet exist (e.g. a new wiki page).
|
|
80
|
-
* The caller chooses whether to honour the create — for tightly-managed
|
|
81
|
-
* surfaces like `systemPrompt` it's usually a contract violation
|
|
82
|
-
* (the analyst named a section that doesn't exist); for `knowledge`
|
|
83
|
-
* it's the whole point.
|
|
84
|
-
*/
|
|
85
|
-
declare function resolveSubjectPath(subject: FindingSubject, surfaces: AgentSurfaces, repoRoot: string): ResolvedSurface | null;
|
|
86
|
-
/**
|
|
87
|
-
* Validate that every declared surface exists on disk under `repoRoot`.
|
|
88
|
-
*
|
|
89
|
-
* Returns an array of `SurfaceValidationIssue` — empty when all required
|
|
90
|
-
* surfaces resolve. `defineAgent` throws with the issues rendered, so
|
|
91
|
-
* a misconfigured manifest fails at startup (not at the first finding
|
|
92
|
-
* the loop produces 20 minutes later).
|
|
93
|
-
*/
|
|
94
|
-
interface SurfaceValidationIssue {
|
|
95
|
-
surface: keyof AgentSurfaces;
|
|
96
|
-
path: string;
|
|
97
|
-
reason: 'missing' | 'not-directory' | 'not-file';
|
|
98
|
-
}
|
|
99
|
-
declare function validateSurfaces(surfaces: AgentSurfaces, repoRoot: string): ReadonlyArray<SurfaceValidationIssue>;
|
|
100
|
-
declare function renderSurfaceIssues(issues: ReadonlyArray<SurfaceValidationIssue>, repoRoot: string): string;
|
|
4
|
+
import { A as AgentSurfaces } from './improvement-adapter-CaZxFxTd.js';
|
|
5
|
+
export { C as CreateSurfaceImprovementAdapterOpts, D as DraftPatchInput, a as DraftPatchOutput, R as ResolvedSurface, S as SurfaceImprovementEdit, b as SurfaceValidationIssue, c as createSurfaceImprovementAdapter, r as renderSurfaceIssues, d as resolveSubjectPath, v as validateSurfaces } from './improvement-adapter-CaZxFxTd.js';
|
|
6
|
+
import { K as KnowledgeAdapter, a as RunAnalystLoopResult } from './types-D_MXrmJP.js';
|
|
101
7
|
|
|
102
8
|
/**
|
|
103
9
|
* The full agent manifest. Each agent ships ONE of these.
|
|
@@ -342,113 +248,6 @@ declare class AgentManifestError extends Error {
|
|
|
342
248
|
*/
|
|
343
249
|
declare function defineAgent<TPersona = unknown, TRunOutput = unknown>(manifest: AgentManifest<TPersona, TRunOutput>): AgentManifest<TPersona, TRunOutput>;
|
|
344
250
|
|
|
345
|
-
/**
|
|
346
|
-
* Substrate-default `ImprovementAdapter` — surfaces-driven, LLM-drafted
|
|
347
|
-
* patches, optional auto-apply or PR-open.
|
|
348
|
-
*
|
|
349
|
-
* This is the one ImprovementAdapter every vertical agent uses. The
|
|
350
|
-
* substrate parses each finding's `subject` via
|
|
351
|
-
* `parseFindingSubject` (agent-eval), resolves it to a real file path
|
|
352
|
-
* via the agent's `AgentSurfaces`, reads the current content, and asks
|
|
353
|
-
* an LLM to draft a unified-diff patch given the finding + current
|
|
354
|
-
* content + per-kind editing-discipline rules.
|
|
355
|
-
*
|
|
356
|
-
* Auto-apply gates on the source-finding's confidence and the
|
|
357
|
-
* autoApply.improvement policy. Two modes:
|
|
358
|
-
* `write` — apply the patch in-place via `git apply -p0`. Operator
|
|
359
|
-
* reviews via `git diff`.
|
|
360
|
-
* `open-pr` — write to a branch, commit, push, open a PR via `gh`.
|
|
361
|
-
* Operator reviews via the PR UI.
|
|
362
|
-
*
|
|
363
|
-
* Fail-loud rules:
|
|
364
|
-
* - Findings whose subject doesn't parse → counted in `errors`.
|
|
365
|
-
* - Findings whose subject targets an undeclared surface → counted in
|
|
366
|
-
* `errors` with the offending kind in the message.
|
|
367
|
-
* - Findings whose target path doesn't exist AND the kind isn't a
|
|
368
|
-
* create-new variant (`new-tool`, `knowledge.wiki`) → counted in
|
|
369
|
-
* `errors` with the resolved path in the message.
|
|
370
|
-
* - LLM drafts that fail JSON-schema validation → counted in
|
|
371
|
-
* `errors` with the schema issue.
|
|
372
|
-
*
|
|
373
|
-
* No silent skips. Every dropped finding has a recorded reason the
|
|
374
|
-
* loop's report surfaces.
|
|
375
|
-
*/
|
|
376
|
-
|
|
377
|
-
interface SurfaceImprovementEdit {
|
|
378
|
-
/** Stable id derived from the source finding so re-proposals are idempotent. */
|
|
379
|
-
id: string;
|
|
380
|
-
/** The finding that produced this edit — for revert + audit trail. */
|
|
381
|
-
sourceFindingId: string;
|
|
382
|
-
/** Parsed subject; included so the apply step doesn't re-parse. */
|
|
383
|
-
subject: FindingSubject;
|
|
384
|
-
/** Resolved on-disk target. */
|
|
385
|
-
target: ResolvedSurface;
|
|
386
|
-
/** SHA-256 of the current file content the patch was drafted against. */
|
|
387
|
-
baseSha256: string;
|
|
388
|
-
/** Unified-diff patch the LLM drafted (relative to `target.absolutePath`). */
|
|
389
|
-
patch: string;
|
|
390
|
-
/** One-line summary the operator sees in the report / PR title. */
|
|
391
|
-
summary: string;
|
|
392
|
-
/** Multi-line rationale for the PR body — finding context + LLM reasoning. */
|
|
393
|
-
rationale: string;
|
|
394
|
-
/** Carry-forward from the finding so the apply gate can check the threshold. */
|
|
395
|
-
confidence: number;
|
|
396
|
-
/** Carry-forward severity for prioritization. */
|
|
397
|
-
severity: AnalystFinding['severity'];
|
|
398
|
-
}
|
|
399
|
-
interface CreateSurfaceImprovementAdapterOpts {
|
|
400
|
-
surfaces: AgentSurfaces;
|
|
401
|
-
repoRoot: string;
|
|
402
|
-
/**
|
|
403
|
-
* LLM-draft callback. Given a finding + current file content + the
|
|
404
|
-
* resolved target, returns a unified-diff patch + summary + rationale.
|
|
405
|
-
*
|
|
406
|
-
* Required — the substrate doesn't ship a hardcoded prompt; the agent
|
|
407
|
-
* author picks the model (Haiku for cheap routine drafts, Sonnet for
|
|
408
|
-
* substantive prompt rewrites, etc.) via this callback.
|
|
409
|
-
*/
|
|
410
|
-
draftPatch: (input: DraftPatchInput) => Promise<DraftPatchOutput>;
|
|
411
|
-
/**
|
|
412
|
-
* Apply mode:
|
|
413
|
-
* `write` — `git apply` in-place; operator reviews via `git diff`
|
|
414
|
-
* `open-pr` — branch + commit + push + `gh pr create`
|
|
415
|
-
* `none` — never apply; collect proposals for the report only
|
|
416
|
-
*
|
|
417
|
-
* The `apply` method honours this even when the loop calls it; the
|
|
418
|
-
* effective behaviour is also gated on the per-finding confidence
|
|
419
|
-
* threshold via `runAnalystLoop`'s `autoApply` policy.
|
|
420
|
-
*/
|
|
421
|
-
mode?: 'write' | 'open-pr' | 'none';
|
|
422
|
-
/** When `mode === 'open-pr'`, the base branch new PRs target. Default: `main`. */
|
|
423
|
-
baseBranch?: string;
|
|
424
|
-
/** Required for `mode === 'open-pr'` — the GH owner/repo (`tangle-network/tax-agent`). */
|
|
425
|
-
ghRepo?: string;
|
|
426
|
-
/**
|
|
427
|
-
* When the resolved target doesn't exist, allow the substrate to
|
|
428
|
-
* CREATE the file (for `knowledge.wiki`, `new-tool` subjects). Default
|
|
429
|
-
* true for those kinds, false for `system-prompt` / `rubric` / etc.
|
|
430
|
-
* (named sections that don't exist are a contract violation, not a
|
|
431
|
-
* scaffolding opportunity).
|
|
432
|
-
*/
|
|
433
|
-
allowCreateForKinds?: ReadonlyArray<FindingSubject['kind']>;
|
|
434
|
-
}
|
|
435
|
-
interface DraftPatchInput {
|
|
436
|
-
finding: AnalystFinding;
|
|
437
|
-
subject: FindingSubject;
|
|
438
|
-
target: ResolvedSurface;
|
|
439
|
-
/** Current file content (empty string when `intent === 'create-new'`). */
|
|
440
|
-
currentContent: string;
|
|
441
|
-
}
|
|
442
|
-
interface DraftPatchOutput {
|
|
443
|
-
/** Unified diff against the current file content. Empty string skips this finding. */
|
|
444
|
-
patch: string;
|
|
445
|
-
/** One-line summary for the operator. */
|
|
446
|
-
summary: string;
|
|
447
|
-
/** Multi-line rationale for the PR body. */
|
|
448
|
-
rationale: string;
|
|
449
|
-
}
|
|
450
|
-
declare function createSurfaceImprovementAdapter(opts: CreateSurfaceImprovementAdapterOpts): ImprovementAdapter<SurfaceImprovementEdit>;
|
|
451
|
-
|
|
452
251
|
/**
|
|
453
252
|
* Substrate-default `KnowledgeAdapter` — wraps agent-knowledge's
|
|
454
253
|
* `proposeFromFindings` + `applyKnowledgeWriteBlocks` with substrate
|
|
@@ -580,4 +379,4 @@ declare function measureOutcome<TProposal, TEdit>(result: RunAnalystLoopResult<T
|
|
|
580
379
|
outcome: OutcomeMeasurement;
|
|
581
380
|
}>;
|
|
582
381
|
|
|
583
|
-
export { type AgentManifest, AgentManifestError, type AgentRubric, type AgentRunContext, type AgentRunInvocation, type AgentRuntime,
|
|
382
|
+
export { type AgentManifest, AgentManifestError, type AgentRubric, type AgentRunContext, type AgentRunInvocation, type AgentRuntime, AgentSurfaces, type AnalystConfig, type AutoApplyPolicy, type CreateSurfaceKnowledgeAdapterOpts, type JudgeConfig, type KnowledgeAdapterDeps, type OutcomeMeasurement, type OutcomeMeasurementOpts, type RubricDimension, collectAgentRun, createSurfaceKnowledgeAdapter, defineAgent, measureOutcome, unimplementedAgentRun };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// src/mcp/local-harness.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
var HARNESS_INVOCATIONS = {
|
|
4
|
+
claude: {
|
|
5
|
+
command: "claude",
|
|
6
|
+
buildArgs: (taskPrompt) => ["--headless", "-p", taskPrompt]
|
|
7
|
+
},
|
|
8
|
+
codex: {
|
|
9
|
+
command: "codex",
|
|
10
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt]
|
|
11
|
+
},
|
|
12
|
+
opencode: {
|
|
13
|
+
command: "opencode",
|
|
14
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt]
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
18
|
+
function runLocalHarness(options) {
|
|
19
|
+
const { harness, cwd, taskPrompt } = options;
|
|
20
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
21
|
+
const env = options.env ?? process.env;
|
|
22
|
+
const spawnImpl = options.spawn ?? spawn;
|
|
23
|
+
const invocation = HARNESS_INVOCATIONS[harness];
|
|
24
|
+
if (!invocation) {
|
|
25
|
+
return Promise.reject(new Error(`runLocalHarness: unknown harness ${String(harness)}`));
|
|
26
|
+
}
|
|
27
|
+
const startedAt = Date.now();
|
|
28
|
+
const args = invocation.buildArgs(taskPrompt);
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
let child;
|
|
31
|
+
try {
|
|
32
|
+
child = spawnImpl(invocation.command, args, { cwd, env, stdio: "pipe" });
|
|
33
|
+
} catch (err) {
|
|
34
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let stdout = "";
|
|
38
|
+
let stderr = "";
|
|
39
|
+
let timedOut = false;
|
|
40
|
+
let settled = false;
|
|
41
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
42
|
+
timedOut = true;
|
|
43
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
44
|
+
}, timeoutMs) : null;
|
|
45
|
+
if (timer && typeof timer.unref === "function") {
|
|
46
|
+
;
|
|
47
|
+
timer.unref();
|
|
48
|
+
}
|
|
49
|
+
const onAbort = () => {
|
|
50
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
51
|
+
};
|
|
52
|
+
if (options.signal) {
|
|
53
|
+
if (options.signal.aborted) onAbort();
|
|
54
|
+
else options.signal.addEventListener("abort", onAbort, { once: true });
|
|
55
|
+
}
|
|
56
|
+
child.stdout?.on("data", (chunk) => {
|
|
57
|
+
stdout += String(chunk);
|
|
58
|
+
});
|
|
59
|
+
child.stderr?.on("data", (chunk) => {
|
|
60
|
+
stderr += String(chunk);
|
|
61
|
+
});
|
|
62
|
+
const finalize = (result) => {
|
|
63
|
+
if (settled) return;
|
|
64
|
+
settled = true;
|
|
65
|
+
if (timer) clearTimeout(timer);
|
|
66
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
67
|
+
resolve(result);
|
|
68
|
+
};
|
|
69
|
+
child.on("error", (err) => {
|
|
70
|
+
if (settled) return;
|
|
71
|
+
settled = true;
|
|
72
|
+
if (timer) clearTimeout(timer);
|
|
73
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
74
|
+
reject(err);
|
|
75
|
+
});
|
|
76
|
+
child.on("close", (code, signal) => {
|
|
77
|
+
finalize({
|
|
78
|
+
exitCode: code,
|
|
79
|
+
stdout,
|
|
80
|
+
stderr,
|
|
81
|
+
killedBySignal: signal,
|
|
82
|
+
durationMs: Date.now() - startedAt,
|
|
83
|
+
timedOut
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
runLocalHarness
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=chunk-GLR25NG7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/local-harness.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Subprocess wrappers for the local coding-harness CLIs installed in the\n * sandbox image (claude-code, codex, opencode). Used by the in-process\n * delegation executor (`createInProcessExecutor`) so a `delegate_code` call\n * spawns a real harness on a real git worktree instead of provisioning a\n * sibling sandbox.\n *\n * All harness invocations:\n * - run with `cwd` set to the worktree\n * - inherit env from the parent (the MCP server inside the sandbox has\n * the harness's auth already)\n * - capture stdout/stderr\n * - support cancellation via AbortSignal\n * - enforce a wall-clock timeout\n */\n\nimport { type ChildProcess, spawn } from 'node:child_process'\n\n/** Local coding harness available inside the sandbox. */\nexport type LocalHarness = 'claude' | 'codex' | 'opencode'\n\n/** Default per-harness command + arg shape. */\nconst HARNESS_INVOCATIONS: Record<\n LocalHarness,\n { command: string; buildArgs: (taskPrompt: string) => string[] }\n> = {\n claude: {\n command: 'claude',\n buildArgs: (taskPrompt) => ['--headless', '-p', taskPrompt],\n },\n codex: {\n command: 'codex',\n buildArgs: (taskPrompt) => ['run', taskPrompt],\n },\n opencode: {\n command: 'opencode',\n buildArgs: (taskPrompt) => ['run', taskPrompt],\n },\n}\n\n/** @experimental */\nexport interface RunLocalHarnessOptions {\n harness: LocalHarness\n /** Working directory for the subprocess (typically a worktree path). */\n cwd: string\n /** Prompt forwarded as the harness CLI's task argument. */\n taskPrompt: string\n /** Wall-clock kill deadline (ms). Default 5 min. Subprocess SIGTERMed on expiry. */\n timeoutMs?: number\n /** Caller cancellation. SIGTERM is sent on abort. */\n signal?: AbortSignal\n /** Override env (defaults to inheriting from the parent). */\n env?: NodeJS.ProcessEnv\n /**\n * Test seam — inject a custom spawner so unit tests can mock the\n * subprocess without touching the OS. Defaults to node's `child_process.spawn`.\n */\n spawn?: (\n command: string,\n args: ReadonlyArray<string>,\n opts: {\n cwd: string\n env: NodeJS.ProcessEnv\n stdio: 'pipe'\n },\n ) => ChildProcess\n}\n\n/** @experimental */\nexport interface LocalHarnessResult {\n /** OS exit code. `null` when killed before exit. */\n exitCode: number | null\n /** Concatenated stdout. */\n stdout: string\n /** Concatenated stderr. */\n stderr: string\n /** Set when the process exited via signal (timeout / abort). */\n killedBySignal: NodeJS.Signals | null\n /** Wall-clock duration ms (spawn → exit). */\n durationMs: number\n /** Set when timeoutMs elapsed before exit. */\n timedOut: boolean\n}\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000\n\n/**\n * Spawn a local coding harness CLI as a subprocess + collect its output.\n *\n * NOT responsible for parsing the harness's output or extracting a diff —\n * the in-process executor's `streamPrompt` orchestrates `git diff` against\n * the worktree after this resolves. This function is intentionally narrow:\n * spawn, wait, capture, return.\n *\n * Fails loud — throws when:\n * - `cwd` doesn't exist (subprocess emits ENOENT; surfaced as Error)\n * - the harness binary is not on PATH (ENOENT)\n *\n * Does NOT throw when:\n * - the subprocess exits non-zero (`result.exitCode` carries the code)\n * - the subprocess is aborted / timed out (`result.killedBySignal` /\n * `result.timedOut` carries the reason)\n *\n * @experimental\n */\nexport function runLocalHarness(options: RunLocalHarnessOptions): Promise<LocalHarnessResult> {\n const { harness, cwd, taskPrompt } = options\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const env = options.env ?? process.env\n const spawnImpl = options.spawn ?? spawn\n\n const invocation = HARNESS_INVOCATIONS[harness]\n if (!invocation) {\n return Promise.reject(new Error(`runLocalHarness: unknown harness ${String(harness)}`))\n }\n\n const startedAt = Date.now()\n const args = invocation.buildArgs(taskPrompt)\n\n return new Promise<LocalHarnessResult>((resolve, reject) => {\n let child: ChildProcess\n try {\n child = spawnImpl(invocation.command, args, { cwd, env, stdio: 'pipe' })\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n\n let stdout = ''\n let stderr = ''\n let timedOut = false\n let settled = false\n\n const timer =\n timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n if (!child.killed) child.kill('SIGTERM')\n }, timeoutMs)\n : null\n if (timer && typeof (timer as { unref?: () => void }).unref === 'function') {\n ;(timer as { unref: () => void }).unref()\n }\n\n const onAbort = () => {\n if (!child.killed) child.kill('SIGTERM')\n }\n if (options.signal) {\n if (options.signal.aborted) onAbort()\n else options.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n child.stdout?.on('data', (chunk) => {\n stdout += String(chunk)\n })\n child.stderr?.on('data', (chunk) => {\n stderr += String(chunk)\n })\n\n const finalize = (result: LocalHarnessResult) => {\n if (settled) return\n settled = true\n if (timer) clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n resolve(result)\n }\n\n child.on('error', (err) => {\n if (settled) return\n settled = true\n if (timer) clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n reject(err)\n })\n\n child.on('close', (code, signal) => {\n finalize({\n exitCode: code,\n stdout,\n stderr,\n killedBySignal: signal,\n durationMs: Date.now() - startedAt,\n timedOut,\n })\n })\n })\n}\n"],"mappings":";AAkBA,SAA4B,aAAa;AAMzC,IAAM,sBAGF;AAAA,EACF,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,WAAW,CAAC,eAAe,CAAC,cAAc,MAAM,UAAU;AAAA,EAC5D;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW,CAAC,eAAe,CAAC,OAAO,UAAU;AAAA,EAC/C;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,WAAW,CAAC,eAAe,CAAC,OAAO,UAAU;AAAA,EAC/C;AACF;AA8CA,IAAM,qBAAqB,IAAI,KAAK;AAqB7B,SAAS,gBAAgB,SAA8D;AAC5F,QAAM,EAAE,SAAS,KAAK,WAAW,IAAI;AACrC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,YAAY,QAAQ,SAAS;AAEnC,QAAM,aAAa,oBAAoB,OAAO;AAC9C,MAAI,CAAC,YAAY;AACf,WAAO,QAAQ,OAAO,IAAI,MAAM,oCAAoC,OAAO,OAAO,CAAC,EAAE,CAAC;AAAA,EACxF;AAEA,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,OAAO,WAAW,UAAU,UAAU;AAE5C,SAAO,IAAI,QAA4B,CAAC,SAAS,WAAW;AAC1D,QAAI;AACJ,QAAI;AACF,cAAQ,UAAU,WAAW,SAAS,MAAM,EAAE,KAAK,KAAK,OAAO,OAAO,CAAC;AAAA,IACzE,SAAS,KAAK;AACZ,aAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI,WAAW;AACf,QAAI,UAAU;AAEd,UAAM,QACJ,YAAY,IACR,WAAW,MAAM;AACf,iBAAW;AACX,UAAI,CAAC,MAAM,OAAQ,OAAM,KAAK,SAAS;AAAA,IACzC,GAAG,SAAS,IACZ;AACN,QAAI,SAAS,OAAQ,MAAiC,UAAU,YAAY;AAC1E;AAAC,MAAC,MAAgC,MAAM;AAAA,IAC1C;AAEA,UAAM,UAAU,MAAM;AACpB,UAAI,CAAC,MAAM,OAAQ,OAAM,KAAK,SAAS;AAAA,IACzC;AACA,QAAI,QAAQ,QAAQ;AAClB,UAAI,QAAQ,OAAO,QAAS,SAAQ;AAAA,UAC/B,SAAQ,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,IACvE;AAEA,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAU,OAAO,KAAK;AAAA,IACxB,CAAC;AACD,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAU,OAAO,KAAK;AAAA,IACxB,CAAC;AAED,UAAM,WAAW,CAAC,WAA+B;AAC/C,UAAI,QAAS;AACb,gBAAU;AACV,UAAI,MAAO,cAAa,KAAK;AAC7B,cAAQ,QAAQ,oBAAoB,SAAS,OAAO;AACpD,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,UAAI,QAAS;AACb,gBAAU;AACV,UAAI,MAAO,cAAa,KAAK;AAC7B,cAAQ,QAAQ,oBAAoB,SAAS,OAAO;AACpD,aAAO,GAAG;AAAA,IACZ,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,MAAM,WAAW;AAClC,eAAS;AAAA,QACP,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,YAAY,KAAK,IAAI,IAAI;AAAA,QACzB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
|
|
@@ -114,7 +114,7 @@ function createOtelExporter(config) {
|
|
|
114
114
|
}
|
|
115
115
|
]
|
|
116
116
|
};
|
|
117
|
-
const url = endpoint.replace(/\/+$/, "")
|
|
117
|
+
const url = `${endpoint.replace(/\/+$/, "")}/v1/traces`;
|
|
118
118
|
try {
|
|
119
119
|
await fetch(url, {
|
|
120
120
|
method: "POST",
|
|
@@ -197,4 +197,4 @@ export {
|
|
|
197
197
|
createOtelExporter,
|
|
198
198
|
loopEventToOtelSpan
|
|
199
199
|
};
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
200
|
+
//# sourceMappingURL=chunk-QZEDHTT2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/openai-tools.ts","../src/otel-export.ts"],"sourcesContent":["/**\n * @experimental\n *\n * OpenAI Chat Completions `tools[]` projection of the 5 agent-runtime MCP\n * delegation tools.\n *\n * Use when configuring `createOpenAICompatibleBackend({ tools: ... })` so the\n * model can call `delegate_code`, `delegate_research`, `delegate_feedback`,\n * `delegation_status`, and `delegation_history` through the OpenAI-compat\n * transport (tcloud, OpenRouter, OpenAI direct, cli-bridge). The runtime\n * surfaces tool calls as `tool_call` stream events — execution is the\n * caller's responsibility (typically the parent sandbox runtime's MCP\n * mount).\n *\n * Sandbox-SDK callers do NOT need this helper: the sandbox runtime mounts\n * MCP servers natively and the in-sandbox harness discovers tools via the\n * runtime, not via an OpenAI tools array.\n *\n * Tool name + description + JSON-schema are pulled from the canonical\n * `DELEGATE_*` constants exported by `./tools/*` so the projection cannot\n * drift from the server's own validators.\n */\n\nimport type { OpenAIChatTool } from '../types'\nimport {\n DELEGATE_CODE_DESCRIPTION,\n DELEGATE_CODE_INPUT_SCHEMA,\n DELEGATE_CODE_TOOL_NAME,\n} from './tools/delegate-code'\nimport {\n DELEGATE_FEEDBACK_DESCRIPTION,\n DELEGATE_FEEDBACK_INPUT_SCHEMA,\n DELEGATE_FEEDBACK_TOOL_NAME,\n} from './tools/delegate-feedback'\nimport {\n DELEGATE_RESEARCH_DESCRIPTION,\n DELEGATE_RESEARCH_INPUT_SCHEMA,\n DELEGATE_RESEARCH_TOOL_NAME,\n} from './tools/delegate-research'\nimport {\n DELEGATION_HISTORY_DESCRIPTION,\n DELEGATION_HISTORY_INPUT_SCHEMA,\n DELEGATION_HISTORY_TOOL_NAME,\n} from './tools/delegation-history'\nimport {\n DELEGATION_STATUS_DESCRIPTION,\n DELEGATION_STATUS_INPUT_SCHEMA,\n DELEGATION_STATUS_TOOL_NAME,\n} from './tools/delegation-status'\n\nfunction buildTool(\n name: string,\n description: string,\n parameters: Readonly<Record<string, unknown>>,\n): OpenAIChatTool {\n // `parameters` arrives as a deeply-readonly `as const` literal. The\n // OpenAI-compat backend JSON-serializes the body so a shallow copy\n // into a plain object is sufficient — and shields callers that mutate\n // the returned descriptor from corrupting the source constant.\n return {\n type: 'function',\n function: { name, description, parameters: { ...parameters } },\n }\n}\n\n/**\n * @experimental\n *\n * Returns the 5 delegation tools projected into OpenAI Chat Completions\n * `tools[]` shape. The order is stable: `delegate_code`,\n * `delegate_research`, `delegate_feedback`, `delegation_status`,\n * `delegation_history`.\n */\nexport function mcpToolsForRuntimeMcp(): OpenAIChatTool[] {\n return [\n buildTool(\n DELEGATE_CODE_TOOL_NAME,\n DELEGATE_CODE_DESCRIPTION,\n DELEGATE_CODE_INPUT_SCHEMA as Readonly<Record<string, unknown>>,\n ),\n buildTool(\n DELEGATE_RESEARCH_TOOL_NAME,\n DELEGATE_RESEARCH_DESCRIPTION,\n DELEGATE_RESEARCH_INPUT_SCHEMA as Readonly<Record<string, unknown>>,\n ),\n buildTool(\n DELEGATE_FEEDBACK_TOOL_NAME,\n DELEGATE_FEEDBACK_DESCRIPTION,\n DELEGATE_FEEDBACK_INPUT_SCHEMA as Readonly<Record<string, unknown>>,\n ),\n buildTool(\n DELEGATION_STATUS_TOOL_NAME,\n DELEGATION_STATUS_DESCRIPTION,\n DELEGATION_STATUS_INPUT_SCHEMA as Readonly<Record<string, unknown>>,\n ),\n buildTool(\n DELEGATION_HISTORY_TOOL_NAME,\n DELEGATION_HISTORY_DESCRIPTION,\n DELEGATION_HISTORY_INPUT_SCHEMA as Readonly<Record<string, unknown>>,\n ),\n ]\n}\n\n/**\n * @experimental\n *\n * Subset filter — return only the projected tools whose `function.name`\n * appears in `names`. Useful for curated mounts (e.g. only the queue-bound\n * delegation tools, omitting `delegate_feedback`). Unknown names are\n * silently ignored; pass an empty array to get an empty result.\n */\nexport function mcpToolsForRuntimeMcpSubset(names: ReadonlyArray<string>): OpenAIChatTool[] {\n const allowed = new Set(names)\n return mcpToolsForRuntimeMcp().filter((tool) => allowed.has(tool.function.name))\n}\n","/**\n * OTEL span exporter — streams LoopTraceEvents to an OTLP/HTTP collector.\n *\n * Reads OTEL_EXPORTER_OTLP_ENDPOINT + OTEL_EXPORTER_OTLP_HEADERS from env\n * when no explicit config is given. Keeps the runtime dep-free from\n * @opentelemetry/sdk-trace-base — minimal OTLP/JSON serializer.\n *\n * The exporter accepts both raw OtelSpan objects and LoopTraceEvents\n * (which get converted to OTLP spans automatically).\n */\n\nexport interface OtelExportConfig {\n /** OTLP endpoint. Reads OTEL_EXPORTER_OTLP_ENDPOINT env by default. */\n endpoint?: string\n /** OTLP headers. Reads OTEL_EXPORTER_OTLP_HEADERS env by default. */\n headers?: Record<string, string>\n /** Batch size before flush. Default 64. */\n batchSize?: number\n /** Flush interval ms. Default 5000. */\n flushIntervalMs?: number\n /** Resource attributes stamped on every export. */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Service name. Default 'agent-runtime'. */\n serviceName?: string\n}\n\nexport interface OtelExporter {\n /** Export a span. */\n exportSpan(span: OtelSpan): void\n /** Force flush pending spans. */\n flush(): Promise<void>\n /** Shutdown cleanly. */\n shutdown(): Promise<void>\n}\n\nexport interface OtelSpan {\n traceId: string\n spanId: string\n parentSpanId?: string\n name: string\n kind?: number\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes?: OtelAttribute[]\n status?: { code: number; message?: string }\n}\n\nexport interface OtelAttribute {\n key: string\n value: { stringValue?: string; intValue?: string; doubleValue?: number; boolValue?: boolean }\n}\n\ninterface OtlpResourceSpans {\n resource: { attributes: OtelAttribute[] }\n scopeSpans: Array<{ scope: { name: string; version: string }; spans: OtelSpan[] }>\n}\n\ninterface OtlpExport {\n resourceSpans: OtlpResourceSpans[]\n}\n\nconst SCOPE = { name: '@tangle-network/agent-runtime', version: '0.23.0' }\n\n/**\n * Create an OTEL exporter. Returns undefined when no endpoint is configured.\n */\nexport function createOtelExporter(config?: OtelExportConfig): OtelExporter | undefined {\n const resolvedEndpoint =\n config?.endpoint ??\n (typeof process !== 'undefined' ? process.env.OTEL_EXPORTER_OTLP_ENDPOINT : undefined)\n if (!resolvedEndpoint) return undefined\n const endpoint: string = resolvedEndpoint\n\n const headers = config?.headers ?? parseHeadersFromEnv()\n const batchSize = config?.batchSize ?? 64\n const flushIntervalMs = config?.flushIntervalMs ?? 5000\n const serviceName = config?.serviceName ?? 'agent-runtime'\n const resourceAttrs = config?.resourceAttributes ?? {}\n\n const pending: OtelSpan[] = []\n let timer: ReturnType<typeof setInterval> | undefined\n let stopped = false\n\n const exporter: OtelExporter = {\n exportSpan(span: OtelSpan): void {\n if (stopped) return\n pending.push(span)\n if (pending.length >= batchSize) {\n void doFlush()\n }\n },\n\n async flush(): Promise<void> {\n await doFlush()\n },\n\n async shutdown(): Promise<void> {\n stopped = true\n if (timer !== undefined) {\n clearInterval(timer)\n timer = undefined\n }\n await doFlush()\n },\n }\n\n timer = setInterval(() => {\n if (pending.length > 0) void doFlush()\n }, flushIntervalMs)\n if (typeof timer === 'object' && 'unref' in timer) {\n ;(timer as NodeJS.Timeout).unref()\n }\n\n async function doFlush(): Promise<void> {\n if (pending.length === 0) return\n const batch = pending.splice(0)\n const body: OtlpExport = {\n resourceSpans: [\n {\n resource: {\n attributes: toAttributes({\n 'service.name': serviceName,\n ...resourceAttrs,\n }),\n },\n scopeSpans: [{ scope: SCOPE, spans: batch }],\n },\n ],\n }\n const url = `${endpoint.replace(/\\/+$/, '')}/v1/traces`\n try {\n await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...headers },\n body: JSON.stringify(body),\n })\n } catch {\n // Best-effort — telemetry export must not crash the runtime.\n }\n }\n\n return exporter\n}\n\n/**\n * Convert a LoopTraceEvent into an OtelSpan for export.\n */\nexport function loopEventToOtelSpan(\n event: {\n kind: string\n runId: string\n timestamp: number\n payload: object\n },\n traceId: string,\n parentSpanId?: string,\n): OtelSpan {\n const spanId = generateSpanId()\n const attrs: Record<string, string | number | boolean> = {\n 'loop.event_kind': event.kind,\n 'loop.run_id': event.runId,\n }\n for (const [k, v] of Object.entries(event.payload)) {\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n attrs[`loop.${k}`] = v\n }\n }\n const ts = msToNs(event.timestamp)\n return {\n traceId: padTraceId(traceId),\n spanId,\n parentSpanId: parentSpanId ? padSpanId(parentSpanId) : undefined,\n name: event.kind,\n kind: 1,\n startTimeUnixNano: ts,\n endTimeUnixNano: ts,\n attributes: toAttributes(attrs),\n status: { code: 1 },\n }\n}\n\nfunction parseHeadersFromEnv(): Record<string, string> {\n if (typeof process === 'undefined') return {}\n const raw = process.env.OTEL_EXPORTER_OTLP_HEADERS\n if (!raw) return {}\n const out: Record<string, string> = {}\n for (const pair of raw.split(',')) {\n const eq = pair.indexOf('=')\n if (eq < 0) continue\n const key = pair.slice(0, eq).trim()\n const value = pair.slice(eq + 1).trim()\n if (key) out[key] = value\n }\n return out\n}\n\nfunction toAttributes(record: Record<string, string | number | boolean>): OtelAttribute[] {\n return Object.entries(record).map(([key, value]) => ({\n key,\n value:\n typeof value === 'number'\n ? Number.isInteger(value)\n ? { intValue: value.toString() }\n : { doubleValue: value }\n : typeof value === 'boolean'\n ? { boolValue: value }\n : { stringValue: value },\n }))\n}\n\nfunction msToNs(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString()\n}\n\nfunction padSpanId(id: string): string {\n const cleaned = id.replace(/-/g, '')\n return cleaned.slice(0, 16).padEnd(16, '0')\n}\n\nfunction padTraceId(id: string): string {\n const cleaned = id.replace(/-/g, '')\n return cleaned.slice(0, 32).padEnd(32, '0')\n}\n\nfunction generateSpanId(): string {\n const bytes = new Uint8Array(8)\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < 8; i++) bytes[i] = Math.floor(Math.random() * 256)\n }\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n"],"mappings":"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","names":[]}
|