zidane 5.7.7 → 5.7.8
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 +1 -0
- package/dist/chat.d.ts +2 -2
- package/dist/headless-CEtk5dzV.js +489 -0
- package/dist/headless-CEtk5dzV.js.map +1 -0
- package/dist/headless.d.ts +2 -0
- package/dist/headless.js +2 -0
- package/dist/{index-B6h9C_JE.d.ts → index-DEqGfnZr.d.ts} +1275 -1128
- package/dist/index-DEqGfnZr.d.ts.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -238
- package/dist/index.js.map +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/{transcript-anchors-qxevvEwT.d.ts → transcript-anchors-BBN7jlvp.d.ts} +2 -2
- package/dist/{transcript-anchors-qxevvEwT.d.ts.map → transcript-anchors-BBN7jlvp.d.ts.map} +1 -1
- package/dist/tui.d.ts +1 -1
- package/dist/types.d.ts +1 -1
- package/docs/HEADLESS.md +138 -0
- package/package.json +8 -2
- package/dist/index-B6h9C_JE.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -798,6 +798,7 @@ Benchmark harnesses live in [`benchmarks/`](./benchmarks). First integration: [T
|
|
|
798
798
|
| Doc | What |
|
|
799
799
|
|---|---|
|
|
800
800
|
| [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) | Mermaid diagrams of the agent loop, tool execution, hook firing order, dependency graph. |
|
|
801
|
+
| [docs/HEADLESS.md](./docs/HEADLESS.md) | `zidane/headless` — non-interactive `runHeadless()` + CLI for automation / RL rollouts. Structured result, JSONL transcript, `stream-json`, exit codes. |
|
|
801
802
|
| [docs/SKILL.md](./docs/SKILL.md) | Authoritative reference for `createAgent` + hooks + tools + sessions + skills + MCP. Long-form. |
|
|
802
803
|
| [docs/CHAT.md](./docs/CHAT.md) | `zidane/chat` — renderer-agnostic chat engine (auth, sessions, safe-mode, settings, theme). Consumed by the TUI and any future GUI. |
|
|
803
804
|
| [docs/TUI.md](./docs/TUI.md) | `zidane/tui` — terminal shell built on `zidane/chat`. `runTui()`, screens, modals, keyboard, theming. |
|
package/dist/chat.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $t as McpToolSchema, Bn as ContextItem, D as SkillConfig, Fn as ContextBreakdown, Hn as ContextSnapshot, In as ContextBreakdownOptions, Ln as ContextCategory, N as Session, Rn as ContextCategoryId, Un as ContextUsageSplit, Vn as ContextMcpGroup, Wn as buildContextBreakdown, Zt as McpServerConfig, dn as SessionTurn, j as SkillsConfig, lt as Provider, r as AgentHooks, zn as ContextExactCounts } from "./agent-BSPhByzT.js";
|
|
2
|
-
import {
|
|
2
|
+
import { H as McpCredentialEntry, U as McpCredentialStore, t as Preset } from "./index-DEqGfnZr.js";
|
|
3
3
|
import { m as SourcedScanPath } from "./index-DmbrQjOk.js";
|
|
4
|
-
import { $ as useInteractionsQueue, $t as parseBindingSpec, A as InteractionsProvider, At as marginTopFor, B as QuestionPayload, Bt as KEYBINDING_DEF_BY_ACTION, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as lastContextSizeFromTurns, E as CreateInteractionToolsOptions, Et as eventsFromTurns, F as PlanRequest, Ft as toolCallPreview, G as TextQuestion, Gt as KeyBindings, H as QuestionResponse, Ht as KeyAction, I as PlanResponse, It as toolResultText, J as isInteractionTool, Jt as formatBindingForDisplay, K as buildResumedToolResultsTurn, Kt as ParsedBinding, L as PlanStep, Lt as updateToolEventOutcomes, M as PendingInteractionEntry, Mt as stripSpawnTokensLine, N as PlanDecision, Nt as sumRunCosts, O as InteractionResponse, Ot as listSessionMeta, P as PlanPayload, Pt as titleFromTurns, Q as useInteractionsActions, Qt as mergeKeybindings, R as Question, Rt as DEFAULT_KEYBINDINGS, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as deriveSessionTitle, U as QuestionType, Ut as KeyBindingDef, V as QuestionRequest, Vt as KEYBINDING_KEY_COL_WIDTH, W as SelectQuestion, Wt as KeyBindingSection, X as pendingInteractionsFromTurns, Xt as keybindingsPath, Y as makeRequestInteraction, Yt as groupBindings, Z as serializeInteractionResponse, Zt as matchesBinding, _ as SessionExportTarget, _n as PLAN_AGENT, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as Hint, at as DiscoveryResult, b as writeSessionExport, bn as singleAgentRegistry, bt as StorageSlot, c as SyntaxTokenStyle, cn as truncateTrailing, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentRegistry, dt as ChatOptions, en as readKeybindings, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as BUILD_AGENT, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_PERSIST_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_BUDGET_EXCLUDE_TOOLS, ht as resolveConfig, i as ChipColor, in as EMPTY_HINTS, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as saveState, k as InteractionsActions, kt as loadState, l as Theme, ln as AgentAccent, lt as parseMcpsFile, m as resolveTheme, mn as DEFAULT_AGENT_ID, mt as ResolvedPaths, n as computeTurnAnchors, nn as CompletionState, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as clipHintsToWidth, ot as buildMcpServers, p as resolveChipColor, pn as BUILTIN_AGENTS, pt as ResolvedConfig, q as createInteractionTools, qt as ensureKeybindingsFile, r as BUILTIN_THEMES, rn as useCompletion, rt as DiscoveredMcp, s as SyntaxStyles, sn as hintsLength, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as stripJsonComments, tt as EnabledToggleSet, u as ThemeColors, un as AgentProfile, ut as AutoUpdateConfig, v as renderSession, vn as accentColor, vt as StorageDirs, w as AnswerValue, wt as createStateStore, x as MarkdownSegment, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as resolveAgentId, yt as StorageMode, z as QuestionChoice, zt as KEYBINDING_DEFS } from "./transcript-anchors-
|
|
4
|
+
import { $ as useInteractionsQueue, $t as parseBindingSpec, A as InteractionsProvider, At as marginTopFor, B as QuestionPayload, Bt as KEYBINDING_DEF_BY_ACTION, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as lastContextSizeFromTurns, E as CreateInteractionToolsOptions, Et as eventsFromTurns, F as PlanRequest, Ft as toolCallPreview, G as TextQuestion, Gt as KeyBindings, H as QuestionResponse, Ht as KeyAction, I as PlanResponse, It as toolResultText, J as isInteractionTool, Jt as formatBindingForDisplay, K as buildResumedToolResultsTurn, Kt as ParsedBinding, L as PlanStep, Lt as updateToolEventOutcomes, M as PendingInteractionEntry, Mt as stripSpawnTokensLine, N as PlanDecision, Nt as sumRunCosts, O as InteractionResponse, Ot as listSessionMeta, P as PlanPayload, Pt as titleFromTurns, Q as useInteractionsActions, Qt as mergeKeybindings, R as Question, Rt as DEFAULT_KEYBINDINGS, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as deriveSessionTitle, U as QuestionType, Ut as KeyBindingDef, V as QuestionRequest, Vt as KEYBINDING_KEY_COL_WIDTH, W as SelectQuestion, Wt as KeyBindingSection, X as pendingInteractionsFromTurns, Xt as keybindingsPath, Y as makeRequestInteraction, Yt as groupBindings, Z as serializeInteractionResponse, Zt as matchesBinding, _ as SessionExportTarget, _n as PLAN_AGENT, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as Hint, at as DiscoveryResult, b as writeSessionExport, bn as singleAgentRegistry, bt as StorageSlot, c as SyntaxTokenStyle, cn as truncateTrailing, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentRegistry, dt as ChatOptions, en as readKeybindings, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as BUILD_AGENT, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_PERSIST_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_BUDGET_EXCLUDE_TOOLS, ht as resolveConfig, i as ChipColor, in as EMPTY_HINTS, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as saveState, k as InteractionsActions, kt as loadState, l as Theme, ln as AgentAccent, lt as parseMcpsFile, m as resolveTheme, mn as DEFAULT_AGENT_ID, mt as ResolvedPaths, n as computeTurnAnchors, nn as CompletionState, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as clipHintsToWidth, ot as buildMcpServers, p as resolveChipColor, pn as BUILTIN_AGENTS, pt as ResolvedConfig, q as createInteractionTools, qt as ensureKeybindingsFile, r as BUILTIN_THEMES, rn as useCompletion, rt as DiscoveredMcp, s as SyntaxStyles, sn as hintsLength, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as stripJsonComments, tt as EnabledToggleSet, u as ThemeColors, un as AgentProfile, ut as AutoUpdateConfig, v as renderSession, vn as accentColor, vt as StorageDirs, w as AnswerValue, wt as createStateStore, x as MarkdownSegment, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as resolveAgentId, yt as StorageMode, z as QuestionChoice, zt as KEYBINDING_DEFS } from "./transcript-anchors-BBN7jlvp.js";
|
|
5
5
|
import { $ as anthropicDescriptor, A as SessionMeta, B as collectReferences, C as EditHunk, D as Owner, E as EditPayload, F as CompletionContext, G as ProviderKey, H as mergeReferences, I as CompletionItem, J as CustomField, K as detectAuth, L as CompletionProvider, M as StreamEvent, N as ToolCallDisplay, O as Picked, P as ActiveTrigger, Q as ProviderDescriptor, R as CompletionReference, S as EditDiffDisplay, T as EditOutcomeKind, U as AuthMethod, V as findActiveTrigger, W as ProviderAuth, X as ModelOption, Y as ModelInfo, Z as OUTPUT_RESERVE_TOKENS, _ as isEditErrorResult, a as formatToolCall, at as getModelInfo, b as selectableTurnIds, c as splitPromptSegments, ct as modelSupportsReasoning, d as RequestApproval, dt as openrouterDescriptor, et as cerebrasDescriptor, f as SafeModeActions, ft as piIdOf, h as useSafeModeQueue, i as displayNameFor, it as getContextWindow, j as Settings, k as Screen, l as ApprovalDecision, lt as modelsForDescriptor, m as useSafeModeActions, n as ToolDisplayMeta, nt as effectiveContextWindow, o as PromptSegment, ot as localDescriptor, p as SafeModeProvider, pt as restoreModelOptions, q as BUILTIN_PROVIDERS, r as ToolFormatLine, rt as enabledModelOptions, s as PromptSegmentRef, st as modelOptionsFor, t as TOOL_DISPLAY, tt as credKeyOf, u as ApprovalRequest, ut as openaiDescriptor, v as isTurnHighlighted, w as EditOutcome, x as turnSelectionOwnership, y as isVisible, z as applyInsert } from "./tool-formatters-fUAp2Nr4.js";
|
|
6
6
|
import { $ as uniqueFilesFromReferences, A as buildUnifiedDiff, B as buildEditOutcomesAnnotation, C as EditSummary, D as PreviewResult, E as InlineSegment, F as previewEditPayload, G as rewriteMultiEditHeader, H as mergeApprovalAndBodyOutcomes, I as splitLines, J as SKILLS_TRIGGER, K as stripEditOutcomesAnnotation, L as summarizeEditPayload, M as computeLineDiff, N as extractEditPayload, O as applyEditPayload, P as filetypeFromPath, Q as createFilesCompletionProvider, R as tokenize, S as EditHunkSummary, T as InlineDiff, U as parseEditOutcomesFromResult, V as maskToOutcomeKinds, W as resolveApprovalForPayload, X as uniqueSkillNamesFromReferences, Y as createSkillsCompletionProvider, Z as FILES_TRIGGER, _ as formatTaskSummary, a as finalizeStreamingMarkdown, b as DiffLine, c as CatalogEntry, d as indexOfEntry, et as FileEntry, f as ageString, g as formatTaskStatus, h as formatDuration, i as turnAsText, it as buildLinearRamp, j as computeInlineDiff, k as buildContextualDiff, l as buildModelCatalog, m as fmtTokens, n as deleteTurnSafely, nt as listProjectFiles, o as finalizeStreamingMarkdownForOwner, p as compactPath, q as summarizeOutcomes, r as truncateTurnsAt, rt as blendHsl, s as turnContextSize, t as countNeighbors, tt as ListProjectFilesOptions, u as filterModelCatalog, v as previewLine, w as HunkResolution, x as DiffOp, y as shortId, z as ResolvedApproval } from "./turn-operations-CE1prnuP.js";
|
|
7
7
|
import { Hookable } from "hookable";
|
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { d as createAgent } from "./tools-dkB_jARJ.js";
|
|
2
|
+
import { n as createProcessContext } from "./contexts-BD2U_xpi.js";
|
|
3
|
+
import { r as toolResultToText } from "./types-BPw_i5vb.js";
|
|
4
|
+
import { i as statsByModel } from "./stats-DAKBEKjc.js";
|
|
5
|
+
import { i as basic_default } from "./presets-DTxFbEZ5.js";
|
|
6
|
+
import { i as createMemoryStore, t as createSession } from "./session-BzLou2_-.js";
|
|
7
|
+
//#region src/run-summary.ts
|
|
8
|
+
/**
|
|
9
|
+
* Build a run-summary collector. State is created fresh inside each
|
|
10
|
+
* `install()` call, so a single collector instance can be installed
|
|
11
|
+
* across multiple agents without attribution cross-talk. `latest()`
|
|
12
|
+
* returns the most-recent summary across **any** install — install
|
|
13
|
+
* per-agent collectors if you need separate post-run snapshots.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const collector = createRunSummaryCollector({
|
|
18
|
+
* onSummary: s => console.log(JSON.stringify(s)),
|
|
19
|
+
* })
|
|
20
|
+
* const uninstall = collector.install(agent.hooks)
|
|
21
|
+
* try { await agent.run({ prompt }) }
|
|
22
|
+
* finally { uninstall() }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function createRunSummaryCollector(options = {}) {
|
|
26
|
+
let last;
|
|
27
|
+
return {
|
|
28
|
+
latest: () => last,
|
|
29
|
+
install(hooks) {
|
|
30
|
+
let runId;
|
|
31
|
+
let parentRunId;
|
|
32
|
+
let depth = 0;
|
|
33
|
+
let agentName;
|
|
34
|
+
let startedAt = Date.now();
|
|
35
|
+
let aborted = false;
|
|
36
|
+
const errors = [];
|
|
37
|
+
const blocks = [];
|
|
38
|
+
const validationRejects = [];
|
|
39
|
+
const budgetEvents = [];
|
|
40
|
+
const pairingRepairs = {};
|
|
41
|
+
const children = [];
|
|
42
|
+
function resetForNewRun() {
|
|
43
|
+
aborted = false;
|
|
44
|
+
errors.length = 0;
|
|
45
|
+
blocks.length = 0;
|
|
46
|
+
validationRejects.length = 0;
|
|
47
|
+
budgetEvents.length = 0;
|
|
48
|
+
for (const k of Object.keys(pairingRepairs)) delete pairingRepairs[k];
|
|
49
|
+
children.length = 0;
|
|
50
|
+
}
|
|
51
|
+
const unregisters = [];
|
|
52
|
+
unregisters.push(hooks.hook("agent:start", (ctx) => {
|
|
53
|
+
resetForNewRun();
|
|
54
|
+
runId = ctx.runId;
|
|
55
|
+
parentRunId = ctx.parentRunId;
|
|
56
|
+
depth = ctx.depth;
|
|
57
|
+
agentName = ctx.agentName;
|
|
58
|
+
startedAt = ctx.startedAt;
|
|
59
|
+
}));
|
|
60
|
+
unregisters.push(hooks.hook("agent:abort", () => {
|
|
61
|
+
aborted = true;
|
|
62
|
+
}));
|
|
63
|
+
unregisters.push(hooks.hook("stream:error", (ctx) => {
|
|
64
|
+
const msg = ctx.err instanceof Error ? ctx.err.message : String(ctx.err);
|
|
65
|
+
const errorType = ctx.err instanceof Error ? ctx.err.name : "unknown";
|
|
66
|
+
errors.push({
|
|
67
|
+
kind: "stream",
|
|
68
|
+
message: msg,
|
|
69
|
+
errorType,
|
|
70
|
+
turnId: ctx.turnId,
|
|
71
|
+
...ctx.statusCode !== void 0 ? { statusCode: ctx.statusCode } : {},
|
|
72
|
+
...ctx.requestId !== void 0 ? { requestId: ctx.requestId } : {}
|
|
73
|
+
});
|
|
74
|
+
}));
|
|
75
|
+
unregisters.push(hooks.hook("tool:error", (ctx) => {
|
|
76
|
+
errors.push({
|
|
77
|
+
kind: "tool",
|
|
78
|
+
message: ctx.error.message,
|
|
79
|
+
errorType: ctx.error.name,
|
|
80
|
+
turnId: ctx.turnId,
|
|
81
|
+
callId: ctx.callId,
|
|
82
|
+
toolName: ctx.name
|
|
83
|
+
});
|
|
84
|
+
}));
|
|
85
|
+
unregisters.push(hooks.hook("mcp:tool:error", (ctx) => {
|
|
86
|
+
errors.push({
|
|
87
|
+
kind: "mcp-tool",
|
|
88
|
+
message: ctx.error.message,
|
|
89
|
+
errorType: ctx.error.name,
|
|
90
|
+
turnId: ctx.turnId,
|
|
91
|
+
callId: ctx.callId,
|
|
92
|
+
server: ctx.server,
|
|
93
|
+
toolName: ctx.displayName
|
|
94
|
+
});
|
|
95
|
+
}));
|
|
96
|
+
unregisters.push(hooks.hook("mcp:error", (ctx) => {
|
|
97
|
+
errors.push({
|
|
98
|
+
kind: "mcp",
|
|
99
|
+
message: ctx.error.message,
|
|
100
|
+
errorType: ctx.error.name,
|
|
101
|
+
server: ctx.name
|
|
102
|
+
});
|
|
103
|
+
}));
|
|
104
|
+
unregisters.push(hooks.hook("spawn:error", (ctx) => {
|
|
105
|
+
errors.push({
|
|
106
|
+
kind: "spawn",
|
|
107
|
+
message: ctx.error.message,
|
|
108
|
+
errorType: ctx.error.name,
|
|
109
|
+
childId: ctx.id
|
|
110
|
+
});
|
|
111
|
+
}));
|
|
112
|
+
unregisters.push(hooks.hook("tool:dispatched", (ctx) => {
|
|
113
|
+
if (ctx.outcome === "gate-block" || ctx.outcome === "unknown" || ctx.outcome === "invalid-input") blocks.push({
|
|
114
|
+
callId: ctx.callId,
|
|
115
|
+
toolName: ctx.name,
|
|
116
|
+
outcome: ctx.outcome,
|
|
117
|
+
...ctx.reason ? { reason: ctx.reason } : {}
|
|
118
|
+
});
|
|
119
|
+
}));
|
|
120
|
+
unregisters.push(hooks.hook("validation:reject", (ctx) => {
|
|
121
|
+
validationRejects.push({
|
|
122
|
+
callId: ctx.callId,
|
|
123
|
+
toolName: ctx.name,
|
|
124
|
+
reason: ctx.reason
|
|
125
|
+
});
|
|
126
|
+
}));
|
|
127
|
+
unregisters.push(hooks.hook("budget:exceeded", (ctx) => {
|
|
128
|
+
budgetEvents.push({
|
|
129
|
+
kind: "bytes",
|
|
130
|
+
observed: ctx.bytes,
|
|
131
|
+
limit: ctx.budget,
|
|
132
|
+
turnId: ctx.turnId
|
|
133
|
+
});
|
|
134
|
+
}));
|
|
135
|
+
unregisters.push(hooks.hook("tool-budget:exceeded", (ctx) => {
|
|
136
|
+
budgetEvents.push({
|
|
137
|
+
kind: "tool-count",
|
|
138
|
+
toolName: ctx.tool,
|
|
139
|
+
mode: ctx.mode,
|
|
140
|
+
observed: ctx.count,
|
|
141
|
+
limit: ctx.max,
|
|
142
|
+
turnId: ctx.turnId
|
|
143
|
+
});
|
|
144
|
+
}));
|
|
145
|
+
unregisters.push(hooks.hook("pairing:repair", (ctx) => {
|
|
146
|
+
pairingRepairs[ctx.mode] = (pairingRepairs[ctx.mode] ?? 0) + 1;
|
|
147
|
+
}));
|
|
148
|
+
unregisters.push(hooks.hook("agent:done", (stats) => {
|
|
149
|
+
const endedAt = Date.now();
|
|
150
|
+
const byModel = [];
|
|
151
|
+
for (const [modelId, usage] of statsByModel(stats)) byModel.push({
|
|
152
|
+
modelId,
|
|
153
|
+
input: usage.input,
|
|
154
|
+
output: usage.output,
|
|
155
|
+
cacheRead: usage.cacheRead,
|
|
156
|
+
cacheCreation: usage.cacheCreation,
|
|
157
|
+
cost: usage.cost,
|
|
158
|
+
turns: usage.turns
|
|
159
|
+
});
|
|
160
|
+
for (const c of stats.children ?? []) children.push(minimalSummaryFromStats(c.stats, {
|
|
161
|
+
depth: c.depth ?? depth + 1,
|
|
162
|
+
status: c.status === "aborted" ? "aborted" : "completed"
|
|
163
|
+
}));
|
|
164
|
+
const summary = {
|
|
165
|
+
...runId ? { runId } : {},
|
|
166
|
+
...parentRunId ? { parentRunId } : {},
|
|
167
|
+
depth,
|
|
168
|
+
...agentName ? { agentName } : {},
|
|
169
|
+
startedAt,
|
|
170
|
+
endedAt,
|
|
171
|
+
durationMs: endedAt - startedAt,
|
|
172
|
+
status: aborted ? "aborted" : "completed",
|
|
173
|
+
turns: stats.turns,
|
|
174
|
+
totals: buildTotals(stats),
|
|
175
|
+
byModel,
|
|
176
|
+
errors: errors.slice(),
|
|
177
|
+
blocks: blocks.slice(),
|
|
178
|
+
validationRejects: validationRejects.slice(),
|
|
179
|
+
budgetEvents: budgetEvents.slice(),
|
|
180
|
+
pairingRepairs: { ...pairingRepairs },
|
|
181
|
+
...children.length > 0 ? { children: children.slice() } : {}
|
|
182
|
+
};
|
|
183
|
+
last = summary;
|
|
184
|
+
try {
|
|
185
|
+
options.onSummary?.(summary);
|
|
186
|
+
} catch {}
|
|
187
|
+
}));
|
|
188
|
+
let disposed = false;
|
|
189
|
+
return function uninstall() {
|
|
190
|
+
if (disposed) return;
|
|
191
|
+
disposed = true;
|
|
192
|
+
for (const un of unregisters) try {
|
|
193
|
+
un();
|
|
194
|
+
} catch {}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function buildTotals(stats) {
|
|
200
|
+
return {
|
|
201
|
+
input: stats.totalIn,
|
|
202
|
+
output: stats.totalOut,
|
|
203
|
+
cacheRead: stats.totalCacheRead,
|
|
204
|
+
cacheCreation: stats.totalCacheCreation,
|
|
205
|
+
...typeof stats.cost === "number" ? { cost: stats.cost } : {},
|
|
206
|
+
...typeof stats.timeTillFirstTokenMs === "number" ? { ttftMs: stats.timeTillFirstTokenMs } : {}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function minimalSummaryFromStats(stats, meta) {
|
|
210
|
+
const byModel = [];
|
|
211
|
+
for (const [modelId, usage] of statsByModel(stats)) byModel.push({
|
|
212
|
+
modelId,
|
|
213
|
+
input: usage.input,
|
|
214
|
+
output: usage.output,
|
|
215
|
+
cacheRead: usage.cacheRead,
|
|
216
|
+
cacheCreation: usage.cacheCreation,
|
|
217
|
+
cost: usage.cost,
|
|
218
|
+
turns: usage.turns
|
|
219
|
+
});
|
|
220
|
+
const children = [];
|
|
221
|
+
for (const c of stats.children ?? []) children.push(minimalSummaryFromStats(c.stats, {
|
|
222
|
+
depth: c.depth ?? meta.depth + 1,
|
|
223
|
+
status: c.status === "aborted" ? "aborted" : "completed"
|
|
224
|
+
}));
|
|
225
|
+
return {
|
|
226
|
+
depth: meta.depth,
|
|
227
|
+
startedAt: 0,
|
|
228
|
+
endedAt: 0,
|
|
229
|
+
durationMs: stats.elapsed,
|
|
230
|
+
status: meta.status,
|
|
231
|
+
turns: stats.turns,
|
|
232
|
+
totals: buildTotals(stats),
|
|
233
|
+
byModel,
|
|
234
|
+
errors: [],
|
|
235
|
+
blocks: [],
|
|
236
|
+
validationRejects: [],
|
|
237
|
+
budgetEvents: [],
|
|
238
|
+
pairingRepairs: {},
|
|
239
|
+
...children.length > 0 ? { children } : {}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/headless.ts
|
|
244
|
+
/** Serialize one event as a newline-terminated JSON line (stream-json). */
|
|
245
|
+
function headlessEventToJsonl(event) {
|
|
246
|
+
return `${JSON.stringify(event)}\n`;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Run a prompt to completion, headless, and return a single serializable
|
|
250
|
+
* {@link HeadlessResult}. Safe to call concurrently for parallel rollouts —
|
|
251
|
+
* each call builds its own agent + session and tears them down in `finally`.
|
|
252
|
+
*/
|
|
253
|
+
async function runHeadless(opts) {
|
|
254
|
+
const startedAt = Date.now();
|
|
255
|
+
const execution = opts.execution ?? createProcessContext({ cwd: opts.cwd });
|
|
256
|
+
const session = opts.session ?? await createSession({ store: opts.store ?? createMemoryStore() });
|
|
257
|
+
const behavior = {};
|
|
258
|
+
if (opts.maxTurns !== void 0) behavior.maxTurns = opts.maxTurns;
|
|
259
|
+
if (opts.maxTokens !== void 0) behavior.maxTokens = opts.maxTokens;
|
|
260
|
+
if (opts.schema !== void 0) behavior.schema = opts.schema;
|
|
261
|
+
const agent = createAgent({
|
|
262
|
+
...basic_default,
|
|
263
|
+
provider: opts.provider,
|
|
264
|
+
execution,
|
|
265
|
+
session,
|
|
266
|
+
behavior,
|
|
267
|
+
...opts.tools !== void 0 ? { tools: opts.tools } : {},
|
|
268
|
+
...opts.mcpServers !== void 0 ? { mcpServers: opts.mcpServers } : {},
|
|
269
|
+
...opts.skills !== void 0 ? { skills: opts.skills } : {}
|
|
270
|
+
});
|
|
271
|
+
const collector = createRunSummaryCollector();
|
|
272
|
+
const uninstallSummary = collector.install(agent.hooks);
|
|
273
|
+
const uninstallEvents = opts.onEvent ? installEventAdapter(agent.hooks, opts.onEvent) : noop;
|
|
274
|
+
const controller = new AbortController();
|
|
275
|
+
if (opts.signal) if (opts.signal.aborted) controller.abort(opts.signal.reason);
|
|
276
|
+
else opts.signal.addEventListener("abort", () => controller.abort(opts.signal.reason), { once: true });
|
|
277
|
+
let timedOut = false;
|
|
278
|
+
const timer = opts.timeoutMs && opts.timeoutMs > 0 ? setTimeout(() => {
|
|
279
|
+
timedOut = true;
|
|
280
|
+
controller.abort(/* @__PURE__ */ new Error(`Headless run timed out after ${opts.timeoutMs}ms`));
|
|
281
|
+
}, opts.timeoutMs) : void 0;
|
|
282
|
+
let stats;
|
|
283
|
+
let error;
|
|
284
|
+
try {
|
|
285
|
+
stats = await agent.run({
|
|
286
|
+
prompt: opts.prompt,
|
|
287
|
+
signal: controller.signal,
|
|
288
|
+
...opts.model !== void 0 ? { model: opts.model } : {},
|
|
289
|
+
...opts.system !== void 0 ? { system: opts.system } : {},
|
|
290
|
+
...opts.thinking !== void 0 ? { thinking: opts.thinking } : {}
|
|
291
|
+
});
|
|
292
|
+
} catch (err) {
|
|
293
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
294
|
+
error = {
|
|
295
|
+
message: e.message,
|
|
296
|
+
type: e.name
|
|
297
|
+
};
|
|
298
|
+
} finally {
|
|
299
|
+
if (timer) clearTimeout(timer);
|
|
300
|
+
uninstallEvents();
|
|
301
|
+
uninstallSummary();
|
|
302
|
+
await agent.destroy();
|
|
303
|
+
}
|
|
304
|
+
let status;
|
|
305
|
+
if (error) status = timedOut ? "timeout" : controller.signal.aborted ? "aborted" : "error";
|
|
306
|
+
else if (controller.signal.aborted) status = timedOut ? "timeout" : "aborted";
|
|
307
|
+
else status = "completed";
|
|
308
|
+
const rawTranscript = session.turns.slice();
|
|
309
|
+
const transcript = opts.includeThinking === false ? stripThinking(rawTranscript) : rawTranscript;
|
|
310
|
+
const summary = collector.latest();
|
|
311
|
+
const result = {
|
|
312
|
+
status,
|
|
313
|
+
finalText: extractFinalText(rawTranscript),
|
|
314
|
+
...stats?.output ? { output: stats.output } : {},
|
|
315
|
+
usage: {
|
|
316
|
+
input: stats?.totalIn ?? 0,
|
|
317
|
+
output: stats?.totalOut ?? 0,
|
|
318
|
+
cacheRead: stats?.totalCacheRead ?? 0,
|
|
319
|
+
cacheCreation: stats?.totalCacheCreation ?? 0,
|
|
320
|
+
...typeof stats?.cost === "number" ? { cost: stats.cost } : {}
|
|
321
|
+
},
|
|
322
|
+
turns: stats?.turns ?? 0,
|
|
323
|
+
durationMs: stats?.elapsed ?? Date.now() - startedAt,
|
|
324
|
+
numToolCalls: countToolCalls(rawTranscript),
|
|
325
|
+
...lastFinishReason(stats) ? { finishReason: lastFinishReason(stats) } : {},
|
|
326
|
+
...error ? { error } : {},
|
|
327
|
+
sessionId: session.id,
|
|
328
|
+
...summary ? { summary } : {},
|
|
329
|
+
transcript
|
|
330
|
+
};
|
|
331
|
+
opts.onEvent?.({
|
|
332
|
+
type: "result",
|
|
333
|
+
result
|
|
334
|
+
});
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Convert raw `session.turns` into standard OpenAI chat-completion messages:
|
|
339
|
+
* assistant turns carry `tool_calls`, and each `tool_result` becomes its own
|
|
340
|
+
* `role: 'tool'` message. This is the drop-in shape for an SFT renderer —
|
|
341
|
+
* unlike `toOpenAI` (session/messages.ts), which emits an internal `_tag`
|
|
342
|
+
* envelope meant for re-sending to a provider, not for training data.
|
|
343
|
+
*/
|
|
344
|
+
function transcriptToOpenAIMessages(turns) {
|
|
345
|
+
const messages = [];
|
|
346
|
+
for (const turn of turns) {
|
|
347
|
+
const text = textOf(turn.content);
|
|
348
|
+
if (turn.role === "system") {
|
|
349
|
+
messages.push({
|
|
350
|
+
role: "system",
|
|
351
|
+
content: text
|
|
352
|
+
});
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (turn.role === "assistant") {
|
|
356
|
+
const toolCalls = turn.content.filter((b) => b.type === "tool_call");
|
|
357
|
+
const msg = {
|
|
358
|
+
role: "assistant",
|
|
359
|
+
content: text || null
|
|
360
|
+
};
|
|
361
|
+
if (toolCalls.length > 0) msg.tool_calls = toolCalls.map((b) => ({
|
|
362
|
+
id: b.id,
|
|
363
|
+
type: "function",
|
|
364
|
+
function: {
|
|
365
|
+
name: b.name,
|
|
366
|
+
arguments: JSON.stringify(b.input)
|
|
367
|
+
}
|
|
368
|
+
}));
|
|
369
|
+
messages.push(msg);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
if (text) messages.push({
|
|
373
|
+
role: "user",
|
|
374
|
+
content: text
|
|
375
|
+
});
|
|
376
|
+
for (const tr of turn.content.filter((b) => b.type === "tool_result")) messages.push({
|
|
377
|
+
role: "tool",
|
|
378
|
+
tool_call_id: tr.callId,
|
|
379
|
+
content: toolResultToText(tr.output)
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
return messages;
|
|
383
|
+
}
|
|
384
|
+
function noop() {}
|
|
385
|
+
function textOf(content) {
|
|
386
|
+
return content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
387
|
+
}
|
|
388
|
+
function extractFinalText(turns) {
|
|
389
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
390
|
+
const turn = turns[i];
|
|
391
|
+
if (turn.role !== "assistant") continue;
|
|
392
|
+
const text = textOf(turn.content);
|
|
393
|
+
if (text) return text;
|
|
394
|
+
}
|
|
395
|
+
return "";
|
|
396
|
+
}
|
|
397
|
+
function countToolCalls(turns) {
|
|
398
|
+
let n = 0;
|
|
399
|
+
for (const turn of turns) for (const block of turn.content) if (block.type === "tool_call") n++;
|
|
400
|
+
return n;
|
|
401
|
+
}
|
|
402
|
+
function lastFinishReason(stats) {
|
|
403
|
+
const usages = stats?.turnUsage;
|
|
404
|
+
if (!usages) return void 0;
|
|
405
|
+
for (let i = usages.length - 1; i >= 0; i--) if (usages[i].finishReason) return usages[i].finishReason;
|
|
406
|
+
}
|
|
407
|
+
function stripThinking(turns) {
|
|
408
|
+
return turns.map((turn) => ({
|
|
409
|
+
...turn,
|
|
410
|
+
content: turn.content.filter((b) => b.type !== "thinking" && b.type !== "redacted_thinking")
|
|
411
|
+
}));
|
|
412
|
+
}
|
|
413
|
+
function installEventAdapter(hooks, onEvent) {
|
|
414
|
+
const unregs = [];
|
|
415
|
+
const emit = (event) => {
|
|
416
|
+
try {
|
|
417
|
+
onEvent(event);
|
|
418
|
+
} catch {}
|
|
419
|
+
};
|
|
420
|
+
unregs.push(hooks.hook("agent:start", (ctx) => emit({
|
|
421
|
+
type: "start",
|
|
422
|
+
runId: ctx.runId,
|
|
423
|
+
...ctx.providerName ? { provider: ctx.providerName } : {}
|
|
424
|
+
})));
|
|
425
|
+
unregs.push(hooks.hook("stream:text", (ctx) => emit({
|
|
426
|
+
type: "text",
|
|
427
|
+
delta: ctx.delta
|
|
428
|
+
})));
|
|
429
|
+
unregs.push(hooks.hook("stream:thinking", (ctx) => emit({
|
|
430
|
+
type: "thinking",
|
|
431
|
+
delta: ctx.delta
|
|
432
|
+
})));
|
|
433
|
+
unregs.push(hooks.hook("tool:before", (ctx) => emit({
|
|
434
|
+
type: "tool_call",
|
|
435
|
+
callId: ctx.callId,
|
|
436
|
+
name: ctx.name,
|
|
437
|
+
input: ctx.input
|
|
438
|
+
})));
|
|
439
|
+
unregs.push(hooks.hook("tool:after", (ctx) => emit({
|
|
440
|
+
type: "tool_result",
|
|
441
|
+
callId: ctx.callId,
|
|
442
|
+
name: ctx.name,
|
|
443
|
+
output: toolResultToText(ctx.result),
|
|
444
|
+
isError: false
|
|
445
|
+
})));
|
|
446
|
+
unregs.push(hooks.hook("tool:error", (ctx) => emit({
|
|
447
|
+
type: "tool_result",
|
|
448
|
+
callId: ctx.callId,
|
|
449
|
+
name: ctx.name,
|
|
450
|
+
output: ctx.error.message,
|
|
451
|
+
isError: true
|
|
452
|
+
})));
|
|
453
|
+
unregs.push(hooks.hook("turn:after", (ctx) => emit({
|
|
454
|
+
type: "turn",
|
|
455
|
+
index: ctx.turn,
|
|
456
|
+
usage: ctx.usage
|
|
457
|
+
})));
|
|
458
|
+
unregs.push(hooks.hook("spawn:before", (ctx) => emit({
|
|
459
|
+
type: "spawn",
|
|
460
|
+
event: "before",
|
|
461
|
+
id: ctx.id
|
|
462
|
+
})));
|
|
463
|
+
unregs.push(hooks.hook("spawn:complete", (ctx) => emit({
|
|
464
|
+
type: "spawn",
|
|
465
|
+
event: "complete",
|
|
466
|
+
id: ctx.id,
|
|
467
|
+
info: { status: ctx.status ?? "completed" }
|
|
468
|
+
})));
|
|
469
|
+
unregs.push(hooks.hook("spawn:error", (ctx) => emit({
|
|
470
|
+
type: "spawn",
|
|
471
|
+
event: "error",
|
|
472
|
+
id: ctx.id,
|
|
473
|
+
info: { message: ctx.error.message }
|
|
474
|
+
})));
|
|
475
|
+
unregs.push(hooks.hook("stream:error", (ctx) => emit({
|
|
476
|
+
type: "error",
|
|
477
|
+
message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),
|
|
478
|
+
...ctx.err instanceof Error ? { errorType: ctx.err.name } : {}
|
|
479
|
+
})));
|
|
480
|
+
return () => {
|
|
481
|
+
for (const un of unregs) try {
|
|
482
|
+
un();
|
|
483
|
+
} catch {}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
487
|
+
export { createRunSummaryCollector as i, runHeadless as n, transcriptToOpenAIMessages as r, headlessEventToJsonl as t };
|
|
488
|
+
|
|
489
|
+
//# sourceMappingURL=headless-CEtk5dzV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-CEtk5dzV.js","names":["basic"],"sources":["../src/run-summary.ts","../src/headless.ts"],"sourcesContent":["/**\n * Run summary collector — one JSON postmortem per `agent.run()`.\n *\n * `AgentStats` is great for billing and per-turn accounting but doesn't\n * carry a record of the *interesting* events that happened during a run\n * (errors, gate blocks, validation rejects, budget hits, MCP failures).\n * Reconstructing that from a hook stream after the fact is exactly the\n * kind of plumbing every consumer ends up re-implementing.\n *\n * This module ships:\n *\n * - {@link RunSummary} — a serializable shape that bundles totals,\n * per-model breakdown, and all the per-run incident lists.\n * - {@link createRunSummaryCollector} — installs hook listeners that\n * build up a {@link RunSummary} during the run and surfaces it on\n * `agent:done`. Calls an optional `onSummary` callback so the host can\n * forward to a log aggregator / DB / postmortem dashboard without\n * touching `agent.run()`'s return value.\n *\n * The collector is purely additive — it doesn't touch the agent loop,\n * doesn't change return shapes, and doesn't suppress any other hook\n * handlers. Drop it in alongside tracing / metrics / logging or use it\n * standalone when you only need the summary.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from './agent'\nimport type { AgentStats } from './types'\nimport { statsByModel } from './stats'\n\n// ---------------------------------------------------------------------------\n// Public shape\n// ---------------------------------------------------------------------------\n\nexport interface RunSummaryTokens {\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n cost?: number\n /** First observable byte from the provider, ms from run start. */\n ttftMs?: number\n}\n\nexport interface RunSummaryByModel {\n modelId: string\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n cost: number\n turns: number\n}\n\nexport interface RunSummaryError {\n kind: 'stream' | 'tool' | 'mcp-tool' | 'mcp' | 'spawn'\n message: string\n errorType?: string\n turnId?: string\n callId?: string\n server?: string\n toolName?: string\n childId?: string\n statusCode?: number\n requestId?: string\n}\n\nexport interface RunSummaryBlock {\n callId: string\n toolName: string\n outcome: 'gate-block' | 'unknown' | 'invalid-input'\n reason?: string\n}\n\nexport interface RunSummaryValidation {\n callId: string\n toolName: string\n reason: string\n}\n\nexport interface RunSummaryBudget {\n kind: 'bytes' | 'tool-count'\n /** Tool name (for `'tool-count'`); absent for byte budgets. */\n toolName?: string\n /** `mode` for `'tool-count'`; absent for byte budgets. */\n mode?: 'steer' | 'block'\n observed: number\n limit: number\n turnId?: string\n}\n\n/**\n * Postmortem snapshot of one `agent.run()`. Strictly serializable — every\n * field round-trips through `JSON.stringify` / `JSON.parse` without loss\n * so a log aggregator can ingest it as-is.\n */\nexport interface RunSummary {\n runId?: string\n parentRunId?: string\n depth: number\n agentName?: string\n startedAt: number\n endedAt: number\n durationMs: number\n status: 'completed' | 'aborted'\n turns: number\n totals: RunSummaryTokens\n byModel: RunSummaryByModel[]\n errors: RunSummaryError[]\n blocks: RunSummaryBlock[]\n validationRejects: RunSummaryValidation[]\n budgetEvents: RunSummaryBudget[]\n /** Counts of pairing repairs, keyed by repair mode. */\n pairingRepairs: Record<string, number>\n /**\n * Postmortem snapshots of child runs that bubbled their stats up via\n * `spawn:complete`. Only present when the run actually spawned.\n */\n children?: RunSummary[]\n}\n\n// ---------------------------------------------------------------------------\n// Collector\n// ---------------------------------------------------------------------------\n\nexport interface RunSummaryCollectorOptions {\n /**\n * Called with the assembled {@link RunSummary} on every `agent:done`.\n * Synchronous — heavy I/O should be deferred (e.g. via `setImmediate`).\n */\n onSummary?: (summary: RunSummary) => void\n}\n\nexport interface RunSummaryCollector {\n /** Install the collector's hook handlers. Returns an uninstall fn. */\n install: (hooks: Hookable<AgentHooks>) => () => void\n /** Most-recent summary; `undefined` until the first `agent:done` fires. */\n latest: () => RunSummary | undefined\n}\n\n/**\n * Build a run-summary collector. State is created fresh inside each\n * `install()` call, so a single collector instance can be installed\n * across multiple agents without attribution cross-talk. `latest()`\n * returns the most-recent summary across **any** install — install\n * per-agent collectors if you need separate post-run snapshots.\n *\n * @example\n * ```ts\n * const collector = createRunSummaryCollector({\n * onSummary: s => console.log(JSON.stringify(s)),\n * })\n * const uninstall = collector.install(agent.hooks)\n * try { await agent.run({ prompt }) }\n * finally { uninstall() }\n * ```\n */\nexport function createRunSummaryCollector(\n options: RunSummaryCollectorOptions = {},\n): RunSummaryCollector {\n let last: RunSummary | undefined\n\n return {\n latest: () => last,\n install(hooks: Hookable<AgentHooks>): () => void {\n // Per-run in-progress accumulators. The hookable bus serializes\n // agent.run lifecycles per agent — we reset between runs on\n // `agent:start` and consume on `agent:done`.\n let runId: string | undefined\n let parentRunId: string | undefined\n let depth = 0\n let agentName: string | undefined\n let startedAt = Date.now()\n let aborted = false\n const errors: RunSummaryError[] = []\n const blocks: RunSummaryBlock[] = []\n const validationRejects: RunSummaryValidation[] = []\n const budgetEvents: RunSummaryBudget[] = []\n const pairingRepairs: Record<string, number> = {}\n const children: RunSummary[] = []\n\n function resetForNewRun(): void {\n aborted = false\n errors.length = 0\n blocks.length = 0\n validationRejects.length = 0\n budgetEvents.length = 0\n for (const k of Object.keys(pairingRepairs))\n delete pairingRepairs[k]\n children.length = 0\n }\n\n const unregisters: Array<() => void> = []\n\n unregisters.push(hooks.hook('agent:start', (ctx) => {\n resetForNewRun()\n runId = ctx.runId\n parentRunId = ctx.parentRunId\n depth = ctx.depth\n agentName = ctx.agentName\n startedAt = ctx.startedAt\n }))\n\n unregisters.push(hooks.hook('agent:abort', () => {\n aborted = true\n }))\n\n unregisters.push(hooks.hook('stream:error', (ctx) => {\n const msg = ctx.err instanceof Error ? ctx.err.message : String(ctx.err)\n const errorType = ctx.err instanceof Error ? ctx.err.name : 'unknown'\n errors.push({\n kind: 'stream',\n message: msg,\n errorType,\n turnId: ctx.turnId,\n ...(ctx.statusCode !== undefined ? { statusCode: ctx.statusCode } : {}),\n ...(ctx.requestId !== undefined ? { requestId: ctx.requestId } : {}),\n })\n }))\n\n unregisters.push(hooks.hook('tool:error', (ctx) => {\n errors.push({\n kind: 'tool',\n message: ctx.error.message,\n errorType: ctx.error.name,\n turnId: ctx.turnId,\n callId: ctx.callId,\n toolName: ctx.name,\n })\n }))\n\n unregisters.push(hooks.hook('mcp:tool:error', (ctx) => {\n errors.push({\n kind: 'mcp-tool',\n message: ctx.error.message,\n errorType: ctx.error.name,\n turnId: ctx.turnId,\n callId: ctx.callId,\n server: ctx.server,\n toolName: ctx.displayName,\n })\n }))\n\n unregisters.push(hooks.hook('mcp:error', (ctx) => {\n errors.push({\n kind: 'mcp',\n message: ctx.error.message,\n errorType: ctx.error.name,\n server: ctx.name,\n })\n }))\n\n unregisters.push(hooks.hook('spawn:error', (ctx) => {\n errors.push({\n kind: 'spawn',\n message: ctx.error.message,\n errorType: ctx.error.name,\n childId: ctx.id,\n })\n }))\n\n unregisters.push(hooks.hook('tool:dispatched', (ctx) => {\n if (ctx.outcome === 'gate-block' || ctx.outcome === 'unknown' || ctx.outcome === 'invalid-input') {\n blocks.push({\n callId: ctx.callId,\n toolName: ctx.name,\n outcome: ctx.outcome,\n ...(ctx.reason ? { reason: ctx.reason } : {}),\n })\n }\n }))\n\n unregisters.push(hooks.hook('validation:reject', (ctx) => {\n validationRejects.push({\n callId: ctx.callId,\n toolName: ctx.name,\n reason: ctx.reason,\n })\n }))\n\n unregisters.push(hooks.hook('budget:exceeded', (ctx) => {\n budgetEvents.push({\n kind: 'bytes',\n observed: ctx.bytes,\n limit: ctx.budget,\n turnId: ctx.turnId,\n })\n }))\n\n unregisters.push(hooks.hook('tool-budget:exceeded', (ctx) => {\n budgetEvents.push({\n kind: 'tool-count',\n toolName: ctx.tool,\n mode: ctx.mode,\n observed: ctx.count,\n limit: ctx.max,\n turnId: ctx.turnId,\n })\n }))\n\n unregisters.push(hooks.hook('pairing:repair', (ctx) => {\n pairingRepairs[ctx.mode] = (pairingRepairs[ctx.mode] ?? 0) + 1\n }))\n\n unregisters.push(hooks.hook('agent:done', (stats) => {\n const endedAt = Date.now()\n\n // Build per-model rollup via the existing `statsByModel` helper\n // so we stay in lockstep with how the rest of the harness\n // attributes cost and tokens by model id.\n const byModel: RunSummaryByModel[] = []\n for (const [modelId, usage] of statsByModel(stats)) {\n byModel.push({\n modelId,\n input: usage.input,\n output: usage.output,\n cacheRead: usage.cacheRead,\n cacheCreation: usage.cacheCreation,\n cost: usage.cost,\n turns: usage.turns,\n })\n }\n\n // Flatten child stats into nested summaries. We don't have the\n // child's full event lists here (those landed on the child's\n // own hooks), so the nested entry is a minimal totals-only\n // record — enough for a flat per-run audit trail; consumers\n // wanting full per-child event lists install a collector on\n // each subagent.\n for (const c of stats.children ?? []) {\n children.push(minimalSummaryFromStats(c.stats, {\n depth: c.depth ?? depth + 1,\n status: c.status === 'aborted' ? 'aborted' : 'completed',\n }))\n }\n\n const summary: RunSummary = {\n ...(runId ? { runId } : {}),\n ...(parentRunId ? { parentRunId } : {}),\n depth,\n ...(agentName ? { agentName } : {}),\n startedAt,\n endedAt,\n durationMs: endedAt - startedAt,\n status: aborted ? 'aborted' : 'completed',\n turns: stats.turns,\n totals: buildTotals(stats),\n byModel,\n errors: errors.slice(),\n blocks: blocks.slice(),\n validationRejects: validationRejects.slice(),\n budgetEvents: budgetEvents.slice(),\n pairingRepairs: { ...pairingRepairs },\n ...(children.length > 0 ? { children: children.slice() } : {}),\n }\n\n last = summary\n try {\n options.onSummary?.(summary)\n }\n catch {\n // Sink errors are not the collector's concern.\n }\n }))\n\n let disposed = false\n return function uninstall() {\n if (disposed)\n return\n disposed = true\n for (const un of unregisters) {\n try {\n un()\n }\n catch { /* ignore */ }\n }\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildTotals(stats: AgentStats): RunSummaryTokens {\n return {\n input: stats.totalIn,\n output: stats.totalOut,\n cacheRead: stats.totalCacheRead,\n cacheCreation: stats.totalCacheCreation,\n ...(typeof stats.cost === 'number' ? { cost: stats.cost } : {}),\n ...(typeof stats.timeTillFirstTokenMs === 'number' ? { ttftMs: stats.timeTillFirstTokenMs } : {}),\n }\n}\n\nfunction minimalSummaryFromStats(\n stats: AgentStats,\n meta: { depth: number, status: 'completed' | 'aborted' },\n): RunSummary {\n const byModel: RunSummaryByModel[] = []\n for (const [modelId, usage] of statsByModel(stats)) {\n byModel.push({\n modelId,\n input: usage.input,\n output: usage.output,\n cacheRead: usage.cacheRead,\n cacheCreation: usage.cacheCreation,\n cost: usage.cost,\n turns: usage.turns,\n })\n }\n const children: RunSummary[] = []\n for (const c of stats.children ?? []) {\n children.push(minimalSummaryFromStats(c.stats, {\n depth: c.depth ?? meta.depth + 1,\n status: c.status === 'aborted' ? 'aborted' : 'completed',\n }))\n }\n return {\n depth: meta.depth,\n startedAt: 0,\n endedAt: 0,\n durationMs: stats.elapsed,\n status: meta.status,\n turns: stats.turns,\n totals: buildTotals(stats),\n byModel,\n errors: [],\n blocks: [],\n validationRejects: [],\n budgetEvents: [],\n pairingRepairs: {},\n ...(children.length > 0 ? { children } : {}),\n }\n}\n","/**\n * Headless mode — a non-interactive, fully-structured way to drive the agent\n * for automation and RL rollouts.\n *\n * `agent.run()` already returns rich {@link AgentStats}, the session captures a\n * lossless transcript (`session.turns`), and the hook bus exposes every\n * streaming/tool/turn event. What this module adds is the *contract* an RL loop\n * needs: one call (`runHeadless`) that runs a prompt to completion in a chosen\n * workdir, bounded by turns + wall-clock, and hands back a single serializable\n * {@link HeadlessResult} — final answer, verifiable structured output, usage,\n * and the complete trajectory — plus an optional live {@link HeadlessEvent}\n * stream (the in-process equivalent of `--output-format stream-json`).\n *\n * It is provider-agnostic: the caller passes a built {@link Provider} (e.g.\n * `local()` pointed at a vLLM server, or any of the named providers). The thin\n * CLI in `src/headless-cli.ts` wraps this with arg parsing, file/stdin I/O, and\n * JSONL transcript writing.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks, AgentOptions } from './agent'\nimport type { ExecutionContext } from './contexts'\nimport type { Provider } from './providers'\nimport type { RunSummary } from './run-summary'\nimport type { Session, SessionStore } from './session'\nimport type { ToolDef } from './tools'\nimport type {\n AgentStats,\n McpServerConfig,\n PromptPart,\n SessionContentBlock,\n SessionTurn,\n ThinkingLevel,\n TurnFinishReason,\n TurnUsage,\n} from './types'\nimport { createAgent } from './agent'\nimport { createProcessContext } from './contexts'\nimport { basic } from './presets'\nimport { createRunSummaryCollector } from './run-summary'\nimport { createMemoryStore, createSession } from './session'\nimport { toolResultToText } from './types'\n\n// ---------------------------------------------------------------------------\n// Public shapes\n// ---------------------------------------------------------------------------\n\nexport type HeadlessStatus = 'completed' | 'aborted' | 'error' | 'timeout'\n\nexport interface HeadlessUsage {\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n /** Cumulative USD cost when the provider/registry could price the run. */\n cost?: number\n}\n\nexport interface HeadlessErrorInfo {\n message: string\n /** Typed-error class name (`AgentAbortedError`, `AgentContextExceededError`, …). */\n type: string\n}\n\n/**\n * Strictly JSON-serializable postmortem of one headless run. Everything an RL\n * reward function needs: the final answer (`finalText`), the verifiable\n * structured output (`output`, present iff a `schema` was set), usage/turns,\n * and the lossless `transcript` (the SFT training data).\n */\nexport interface HeadlessResult {\n status: HeadlessStatus\n /** Concatenated text of the last assistant turn that produced any text. */\n finalText: string\n /** Schema-enforced structured output (only when `opts.schema` is set). */\n output?: Record<string, unknown>\n usage: HeadlessUsage\n turns: number\n durationMs: number\n /** Total `tool_call` blocks across the whole transcript. */\n numToolCalls: number\n /** Finish reason of the final turn that reported one. */\n finishReason?: TurnFinishReason\n error?: HeadlessErrorInfo\n sessionId: string\n /** Incident postmortem (errors, gate blocks, budget events) via run-summary. */\n summary?: RunSummary\n /** Lossless transcript — raw `session.turns`. Thinking stripped when `includeThinking: false`. */\n transcript: SessionTurn[]\n}\n\n/**\n * Live event union — the in-process equivalent of a `stream-json` line. Every\n * member is JSON-serializable; render to JSONL with {@link headlessEventToJsonl}.\n */\nexport type HeadlessEvent\n = | { type: 'start', runId: string, provider?: string }\n | { type: 'text', delta: string }\n | { type: 'thinking', delta: string }\n | { type: 'tool_call', callId: string, name: string, input: Record<string, unknown> }\n | { type: 'tool_result', callId: string, name: string, output: string, isError: boolean }\n | { type: 'turn', index: number, usage: TurnUsage }\n | { type: 'spawn', event: 'before' | 'complete' | 'error', id: string, info?: Record<string, unknown> }\n | { type: 'error', message: string, errorType?: string }\n | { type: 'result', result: HeadlessResult }\n\n/** Serialize one event as a newline-terminated JSON line (stream-json). */\nexport function headlessEventToJsonl(event: HeadlessEvent): string {\n return `${JSON.stringify(event)}\\n`\n}\n\nexport interface HeadlessOptions {\n /** User prompt — plain string or multimodal `PromptPart[]`. */\n prompt: string | PromptPart[]\n /** Built provider (e.g. `local()`, `openaiCompat(...)`, `anthropic(...)`). */\n provider: Provider\n model?: string\n /** Override the preset system prompt for this run. */\n system?: string\n thinking?: ThinkingLevel\n maxTurns?: number\n maxTokens?: number\n /** Wall-clock cap; on expiry the run is aborted and `status` becomes `'timeout'`. */\n timeoutMs?: number\n /** External abort signal — chained with the internal timeout controller. */\n signal?: AbortSignal\n /** JSON Schema for structured-output enforcement → populates `result.output`. */\n schema?: Record<string, unknown>\n /** Tool overrides. Omit to use the basic preset's tools. */\n tools?: Record<string, ToolDef>\n mcpServers?: McpServerConfig[]\n skills?: AgentOptions['skills']\n /** Execution context. Defaults to a process context rooted at `cwd`. */\n execution?: ExecutionContext\n /** Working directory for the default process context (ignored if `execution` is set). */\n cwd?: string\n /** Reuse / resume an existing session. */\n session?: Session\n /** Session store for a fresh session (defaults to an in-memory store). */\n store?: SessionStore\n /** Keep `thinking` blocks in `result.transcript` (default true). */\n includeThinking?: boolean\n /** Live event callback — the in-process stream-json equivalent. */\n onEvent?: (event: HeadlessEvent) => void\n}\n\n// ---------------------------------------------------------------------------\n// runHeadless\n// ---------------------------------------------------------------------------\n\n/**\n * Run a prompt to completion, headless, and return a single serializable\n * {@link HeadlessResult}. Safe to call concurrently for parallel rollouts —\n * each call builds its own agent + session and tears them down in `finally`.\n */\nexport async function runHeadless(opts: HeadlessOptions): Promise<HeadlessResult> {\n const startedAt = Date.now()\n const execution = opts.execution ?? createProcessContext({ cwd: opts.cwd })\n const session = opts.session ?? await createSession({ store: opts.store ?? createMemoryStore() })\n\n const behavior: NonNullable<AgentOptions['behavior']> = {}\n if (opts.maxTurns !== undefined)\n behavior.maxTurns = opts.maxTurns\n if (opts.maxTokens !== undefined)\n behavior.maxTokens = opts.maxTokens\n if (opts.schema !== undefined)\n behavior.schema = opts.schema\n\n const agent = createAgent({\n ...basic,\n provider: opts.provider,\n execution,\n session,\n behavior,\n ...(opts.tools !== undefined ? { tools: opts.tools } : {}),\n ...(opts.mcpServers !== undefined ? { mcpServers: opts.mcpServers } : {}),\n ...(opts.skills !== undefined ? { skills: opts.skills } : {}),\n })\n\n const collector = createRunSummaryCollector()\n const uninstallSummary = collector.install(agent.hooks)\n const uninstallEvents = opts.onEvent ? installEventAdapter(agent.hooks, opts.onEvent) : noop\n\n // Internal controller drives the wall-clock timeout and chains any external\n // signal so a host cancel and a timeout both abort the same run.\n const controller = new AbortController()\n if (opts.signal) {\n if (opts.signal.aborted)\n controller.abort(opts.signal.reason)\n else\n opts.signal.addEventListener('abort', () => controller.abort(opts.signal!.reason), { once: true })\n }\n let timedOut = false\n const timer = opts.timeoutMs && opts.timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n controller.abort(new Error(`Headless run timed out after ${opts.timeoutMs}ms`))\n }, opts.timeoutMs)\n : undefined\n\n let stats: AgentStats | undefined\n let error: HeadlessErrorInfo | undefined\n\n try {\n stats = await agent.run({\n prompt: opts.prompt,\n signal: controller.signal,\n ...(opts.model !== undefined ? { model: opts.model } : {}),\n ...(opts.system !== undefined ? { system: opts.system } : {}),\n ...(opts.thinking !== undefined ? { thinking: opts.thinking } : {}),\n })\n }\n catch (err) {\n // The agent loop throws typed errors (AgentAbortedError,\n // AgentContextExceededError, AgentProviderError, …) — their `name` already\n // classifies the failure, so surface it directly.\n const e = err instanceof Error ? err : new Error(String(err))\n error = { message: e.message, type: e.name }\n }\n finally {\n if (timer)\n clearTimeout(timer)\n uninstallEvents()\n uninstallSummary()\n await agent.destroy()\n }\n\n // Status: a thrown error wins, but an abort/timeout can also surface as a\n // clean resolve (the loop returns partial stats), so check the signal too.\n let status: HeadlessStatus\n if (error)\n status = timedOut ? 'timeout' : controller.signal.aborted ? 'aborted' : 'error'\n else if (controller.signal.aborted)\n status = timedOut ? 'timeout' : 'aborted'\n else\n status = 'completed'\n\n const rawTranscript = session.turns.slice()\n const transcript = opts.includeThinking === false ? stripThinking(rawTranscript) : rawTranscript\n const summary = collector.latest()\n\n const result: HeadlessResult = {\n status,\n finalText: extractFinalText(rawTranscript),\n ...(stats?.output ? { output: stats.output } : {}),\n usage: {\n input: stats?.totalIn ?? 0,\n output: stats?.totalOut ?? 0,\n cacheRead: stats?.totalCacheRead ?? 0,\n cacheCreation: stats?.totalCacheCreation ?? 0,\n ...(typeof stats?.cost === 'number' ? { cost: stats.cost } : {}),\n },\n turns: stats?.turns ?? 0,\n durationMs: stats?.elapsed ?? (Date.now() - startedAt),\n numToolCalls: countToolCalls(rawTranscript),\n ...(lastFinishReason(stats) ? { finishReason: lastFinishReason(stats) } : {}),\n ...(error ? { error } : {}),\n sessionId: session.id,\n ...(summary ? { summary } : {}),\n transcript,\n }\n\n opts.onEvent?.({ type: 'result', result })\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Transcript → OpenAI chat messages (SFT-ready)\n// ---------------------------------------------------------------------------\n\nexport interface OpenAIChatMessage {\n role: 'system' | 'user' | 'assistant' | 'tool'\n content: string | null\n tool_calls?: Array<{ id: string, type: 'function', function: { name: string, arguments: string } }>\n tool_call_id?: string\n}\n\n/**\n * Convert raw `session.turns` into standard OpenAI chat-completion messages:\n * assistant turns carry `tool_calls`, and each `tool_result` becomes its own\n * `role: 'tool'` message. This is the drop-in shape for an SFT renderer —\n * unlike `toOpenAI` (session/messages.ts), which emits an internal `_tag`\n * envelope meant for re-sending to a provider, not for training data.\n */\nexport function transcriptToOpenAIMessages(turns: SessionTurn[]): OpenAIChatMessage[] {\n const messages: OpenAIChatMessage[] = []\n for (const turn of turns) {\n const text = textOf(turn.content)\n\n if (turn.role === 'system') {\n messages.push({ role: 'system', content: text })\n continue\n }\n\n if (turn.role === 'assistant') {\n const toolCalls = turn.content.filter((b): b is ToolCallBlock => b.type === 'tool_call')\n const msg: OpenAIChatMessage = { role: 'assistant', content: text || null }\n if (toolCalls.length > 0) {\n msg.tool_calls = toolCalls.map(b => ({\n id: b.id,\n type: 'function' as const,\n function: { name: b.name, arguments: JSON.stringify(b.input) },\n }))\n }\n messages.push(msg)\n continue\n }\n\n // user turn — may carry prompt text and/or tool_result blocks\n if (text)\n messages.push({ role: 'user', content: text })\n for (const tr of turn.content.filter((b): b is ToolResultBlock => b.type === 'tool_result'))\n messages.push({ role: 'tool', tool_call_id: tr.callId, content: toolResultToText(tr.output) })\n }\n return messages\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\ntype TextBlock = Extract<SessionContentBlock, { type: 'text' }>\ntype ToolCallBlock = Extract<SessionContentBlock, { type: 'tool_call' }>\ntype ToolResultBlock = Extract<SessionContentBlock, { type: 'tool_result' }>\n\nfunction noop(): void {}\n\nfunction textOf(content: SessionContentBlock[]): string {\n return content.filter((b): b is TextBlock => b.type === 'text').map(b => b.text).join('')\n}\n\nfunction extractFinalText(turns: SessionTurn[]): string {\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]\n if (turn.role !== 'assistant')\n continue\n const text = textOf(turn.content)\n if (text)\n return text\n }\n return ''\n}\n\nfunction countToolCalls(turns: SessionTurn[]): number {\n let n = 0\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n n++\n }\n }\n return n\n}\n\nfunction lastFinishReason(stats?: AgentStats): TurnFinishReason | undefined {\n const usages = stats?.turnUsage\n if (!usages)\n return undefined\n for (let i = usages.length - 1; i >= 0; i--) {\n if (usages[i].finishReason)\n return usages[i].finishReason\n }\n return undefined\n}\n\nfunction stripThinking(turns: SessionTurn[]): SessionTurn[] {\n return turns.map(turn => ({\n ...turn,\n content: turn.content.filter(b => b.type !== 'thinking' && b.type !== 'redacted_thinking'),\n }))\n}\n\nfunction installEventAdapter(\n hooks: Hookable<AgentHooks>,\n onEvent: (event: HeadlessEvent) => void,\n): () => void {\n const unregs: Array<() => void> = []\n const emit = (event: HeadlessEvent): void => {\n try {\n onEvent(event)\n }\n catch {\n // A consumer's sink throwing is not the adapter's concern.\n }\n }\n\n unregs.push(hooks.hook('agent:start', ctx => emit({\n type: 'start',\n runId: ctx.runId,\n ...(ctx.providerName ? { provider: ctx.providerName } : {}),\n })))\n unregs.push(hooks.hook('stream:text', ctx => emit({ type: 'text', delta: ctx.delta })))\n unregs.push(hooks.hook('stream:thinking', ctx => emit({ type: 'thinking', delta: ctx.delta })))\n unregs.push(hooks.hook('tool:before', ctx => emit({\n type: 'tool_call',\n callId: ctx.callId,\n name: ctx.name,\n input: ctx.input,\n })))\n unregs.push(hooks.hook('tool:after', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: toolResultToText(ctx.result),\n isError: false,\n })))\n unregs.push(hooks.hook('tool:error', ctx => emit({\n type: 'tool_result',\n callId: ctx.callId,\n name: ctx.name,\n output: ctx.error.message,\n isError: true,\n })))\n unregs.push(hooks.hook('turn:after', ctx => emit({ type: 'turn', index: ctx.turn, usage: ctx.usage })))\n unregs.push(hooks.hook('spawn:before', ctx => emit({ type: 'spawn', event: 'before', id: ctx.id })))\n unregs.push(hooks.hook('spawn:complete', ctx => emit({\n type: 'spawn',\n event: 'complete',\n id: ctx.id,\n info: { status: ctx.status ?? 'completed' },\n })))\n unregs.push(hooks.hook('spawn:error', ctx => emit({\n type: 'spawn',\n event: 'error',\n id: ctx.id,\n info: { message: ctx.error.message },\n })))\n unregs.push(hooks.hook('stream:error', ctx => emit({\n type: 'error',\n message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),\n ...(ctx.err instanceof Error ? { errorType: ctx.err.name } : {}),\n })))\n\n return () => {\n for (const un of unregs) {\n try {\n un()\n }\n catch {\n // ignore\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Ct as HeadlessUsage, Dt as transcriptToOpenAIMessages, Et as runHeadless, St as HeadlessStatus, Tt as headlessEventToJsonl, bt as HeadlessOptions, vt as HeadlessErrorInfo, wt as OpenAIChatMessage, xt as HeadlessResult, yt as HeadlessEvent } from "./index-DEqGfnZr.js";
|
|
2
|
+
export { HeadlessErrorInfo, HeadlessEvent, HeadlessOptions, HeadlessResult, HeadlessStatus, HeadlessUsage, OpenAIChatMessage, headlessEventToJsonl, runHeadless, transcriptToOpenAIMessages };
|
package/dist/headless.js
ADDED