@percena/weft 0.4.0-next.3 → 0.4.0-next.5
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/dist/action-bridge.cjs +172 -6
- package/dist/action-bridge.d.cts +112 -13
- package/dist/action-bridge.d.ts +112 -13
- package/dist/action-bridge.js +166 -4
- package/dist/chat.cjs +982 -3
- package/dist/chat.d.cts +30 -1
- package/dist/chat.d.ts +30 -1
- package/dist/chat.js +981 -2
- package/dist/index.cjs +341 -1616
- package/dist/index.d.cts +4 -274
- package/dist/index.d.ts +4 -274
- package/dist/index.js +174 -1408
- package/dist/styles/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Main-Bold.woff +0 -0
- package/dist/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/dist/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Main-Italic.woff +0 -0
- package/dist/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Main-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/dist/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Math-Italic.woff +0 -0
- package/dist/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Script-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/styles/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/dist/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/package.json +2 -30
- package/dist/local-runtime.cjs +0 -1387
- package/dist/local-runtime.d.cts +0 -3314
- package/dist/local-runtime.d.ts +0 -3314
- package/dist/local-runtime.js +0 -1345
- package/dist/skills-browser.cjs +0 -118
- package/dist/skills-browser.d.cts +0 -105
- package/dist/skills-browser.d.ts +0 -105
- package/dist/skills-browser.js +0 -88
package/dist/local-runtime.js
DELETED
|
@@ -1,1345 +0,0 @@
|
|
|
1
|
-
// ../packages/timeline/dist/index.js
|
|
2
|
-
function createTimelineSequencer(options) {
|
|
3
|
-
let seq = options.startSeq ?? 0;
|
|
4
|
-
const now = options.now ?? Date.now;
|
|
5
|
-
return {
|
|
6
|
-
append(item, rawRef) {
|
|
7
|
-
seq += 1;
|
|
8
|
-
return appendTimelineItem({
|
|
9
|
-
sessionId: options.sessionId,
|
|
10
|
-
provider: options.provider,
|
|
11
|
-
epoch: options.epoch,
|
|
12
|
-
seq,
|
|
13
|
-
timestamp: now(),
|
|
14
|
-
item,
|
|
15
|
-
rawRef
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function appendTimelineItem(envelope) {
|
|
21
|
-
return {
|
|
22
|
-
...envelope,
|
|
23
|
-
rawRef: envelope.rawRef ? { ...envelope.rawRef } : void 0
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// ../packages/runtime-core/dist/index.js
|
|
28
|
-
var initialRuntimeState = {
|
|
29
|
-
status: "idle",
|
|
30
|
-
acceptedMessages: [],
|
|
31
|
-
queuedMessages: []
|
|
32
|
-
};
|
|
33
|
-
function reduceRuntimeState(state = initialRuntimeState, action) {
|
|
34
|
-
switch (action.type) {
|
|
35
|
-
case "preflight_start":
|
|
36
|
-
return { ...state, status: "preflighting", lastError: void 0 };
|
|
37
|
-
case "preflight_ok":
|
|
38
|
-
return { ...state, status: "ready", lastError: void 0 };
|
|
39
|
-
case "preflight_error":
|
|
40
|
-
return { ...state, status: "failed", lastError: action.error };
|
|
41
|
-
case "starting":
|
|
42
|
-
if (state.status === "ready" || state.status === "idle") {
|
|
43
|
-
return { ...state, status: "starting" };
|
|
44
|
-
}
|
|
45
|
-
return state;
|
|
46
|
-
case "send_message":
|
|
47
|
-
if (state.status === "running" || state.status === "waiting_for_permission") {
|
|
48
|
-
return {
|
|
49
|
-
...state,
|
|
50
|
-
queuedMessages: [...state.queuedMessages, action.message]
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
...state,
|
|
55
|
-
status: "running",
|
|
56
|
-
acceptedMessages: [...state.acceptedMessages, action.message]
|
|
57
|
-
};
|
|
58
|
-
case "permission_request":
|
|
59
|
-
return {
|
|
60
|
-
...state,
|
|
61
|
-
status: "waiting_for_permission",
|
|
62
|
-
waitingPermissionRequestId: action.requestId
|
|
63
|
-
};
|
|
64
|
-
case "permission_response":
|
|
65
|
-
return {
|
|
66
|
-
...state,
|
|
67
|
-
status: "running",
|
|
68
|
-
waitingPermissionRequestId: void 0
|
|
69
|
-
};
|
|
70
|
-
case "turn_completed":
|
|
71
|
-
if (state.status === "running") {
|
|
72
|
-
return { ...state, status: "turn_completed" };
|
|
73
|
-
}
|
|
74
|
-
return state;
|
|
75
|
-
case "complete": {
|
|
76
|
-
if (state.status === "turn_completed") {
|
|
77
|
-
const [nextMessage2, ...remaining2] = state.queuedMessages;
|
|
78
|
-
if (nextMessage2) {
|
|
79
|
-
return {
|
|
80
|
-
...state,
|
|
81
|
-
status: "running",
|
|
82
|
-
acceptedMessages: [...state.acceptedMessages, nextMessage2],
|
|
83
|
-
queuedMessages: remaining2
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return { ...state, status: "ready" };
|
|
87
|
-
}
|
|
88
|
-
const [nextMessage, ...remaining] = state.queuedMessages;
|
|
89
|
-
if (nextMessage) {
|
|
90
|
-
return {
|
|
91
|
-
...state,
|
|
92
|
-
status: "running",
|
|
93
|
-
acceptedMessages: [...state.acceptedMessages, nextMessage],
|
|
94
|
-
queuedMessages: remaining
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return { ...state, status: "ready" };
|
|
98
|
-
}
|
|
99
|
-
case "abort":
|
|
100
|
-
return {
|
|
101
|
-
...state,
|
|
102
|
-
status: "ready",
|
|
103
|
-
lastError: action.reason,
|
|
104
|
-
queuedMessages: [],
|
|
105
|
-
waitingPermissionRequestId: void 0
|
|
106
|
-
};
|
|
107
|
-
case "error":
|
|
108
|
-
return { ...state, status: "failed", lastError: action.error };
|
|
109
|
-
case "dispose":
|
|
110
|
-
return {
|
|
111
|
-
...state,
|
|
112
|
-
status: "disposed",
|
|
113
|
-
queuedMessages: [],
|
|
114
|
-
waitingPermissionRequestId: void 0
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ../packages/local-runtime/dist/chunk-BGP42L4K.js
|
|
120
|
-
var PushAgentEventStream = class {
|
|
121
|
-
connected = false;
|
|
122
|
-
listeners = null;
|
|
123
|
-
connect(onEvent, onError, onClose) {
|
|
124
|
-
this.listeners = { onEvent, onError, onClose };
|
|
125
|
-
this.connected = true;
|
|
126
|
-
}
|
|
127
|
-
disconnect() {
|
|
128
|
-
this.listeners = null;
|
|
129
|
-
this.connected = false;
|
|
130
|
-
}
|
|
131
|
-
isConnected() {
|
|
132
|
-
return this.connected;
|
|
133
|
-
}
|
|
134
|
-
emit(event) {
|
|
135
|
-
this.listeners?.onEvent(event);
|
|
136
|
-
}
|
|
137
|
-
fail(error) {
|
|
138
|
-
this.listeners?.onError?.(error);
|
|
139
|
-
}
|
|
140
|
-
close() {
|
|
141
|
-
this.connected = false;
|
|
142
|
-
this.listeners?.onClose?.();
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
function parseJsonLine(line) {
|
|
146
|
-
const trimmed = line.trim();
|
|
147
|
-
if (!trimmed) return null;
|
|
148
|
-
try {
|
|
149
|
-
return JSON.parse(trimmed);
|
|
150
|
-
} catch {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
function asRecord(value) {
|
|
155
|
-
return value && typeof value === "object" ? value : {};
|
|
156
|
-
}
|
|
157
|
-
function getText(value) {
|
|
158
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
159
|
-
}
|
|
160
|
-
function normalizeUsage(raw) {
|
|
161
|
-
const inputTokens = typeof raw.input_tokens === "number" ? raw.input_tokens : typeof raw.inputTokens === "number" ? raw.inputTokens : 0;
|
|
162
|
-
const outputTokens = typeof raw.output_tokens === "number" ? raw.output_tokens : typeof raw.outputTokens === "number" ? raw.outputTokens : 0;
|
|
163
|
-
return { inputTokens, outputTokens };
|
|
164
|
-
}
|
|
165
|
-
function mapClaudeStreamJsonLine(line) {
|
|
166
|
-
const payload = asRecord(parseJsonLine(line));
|
|
167
|
-
const type = getText(payload.type);
|
|
168
|
-
if (!type) return [];
|
|
169
|
-
if (type === "system" && payload.subtype === "init") {
|
|
170
|
-
return [{ type: "status", message: "Claude session initialized" }];
|
|
171
|
-
}
|
|
172
|
-
if (type === "stream_event") {
|
|
173
|
-
const event = asRecord(payload.event);
|
|
174
|
-
if (event.type === "content_block_delta") {
|
|
175
|
-
const delta = asRecord(event.delta);
|
|
176
|
-
const text = getText(delta.text);
|
|
177
|
-
if (text) {
|
|
178
|
-
return [{
|
|
179
|
-
type: "text_delta",
|
|
180
|
-
text,
|
|
181
|
-
turnId: getText(asRecord(payload.message).id) ?? getText(payload.message_id) ?? "msg_1"
|
|
182
|
-
}];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return [];
|
|
186
|
-
}
|
|
187
|
-
if (type === "assistant") {
|
|
188
|
-
const message = asRecord(payload.message);
|
|
189
|
-
const turnId = getText(message.id);
|
|
190
|
-
const content = Array.isArray(message.content) ? message.content.map(asRecord) : [];
|
|
191
|
-
const events = [];
|
|
192
|
-
for (const item of content) {
|
|
193
|
-
if (item.type === "tool_use") {
|
|
194
|
-
const toolUseId = getText(item.id);
|
|
195
|
-
const toolName = getText(item.name);
|
|
196
|
-
if (toolUseId && toolName) {
|
|
197
|
-
events.push({
|
|
198
|
-
type: "tool_start",
|
|
199
|
-
toolName,
|
|
200
|
-
toolUseId,
|
|
201
|
-
input: asRecord(item.input),
|
|
202
|
-
turnId
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
} else if (item.type === "text") {
|
|
206
|
-
const text = getText(item.text);
|
|
207
|
-
if (text) {
|
|
208
|
-
events.push({
|
|
209
|
-
type: "text_complete",
|
|
210
|
-
text,
|
|
211
|
-
isIntermediate: message.stop_reason === "tool_use",
|
|
212
|
-
turnId
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return events;
|
|
218
|
-
}
|
|
219
|
-
if (type === "result") {
|
|
220
|
-
if (payload.subtype && payload.subtype !== "success") {
|
|
221
|
-
return [{ type: "error", message: `Claude finished with ${String(payload.subtype)}` }, { type: "complete" }];
|
|
222
|
-
}
|
|
223
|
-
return [{ type: "complete", usage: normalizeUsage(asRecord(payload.usage)) }];
|
|
224
|
-
}
|
|
225
|
-
if (type === "error") {
|
|
226
|
-
return [{ type: "error", message: getText(payload.message) ?? "Claude stream error" }];
|
|
227
|
-
}
|
|
228
|
-
return [];
|
|
229
|
-
}
|
|
230
|
-
function mapCodexExecJsonLine(line) {
|
|
231
|
-
const payload = asRecord(parseJsonLine(line));
|
|
232
|
-
const type = getText(payload.type);
|
|
233
|
-
if (!type) return [];
|
|
234
|
-
if (type === "session.started" || type === "session_started" || type === "thread.started" || type === "thread_started") {
|
|
235
|
-
return [{ type: "status", message: "Codex session initialized" }];
|
|
236
|
-
}
|
|
237
|
-
if (type === "turn.started" || type === "turn_started") {
|
|
238
|
-
return [{ type: "status", message: "Codex turn started" }];
|
|
239
|
-
}
|
|
240
|
-
if (type === "item.started" || type === "item_started") {
|
|
241
|
-
const item = asRecord(payload.item);
|
|
242
|
-
const itemType = getText(item.type);
|
|
243
|
-
if (itemType === "command_execution" || itemType === "commandExecution") {
|
|
244
|
-
const toolUseId = getText(item.id) ?? getText(payload.item_id) ?? `tool-${Date.now()}`;
|
|
245
|
-
const command = getText(item.command);
|
|
246
|
-
return [{
|
|
247
|
-
type: "tool_start",
|
|
248
|
-
toolName: "Bash",
|
|
249
|
-
toolUseId,
|
|
250
|
-
input: command ? { command } : asRecord(item.arguments),
|
|
251
|
-
turnId: getText(payload.turn_id) ?? getText(payload.turnId)
|
|
252
|
-
}];
|
|
253
|
-
}
|
|
254
|
-
return [];
|
|
255
|
-
}
|
|
256
|
-
if (type === "item.completed" || type === "item_completed") {
|
|
257
|
-
const item = asRecord(payload.item);
|
|
258
|
-
const itemType = getText(item.type);
|
|
259
|
-
if (itemType === "agent_message" || itemType === "agentMessage") {
|
|
260
|
-
const text = getText(item.text) ?? getText(item.message);
|
|
261
|
-
return text ? [{
|
|
262
|
-
type: "text_complete",
|
|
263
|
-
text,
|
|
264
|
-
isIntermediate: false,
|
|
265
|
-
turnId: getText(payload.turn_id) ?? getText(payload.turnId) ?? getText(item.id)
|
|
266
|
-
}] : [];
|
|
267
|
-
}
|
|
268
|
-
if (itemType === "command_execution" || itemType === "commandExecution") {
|
|
269
|
-
const toolUseId = getText(item.id) ?? getText(payload.item_id) ?? `tool-${Date.now()}`;
|
|
270
|
-
const exitCode = typeof item.exit_code === "number" ? item.exit_code : typeof item.exitCode === "number" ? item.exitCode : 0;
|
|
271
|
-
return [{
|
|
272
|
-
type: "tool_result",
|
|
273
|
-
toolName: "Bash",
|
|
274
|
-
toolUseId,
|
|
275
|
-
result: getText(item.aggregated_output) ?? getText(item.aggregatedOutput) ?? getText(item.output) ?? "",
|
|
276
|
-
isError: exitCode !== 0 || item.is_error === true,
|
|
277
|
-
turnId: getText(payload.turn_id) ?? getText(payload.turnId)
|
|
278
|
-
}];
|
|
279
|
-
}
|
|
280
|
-
return [];
|
|
281
|
-
}
|
|
282
|
-
if (type === "agent_message_delta" || type === "message_delta" || type === "response.output_text.delta") {
|
|
283
|
-
const text = getText(payload.delta) ?? getText(payload.text);
|
|
284
|
-
return text ? [{ type: "text_delta", text }] : [];
|
|
285
|
-
}
|
|
286
|
-
if (type === "agent_message" || type === "message" || type === "response.output_text.done") {
|
|
287
|
-
const text = getText(payload.message) ?? getText(payload.text);
|
|
288
|
-
return text ? [{ type: "text_complete", text, isIntermediate: false }] : [];
|
|
289
|
-
}
|
|
290
|
-
if (type === "exec_command_begin" || type === "tool_call_begin") {
|
|
291
|
-
const toolUseId = getText(payload.call_id) ?? getText(payload.id) ?? `tool-${Date.now()}`;
|
|
292
|
-
const command = getText(payload.command);
|
|
293
|
-
return [{
|
|
294
|
-
type: "tool_start",
|
|
295
|
-
toolName: getText(payload.tool_name) ?? "Bash",
|
|
296
|
-
toolUseId,
|
|
297
|
-
input: command ? { command } : asRecord(payload.arguments)
|
|
298
|
-
}];
|
|
299
|
-
}
|
|
300
|
-
if (type === "exec_command_end" || type === "tool_call_end") {
|
|
301
|
-
const toolUseId = getText(payload.call_id) ?? getText(payload.id) ?? `tool-${Date.now()}`;
|
|
302
|
-
const exitCode = typeof payload.exit_code === "number" ? payload.exit_code : 0;
|
|
303
|
-
return [{
|
|
304
|
-
type: "tool_result",
|
|
305
|
-
toolName: getText(payload.tool_name) ?? "Bash",
|
|
306
|
-
toolUseId,
|
|
307
|
-
result: getText(payload.output) ?? getText(payload.result) ?? "",
|
|
308
|
-
isError: exitCode !== 0 || payload.is_error === true
|
|
309
|
-
}];
|
|
310
|
-
}
|
|
311
|
-
if (type === "turn_completed" || type === "turn.completed" || type === "task_complete" || type === "response.completed") {
|
|
312
|
-
return [{ type: "complete", usage: normalizeUsage(asRecord(payload.usage)) }];
|
|
313
|
-
}
|
|
314
|
-
if (type === "error") {
|
|
315
|
-
return [{ type: "error", message: getText(payload.message) ?? "Codex stream error" }];
|
|
316
|
-
}
|
|
317
|
-
return [];
|
|
318
|
-
}
|
|
319
|
-
function createLocalTimelineProjector(options) {
|
|
320
|
-
const sequencer = createTimelineSequencer(options);
|
|
321
|
-
let lastTurnId;
|
|
322
|
-
return {
|
|
323
|
-
project(event) {
|
|
324
|
-
const items = mapAgentEventToTimelineItems(event, lastTurnId);
|
|
325
|
-
const eventTurnId = turnIdFromAgentEvent(event);
|
|
326
|
-
const itemTurnId = items.map((item) => "turnId" in item ? item.turnId : void 0).find((turnId) => typeof turnId === "string");
|
|
327
|
-
if (eventTurnId ?? itemTurnId) lastTurnId = eventTurnId ?? itemTurnId;
|
|
328
|
-
return items.map((item) => append(sequencer, item, event.type));
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
function append(sequencer, item, providerEventType) {
|
|
333
|
-
return sequencer.append(item, { providerEventType });
|
|
334
|
-
}
|
|
335
|
-
function mapAgentEventToTimelineItems(event, lastTurnId) {
|
|
336
|
-
switch (event.type) {
|
|
337
|
-
case "status":
|
|
338
|
-
case "info":
|
|
339
|
-
return [{ type: "session_status", status: event.message }];
|
|
340
|
-
case "text_delta": {
|
|
341
|
-
const turnId = event.turnId ?? lastTurnId ?? "turn-local";
|
|
342
|
-
return [{
|
|
343
|
-
type: "assistant_message_delta",
|
|
344
|
-
text: event.text,
|
|
345
|
-
messageId: messageIdForTurn(turnId),
|
|
346
|
-
turnId
|
|
347
|
-
}];
|
|
348
|
-
}
|
|
349
|
-
case "text_complete": {
|
|
350
|
-
const turnId = event.turnId ?? lastTurnId ?? "turn-local";
|
|
351
|
-
return [{
|
|
352
|
-
type: "assistant_message",
|
|
353
|
-
text: event.text,
|
|
354
|
-
messageId: messageIdForTurn(turnId),
|
|
355
|
-
turnId
|
|
356
|
-
}];
|
|
357
|
-
}
|
|
358
|
-
case "reasoning_delta": {
|
|
359
|
-
const turnId = event.turnId ?? lastTurnId ?? "turn-local";
|
|
360
|
-
return [{
|
|
361
|
-
type: "assistant_message_delta",
|
|
362
|
-
text: event.text,
|
|
363
|
-
messageId: messageIdForTurn(turnId),
|
|
364
|
-
turnId
|
|
365
|
-
}];
|
|
366
|
-
}
|
|
367
|
-
case "reasoning": {
|
|
368
|
-
const turnId = event.turnId ?? lastTurnId ?? "turn-local";
|
|
369
|
-
return [{
|
|
370
|
-
type: "assistant_message",
|
|
371
|
-
text: event.text,
|
|
372
|
-
messageId: messageIdForTurn(turnId),
|
|
373
|
-
turnId
|
|
374
|
-
}];
|
|
375
|
-
}
|
|
376
|
-
case "tool_start":
|
|
377
|
-
return [{
|
|
378
|
-
type: "tool_call",
|
|
379
|
-
callId: event.toolUseId,
|
|
380
|
-
name: event.toolName,
|
|
381
|
-
status: "running",
|
|
382
|
-
detail: { input: event.input },
|
|
383
|
-
turnId: event.turnId
|
|
384
|
-
}];
|
|
385
|
-
case "tool_result":
|
|
386
|
-
return [{
|
|
387
|
-
type: "tool_result",
|
|
388
|
-
callId: event.toolUseId,
|
|
389
|
-
result: event.result,
|
|
390
|
-
isError: event.isError,
|
|
391
|
-
turnId: event.turnId
|
|
392
|
-
}];
|
|
393
|
-
case "permission_request":
|
|
394
|
-
return [{
|
|
395
|
-
type: "permission_requested",
|
|
396
|
-
request: {
|
|
397
|
-
requestId: event.requestId,
|
|
398
|
-
toolName: event.toolName,
|
|
399
|
-
input: { command: event.command },
|
|
400
|
-
reason: event.reason
|
|
401
|
-
}
|
|
402
|
-
}];
|
|
403
|
-
case "permission_response":
|
|
404
|
-
return [{
|
|
405
|
-
type: "permission_resolved",
|
|
406
|
-
requestId: event.requestId,
|
|
407
|
-
resolution: {
|
|
408
|
-
allowed: event.allowed,
|
|
409
|
-
remember: event.remember ?? false
|
|
410
|
-
}
|
|
411
|
-
}];
|
|
412
|
-
case "complete": {
|
|
413
|
-
const items = [];
|
|
414
|
-
if (lastTurnId) {
|
|
415
|
-
items.push({
|
|
416
|
-
type: "turn_completed",
|
|
417
|
-
turnId: lastTurnId,
|
|
418
|
-
usage: event.usage
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
items.push({ type: "session_status", status: "ready" });
|
|
422
|
-
return items;
|
|
423
|
-
}
|
|
424
|
-
case "error":
|
|
425
|
-
if (lastTurnId) {
|
|
426
|
-
return [{
|
|
427
|
-
type: "turn_failed",
|
|
428
|
-
turnId: lastTurnId,
|
|
429
|
-
error: { message: event.message }
|
|
430
|
-
}];
|
|
431
|
-
}
|
|
432
|
-
return [{ type: "session_status", status: "failed" }];
|
|
433
|
-
case "typed_error":
|
|
434
|
-
if (lastTurnId) {
|
|
435
|
-
return [{
|
|
436
|
-
type: "turn_failed",
|
|
437
|
-
turnId: lastTurnId,
|
|
438
|
-
error: event.error
|
|
439
|
-
}];
|
|
440
|
-
}
|
|
441
|
-
return [{ type: "session_status", status: "failed" }];
|
|
442
|
-
case "source_activated":
|
|
443
|
-
return [{
|
|
444
|
-
type: "source_state_changed",
|
|
445
|
-
source: {
|
|
446
|
-
sourceSlug: event.sourceSlug,
|
|
447
|
-
state: "active",
|
|
448
|
-
originalMessage: event.originalMessage
|
|
449
|
-
}
|
|
450
|
-
}];
|
|
451
|
-
case "usage_update":
|
|
452
|
-
return [{ type: "session_status", status: "usage_update" }];
|
|
453
|
-
case "working_directory_changed":
|
|
454
|
-
return [{
|
|
455
|
-
type: "session_status",
|
|
456
|
-
status: `working_directory:${event.workingDirectory}`
|
|
457
|
-
}];
|
|
458
|
-
case "compaction_started":
|
|
459
|
-
return [{ type: "compaction_started" }];
|
|
460
|
-
case "compaction_boundary":
|
|
461
|
-
return [{ type: "compaction_boundary", summary: event.summary }];
|
|
462
|
-
case "task_backgrounded":
|
|
463
|
-
case "shell_backgrounded":
|
|
464
|
-
case "task_progress":
|
|
465
|
-
case "task_completed":
|
|
466
|
-
case "shell_killed":
|
|
467
|
-
case "steer_undelivered":
|
|
468
|
-
return [{ type: "session_status", status: event.type }];
|
|
469
|
-
default:
|
|
470
|
-
return [];
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
function turnIdFromAgentEvent(event) {
|
|
474
|
-
if ("turnId" in event) return event.turnId;
|
|
475
|
-
return void 0;
|
|
476
|
-
}
|
|
477
|
-
function messageIdForTurn(turnId) {
|
|
478
|
-
return `${turnId}:assistant`;
|
|
479
|
-
}
|
|
480
|
-
function createFakeLocalAgentSession(options) {
|
|
481
|
-
const events = new PushAgentEventStream();
|
|
482
|
-
let state = initialRuntimeState;
|
|
483
|
-
function dispatch(action) {
|
|
484
|
-
state = reduceRuntimeState(state, action);
|
|
485
|
-
}
|
|
486
|
-
async function runScript() {
|
|
487
|
-
events.emit({ type: "status", message: `${options.provider} runtime accepted message` });
|
|
488
|
-
for (const event of options.script) {
|
|
489
|
-
if (event.type === "permission_request") {
|
|
490
|
-
dispatch({ type: "permission_request", requestId: event.requestId });
|
|
491
|
-
}
|
|
492
|
-
events.emit(event);
|
|
493
|
-
if (event.type === "complete") {
|
|
494
|
-
dispatch({ type: "complete" });
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
return {
|
|
499
|
-
sessionId: options.sessionId ?? `local-${options.provider}-${Date.now()}`,
|
|
500
|
-
provider: options.provider,
|
|
501
|
-
events,
|
|
502
|
-
async preflight() {
|
|
503
|
-
dispatch({ type: "preflight_ok" });
|
|
504
|
-
return {
|
|
505
|
-
mode: "provider-owned",
|
|
506
|
-
configured: true,
|
|
507
|
-
source: "fake-local-runtime"
|
|
508
|
-
};
|
|
509
|
-
},
|
|
510
|
-
getState() {
|
|
511
|
-
return state;
|
|
512
|
-
},
|
|
513
|
-
commands: {
|
|
514
|
-
async sendMessage(message, _sendOptions) {
|
|
515
|
-
dispatch({ type: "send_message", message });
|
|
516
|
-
await runScript();
|
|
517
|
-
},
|
|
518
|
-
async abort(reason) {
|
|
519
|
-
dispatch({ type: "abort", reason });
|
|
520
|
-
events.emit({ type: "error", message: reason ?? "Aborted" });
|
|
521
|
-
events.emit({ type: "complete" });
|
|
522
|
-
},
|
|
523
|
-
async respondToPermission(_requestId, _allowed, _remember) {
|
|
524
|
-
dispatch({ type: "permission_response" });
|
|
525
|
-
},
|
|
526
|
-
async dispose() {
|
|
527
|
-
dispatch({ type: "dispose" });
|
|
528
|
-
events.close();
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
function generateTraceTurnId() {
|
|
534
|
-
return `turn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
535
|
-
}
|
|
536
|
-
function generateTraceToolUseId() {
|
|
537
|
-
return `tool-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
538
|
-
}
|
|
539
|
-
var TraceToolIndex = class {
|
|
540
|
-
index = /* @__PURE__ */ new Map();
|
|
541
|
-
append(id, name, input) {
|
|
542
|
-
this.index.set(id, { id, name, input, matched: false });
|
|
543
|
-
}
|
|
544
|
-
find(id) {
|
|
545
|
-
return this.index.get(id);
|
|
546
|
-
}
|
|
547
|
-
markMatched(id) {
|
|
548
|
-
const entry = this.index.get(id);
|
|
549
|
-
if (entry) {
|
|
550
|
-
entry.matched = true;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
isMatched(id) {
|
|
554
|
-
return this.index.get(id)?.matched ?? false;
|
|
555
|
-
}
|
|
556
|
-
has(id) {
|
|
557
|
-
return this.index.has(id);
|
|
558
|
-
}
|
|
559
|
-
clear() {
|
|
560
|
-
this.index.clear();
|
|
561
|
-
}
|
|
562
|
-
/** Get all unmatched tool starts (for detecting orphaned tool calls) */
|
|
563
|
-
unmatched() {
|
|
564
|
-
return Array.from(this.index.values()).filter((entry) => !entry.matched);
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
|
-
var READ_PATTERNS = [
|
|
568
|
-
// cat file
|
|
569
|
-
{
|
|
570
|
-
regex: /^cat\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
571
|
-
extract: (m) => ({ filePath: m[1], originalCommand: m[0] })
|
|
572
|
-
},
|
|
573
|
-
// head -n N file / head -N file
|
|
574
|
-
{
|
|
575
|
-
regex: /^head\s+-n\s+(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
576
|
-
extract: (m) => ({
|
|
577
|
-
filePath: m[2],
|
|
578
|
-
endLine: parseInt(m[1], 10),
|
|
579
|
-
originalCommand: m[0]
|
|
580
|
-
})
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
regex: /^head\s+-(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
584
|
-
extract: (m) => ({
|
|
585
|
-
filePath: m[2],
|
|
586
|
-
endLine: parseInt(m[1], 10),
|
|
587
|
-
originalCommand: m[0]
|
|
588
|
-
})
|
|
589
|
-
},
|
|
590
|
-
// tail -n N file
|
|
591
|
-
{
|
|
592
|
-
regex: /^tail\s+-n\s+(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
593
|
-
extract: (m) => ({
|
|
594
|
-
filePath: m[2],
|
|
595
|
-
startLine: -parseInt(m[1], 10),
|
|
596
|
-
// negative = last N lines
|
|
597
|
-
originalCommand: m[0]
|
|
598
|
-
})
|
|
599
|
-
},
|
|
600
|
-
// sed -n 'start,end' file
|
|
601
|
-
{
|
|
602
|
-
regex: /^sed\s+-n\s+'(\d+),(\d+)p'\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
603
|
-
extract: (m) => ({
|
|
604
|
-
filePath: m[3],
|
|
605
|
-
startLine: parseInt(m[1], 10),
|
|
606
|
-
endLine: parseInt(m[2], 10),
|
|
607
|
-
originalCommand: m[0]
|
|
608
|
-
})
|
|
609
|
-
},
|
|
610
|
-
// sed -n 'startp' file
|
|
611
|
-
{
|
|
612
|
-
regex: /^sed\s+-n\s+'(\d+)p'\s+['"]?([^'"\s]+)['"]?\s*$/,
|
|
613
|
-
extract: (m) => ({
|
|
614
|
-
filePath: m[2],
|
|
615
|
-
startLine: parseInt(m[1], 10),
|
|
616
|
-
endLine: parseInt(m[1], 10),
|
|
617
|
-
originalCommand: m[0]
|
|
618
|
-
})
|
|
619
|
-
}
|
|
620
|
-
];
|
|
621
|
-
function parseTraceReadCommand(command) {
|
|
622
|
-
const stripped = command.replace(/^bash\s+-[lc]+\s+/, "").trim();
|
|
623
|
-
for (const pattern of READ_PATTERNS) {
|
|
624
|
-
const match = stripped.match(pattern.regex);
|
|
625
|
-
if (match) {
|
|
626
|
-
return pattern.extract(match);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
return null;
|
|
630
|
-
}
|
|
631
|
-
var TraceEventAdapter = class {
|
|
632
|
-
turnIndex = 0;
|
|
633
|
-
currentTurnId = null;
|
|
634
|
-
// Shared state maps — reset on each turn
|
|
635
|
-
commandOutput = /* @__PURE__ */ new Map();
|
|
636
|
-
readCommands = /* @__PURE__ */ new Map();
|
|
637
|
-
blockReasons = /* @__PURE__ */ new Map();
|
|
638
|
-
toolIndex = new TraceToolIndex();
|
|
639
|
-
/**
|
|
640
|
-
* Start a new turn — resets shared state and calls subclass hook.
|
|
641
|
-
*/
|
|
642
|
-
startTurn(turnId) {
|
|
643
|
-
this.turnIndex++;
|
|
644
|
-
this.commandOutput.clear();
|
|
645
|
-
this.readCommands.clear();
|
|
646
|
-
this.blockReasons.clear();
|
|
647
|
-
this.toolIndex.clear();
|
|
648
|
-
this.currentTurnId = turnId || generateTraceTurnId();
|
|
649
|
-
this.onTurnStart();
|
|
650
|
-
}
|
|
651
|
-
setBlockReason(id, reason) {
|
|
652
|
-
this.blockReasons.set(id, reason);
|
|
653
|
-
}
|
|
654
|
-
consumeBlockReason(...keys) {
|
|
655
|
-
for (const key of keys) {
|
|
656
|
-
const reason = this.blockReasons.get(key);
|
|
657
|
-
if (reason !== void 0) {
|
|
658
|
-
this.blockReasons.delete(key);
|
|
659
|
-
return reason;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
return void 0;
|
|
663
|
-
}
|
|
664
|
-
classifyReadCommand(id, command) {
|
|
665
|
-
const readInfo = parseTraceReadCommand(command);
|
|
666
|
-
if (readInfo) {
|
|
667
|
-
this.readCommands.set(id, readInfo);
|
|
668
|
-
}
|
|
669
|
-
return readInfo;
|
|
670
|
-
}
|
|
671
|
-
consumeReadCommand(id) {
|
|
672
|
-
const info = this.readCommands.get(id);
|
|
673
|
-
if (info) {
|
|
674
|
-
this.readCommands.delete(id);
|
|
675
|
-
}
|
|
676
|
-
return info;
|
|
677
|
-
}
|
|
678
|
-
accumulateOutput(id, delta) {
|
|
679
|
-
const current = this.commandOutput.get(id) || "";
|
|
680
|
-
this.commandOutput.set(id, current + delta);
|
|
681
|
-
}
|
|
682
|
-
consumeOutput(id) {
|
|
683
|
-
const output = this.commandOutput.get(id);
|
|
684
|
-
if (output !== void 0) {
|
|
685
|
-
this.commandOutput.delete(id);
|
|
686
|
-
}
|
|
687
|
-
return output;
|
|
688
|
-
}
|
|
689
|
-
createToolStart(id, toolName, input, intent, displayName, parentToolUseId) {
|
|
690
|
-
return {
|
|
691
|
-
type: "tool_start",
|
|
692
|
-
toolName,
|
|
693
|
-
toolUseId: id,
|
|
694
|
-
input,
|
|
695
|
-
intent,
|
|
696
|
-
displayName,
|
|
697
|
-
turnId: this.currentTurnId || void 0,
|
|
698
|
-
parentToolUseId
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
createToolResult(id, toolName, result, isError, parentToolUseId) {
|
|
702
|
-
return {
|
|
703
|
-
type: "tool_result",
|
|
704
|
-
toolUseId: id,
|
|
705
|
-
toolName,
|
|
706
|
-
result,
|
|
707
|
-
isError,
|
|
708
|
-
turnId: this.currentTurnId || void 0,
|
|
709
|
-
parentToolUseId
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
createReadToolStart(id, readInfo, intent) {
|
|
713
|
-
return this.createToolStart(
|
|
714
|
-
id,
|
|
715
|
-
"Read",
|
|
716
|
-
{
|
|
717
|
-
file_path: readInfo.filePath,
|
|
718
|
-
offset: readInfo.startLine,
|
|
719
|
-
limit: readInfo.endLine ? readInfo.endLine - (readInfo.startLine || 1) + 1 : void 0,
|
|
720
|
-
_command: readInfo.originalCommand
|
|
721
|
-
},
|
|
722
|
-
intent,
|
|
723
|
-
"Read File"
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
/**
|
|
727
|
-
* Build an MCP tool name from server and tool names.
|
|
728
|
-
*/
|
|
729
|
-
buildMcpToolName(serverName, toolName) {
|
|
730
|
-
if (toolName.startsWith("mcp__")) return toolName;
|
|
731
|
-
return `mcp__${serverName}__${toolName}`;
|
|
732
|
-
}
|
|
733
|
-
};
|
|
734
|
-
var ClaudeStdoutAdapter = class extends TraceEventAdapter {
|
|
735
|
-
hasFinalResponse = false;
|
|
736
|
-
onTurnStart() {
|
|
737
|
-
this.hasFinalResponse = false;
|
|
738
|
-
}
|
|
739
|
-
/**
|
|
740
|
-
* Parse claude -p stdout + stderr into AgentEvent[].
|
|
741
|
-
*
|
|
742
|
-
* Since claude -p output is mostly unstructured plain text,
|
|
743
|
-
* we do a best-effort extraction of tool-related patterns
|
|
744
|
-
* and map everything else to text_complete / status / error events.
|
|
745
|
-
*/
|
|
746
|
-
parseOutput(stdout, stderr) {
|
|
747
|
-
const events = [];
|
|
748
|
-
this.startTurn();
|
|
749
|
-
if (stderr.trim()) {
|
|
750
|
-
const errorLines = stderr.split("\n").filter((l) => l.trim());
|
|
751
|
-
for (const line of errorLines) {
|
|
752
|
-
if (line.includes("rate_limited") || line.includes("Rate limit") || line.includes("429")) {
|
|
753
|
-
events.push({ type: "error", message: "Rate limited \u2014 please wait and retry" });
|
|
754
|
-
} else if (line.includes("invalid_api_key") || line.includes("Authentication") || line.includes("401") || line.includes("403")) {
|
|
755
|
-
events.push({ type: "error", message: "Authentication error \u2014 check your API key" });
|
|
756
|
-
} else if (line.includes("context_length_exceeded") || line.includes("too long")) {
|
|
757
|
-
events.push({ type: "error", message: "Context limit exceeded" });
|
|
758
|
-
} else {
|
|
759
|
-
events.push({ type: "status", message: line.trim() });
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
const stdoutLines = stdout.split("\n");
|
|
764
|
-
let responseText = "";
|
|
765
|
-
let currentTool = null;
|
|
766
|
-
let inXmlToolUse = false;
|
|
767
|
-
let xmlToolName = "";
|
|
768
|
-
let xmlToolInput = "";
|
|
769
|
-
let xmlToolResult = "";
|
|
770
|
-
let inXmlToolResult = false;
|
|
771
|
-
for (const line of stdoutLines) {
|
|
772
|
-
const xmlToolStartMatch = line.match(/<tool_use>\s*([\w.]+)/i);
|
|
773
|
-
if (xmlToolStartMatch) {
|
|
774
|
-
if (responseText.trim()) {
|
|
775
|
-
events.push({
|
|
776
|
-
type: "text_complete",
|
|
777
|
-
text: responseText.trim(),
|
|
778
|
-
isIntermediate: true,
|
|
779
|
-
turnId: this.currentTurnId || void 0
|
|
780
|
-
});
|
|
781
|
-
responseText = "";
|
|
782
|
-
}
|
|
783
|
-
inXmlToolUse = true;
|
|
784
|
-
xmlToolName = xmlToolStartMatch[1];
|
|
785
|
-
xmlToolInput = "";
|
|
786
|
-
continue;
|
|
787
|
-
}
|
|
788
|
-
if (inXmlToolUse && line.match(/<\/tool_use>/i)) {
|
|
789
|
-
inXmlToolUse = false;
|
|
790
|
-
const toolId = generateTraceToolUseId();
|
|
791
|
-
let parsedInput = {};
|
|
792
|
-
try {
|
|
793
|
-
parsedInput = JSON.parse(xmlToolInput.trim());
|
|
794
|
-
} catch {
|
|
795
|
-
parsedInput = { raw_input: xmlToolInput.trim() };
|
|
796
|
-
}
|
|
797
|
-
events.push(this.createToolStart(toolId, xmlToolName, parsedInput));
|
|
798
|
-
this.toolIndex.append(toolId, xmlToolName, parsedInput);
|
|
799
|
-
currentTool = { id: toolId, name: xmlToolName, input: parsedInput, outputLines: [] };
|
|
800
|
-
continue;
|
|
801
|
-
}
|
|
802
|
-
if (inXmlToolUse) {
|
|
803
|
-
xmlToolInput += line + "\n";
|
|
804
|
-
continue;
|
|
805
|
-
}
|
|
806
|
-
const xmlResultStartMatch = line.match(/<tool_result>/i);
|
|
807
|
-
if (xmlResultStartMatch) {
|
|
808
|
-
inXmlToolResult = true;
|
|
809
|
-
xmlToolResult = "";
|
|
810
|
-
continue;
|
|
811
|
-
}
|
|
812
|
-
if (inXmlToolResult && line.match(/<\/tool_result>/i)) {
|
|
813
|
-
inXmlToolResult = false;
|
|
814
|
-
if (currentTool) {
|
|
815
|
-
events.push(
|
|
816
|
-
this.createToolResult(currentTool.id, currentTool.name, xmlToolResult.trim(), false)
|
|
817
|
-
);
|
|
818
|
-
currentTool = null;
|
|
819
|
-
}
|
|
820
|
-
xmlToolResult = "";
|
|
821
|
-
continue;
|
|
822
|
-
}
|
|
823
|
-
if (inXmlToolResult) {
|
|
824
|
-
xmlToolResult += line + "\n";
|
|
825
|
-
continue;
|
|
826
|
-
}
|
|
827
|
-
const toolStartMatch = matchToolStartPattern(line);
|
|
828
|
-
if (toolStartMatch) {
|
|
829
|
-
if (responseText.trim()) {
|
|
830
|
-
events.push({
|
|
831
|
-
type: "text_complete",
|
|
832
|
-
text: responseText.trim(),
|
|
833
|
-
isIntermediate: true,
|
|
834
|
-
turnId: this.currentTurnId || void 0
|
|
835
|
-
});
|
|
836
|
-
responseText = "";
|
|
837
|
-
}
|
|
838
|
-
currentTool = {
|
|
839
|
-
id: generateTraceToolUseId(),
|
|
840
|
-
name: toolStartMatch.name,
|
|
841
|
-
input: toolStartMatch.input,
|
|
842
|
-
outputLines: []
|
|
843
|
-
};
|
|
844
|
-
events.push(
|
|
845
|
-
this.createToolStart(currentTool.id, currentTool.name, currentTool.input)
|
|
846
|
-
);
|
|
847
|
-
this.toolIndex.append(currentTool.id, currentTool.name, currentTool.input);
|
|
848
|
-
continue;
|
|
849
|
-
}
|
|
850
|
-
const toolEndMatch = matchToolEndPattern(line);
|
|
851
|
-
if (toolEndMatch && currentTool) {
|
|
852
|
-
events.push(
|
|
853
|
-
this.createToolResult(
|
|
854
|
-
currentTool.id,
|
|
855
|
-
currentTool.name,
|
|
856
|
-
currentTool.outputLines.join("\n").trim() || toolEndMatch.result,
|
|
857
|
-
toolEndMatch.isError
|
|
858
|
-
)
|
|
859
|
-
);
|
|
860
|
-
currentTool = null;
|
|
861
|
-
continue;
|
|
862
|
-
}
|
|
863
|
-
if (currentTool) {
|
|
864
|
-
currentTool.outputLines.push(line);
|
|
865
|
-
} else {
|
|
866
|
-
responseText += line + "\n";
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
if (currentTool) {
|
|
870
|
-
events.push(
|
|
871
|
-
this.createToolResult(
|
|
872
|
-
currentTool.id,
|
|
873
|
-
currentTool.name,
|
|
874
|
-
currentTool.outputLines.join("\n").trim(),
|
|
875
|
-
false
|
|
876
|
-
)
|
|
877
|
-
);
|
|
878
|
-
}
|
|
879
|
-
if (responseText.trim()) {
|
|
880
|
-
events.push({
|
|
881
|
-
type: "text_complete",
|
|
882
|
-
text: responseText.trim(),
|
|
883
|
-
isIntermediate: false,
|
|
884
|
-
turnId: this.currentTurnId || void 0
|
|
885
|
-
});
|
|
886
|
-
this.hasFinalResponse = true;
|
|
887
|
-
}
|
|
888
|
-
events.push({ type: "complete" });
|
|
889
|
-
return events;
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
|
-
function matchToolStartPattern(line) {
|
|
893
|
-
const trimmed = line.trim();
|
|
894
|
-
const cmdMatch = trimmed.match(/^Running command:\s+(.+)$/i) || trimmed.match(/^Executing:\s+(.+)$/i) || trimmed.match(/^Running bash command:\s+(.+)$/i);
|
|
895
|
-
if (cmdMatch) {
|
|
896
|
-
return { name: "Bash", input: { command: cmdMatch[1] } };
|
|
897
|
-
}
|
|
898
|
-
const readMatch = trimmed.match(/^Reading file:\s+(.+)$/i) || trimmed.match(/^Read:\s+(.+)$/i);
|
|
899
|
-
if (readMatch) {
|
|
900
|
-
return { name: "Read", input: { file_path: readMatch[1] } };
|
|
901
|
-
}
|
|
902
|
-
const writeMatch = trimmed.match(/^Writing file:\s+(.+)$/i) || trimmed.match(/^Edit:\s+(.+)$/i) || trimmed.match(/^Writing:\s+(.+)$/i);
|
|
903
|
-
if (writeMatch) {
|
|
904
|
-
return { name: "Edit", input: { file_path: writeMatch[1] } };
|
|
905
|
-
}
|
|
906
|
-
const searchMatch = trimmed.match(/^Searching for:\s+(.+)$/i) || trimmed.match(/^Search:\s+(.+)$/i);
|
|
907
|
-
if (searchMatch) {
|
|
908
|
-
return { name: "Search", input: { query: searchMatch[1] } };
|
|
909
|
-
}
|
|
910
|
-
return null;
|
|
911
|
-
}
|
|
912
|
-
function matchToolEndPattern(line) {
|
|
913
|
-
const trimmed = line.trim();
|
|
914
|
-
if (/^Command (completed|finished|done)/i.test(trimmed) || /^Done$/i.test(trimmed)) {
|
|
915
|
-
return { result: trimmed, isError: false };
|
|
916
|
-
}
|
|
917
|
-
if (/^Command failed/i.test(trimmed) || /^Error:/i.test(trimmed)) {
|
|
918
|
-
return { result: trimmed, isError: true };
|
|
919
|
-
}
|
|
920
|
-
if (/^File (written|read|updated) (successfully|complete)/i.test(trimmed)) {
|
|
921
|
-
return { result: trimmed, isError: false };
|
|
922
|
-
}
|
|
923
|
-
return null;
|
|
924
|
-
}
|
|
925
|
-
function parseClaudeStdoutTrace(stdout, stderr) {
|
|
926
|
-
return new ClaudeStdoutAdapter().parseOutput(stdout, stderr);
|
|
927
|
-
}
|
|
928
|
-
var CodexRolloutAdapter = class extends TraceEventAdapter {
|
|
929
|
-
// Per-turn state for deduplication
|
|
930
|
-
emittedEventMsgIds = /* @__PURE__ */ new Set();
|
|
931
|
-
pendingAssistantText = null;
|
|
932
|
-
pendingAssistantTurnId = null;
|
|
933
|
-
onTurnStart() {
|
|
934
|
-
this.emittedEventMsgIds.clear();
|
|
935
|
-
this.pendingAssistantText = null;
|
|
936
|
-
this.pendingAssistantTurnId = null;
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Parse a complete rollout JSONL string into AgentEvent[].
|
|
940
|
-
* Each line is a JSON object representing a Codex event.
|
|
941
|
-
*/
|
|
942
|
-
parseRollout(rolloutJsonl) {
|
|
943
|
-
const events = [];
|
|
944
|
-
const lines = rolloutJsonl.split("\n").filter((l) => l.trim());
|
|
945
|
-
this.startTurn();
|
|
946
|
-
for (const line of lines) {
|
|
947
|
-
try {
|
|
948
|
-
const obj = JSON.parse(line);
|
|
949
|
-
const parsed = this.adaptRolloutEvent(obj);
|
|
950
|
-
events.push(...parsed);
|
|
951
|
-
} catch {
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
if (this.pendingAssistantText) {
|
|
955
|
-
events.push({
|
|
956
|
-
type: "text_complete",
|
|
957
|
-
text: this.pendingAssistantText,
|
|
958
|
-
isIntermediate: false,
|
|
959
|
-
turnId: this.pendingAssistantTurnId || this.currentTurnId || void 0
|
|
960
|
-
});
|
|
961
|
-
this.pendingAssistantText = null;
|
|
962
|
-
}
|
|
963
|
-
const hasComplete = events.some((e) => e.type === "complete");
|
|
964
|
-
if (!hasComplete && events.length > 0) {
|
|
965
|
-
events.push({ type: "complete" });
|
|
966
|
-
}
|
|
967
|
-
return events;
|
|
968
|
-
}
|
|
969
|
-
/**
|
|
970
|
-
* Adapt a single Codex rollout event to AgentEvent[].
|
|
971
|
-
*/
|
|
972
|
-
adaptRolloutEvent(event) {
|
|
973
|
-
const events = [];
|
|
974
|
-
switch (event.type) {
|
|
975
|
-
// ====================================================================
|
|
976
|
-
// Text & reasoning events
|
|
977
|
-
// ====================================================================
|
|
978
|
-
case "response_item": {
|
|
979
|
-
const item = event;
|
|
980
|
-
if (item.id && this.emittedEventMsgIds.has(item.id)) {
|
|
981
|
-
break;
|
|
982
|
-
}
|
|
983
|
-
if (item.role === "assistant") {
|
|
984
|
-
const text = extractTextFromContent(item.content);
|
|
985
|
-
if (text) {
|
|
986
|
-
const isReasoning = item.metadata?.reasoning === true;
|
|
987
|
-
const isIntermediate = isReasoning || hasToolUseInContent(item.content);
|
|
988
|
-
if (isIntermediate) {
|
|
989
|
-
events.push({
|
|
990
|
-
type: "text_complete",
|
|
991
|
-
text,
|
|
992
|
-
isIntermediate: true,
|
|
993
|
-
turnId: this.currentTurnId || void 0
|
|
994
|
-
});
|
|
995
|
-
} else {
|
|
996
|
-
this.pendingAssistantText = text;
|
|
997
|
-
this.pendingAssistantTurnId = this.currentTurnId;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
const toolUses = extractToolUsesFromContent(item.content);
|
|
1001
|
-
for (const tu of toolUses) {
|
|
1002
|
-
this.toolIndex.append(tu.id, tu.name, tu.input);
|
|
1003
|
-
events.push(this.createToolStart(tu.id, tu.name, tu.input, void 0, void 0));
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
if (item.role === "user" && isSyntheticMessage(item)) {
|
|
1007
|
-
break;
|
|
1008
|
-
}
|
|
1009
|
-
break;
|
|
1010
|
-
}
|
|
1011
|
-
case "event_msg": {
|
|
1012
|
-
const msg = event;
|
|
1013
|
-
if (msg.id) {
|
|
1014
|
-
this.emittedEventMsgIds.add(msg.id);
|
|
1015
|
-
}
|
|
1016
|
-
if (msg.role === "assistant" && msg.message) {
|
|
1017
|
-
events.push({
|
|
1018
|
-
type: "text_complete",
|
|
1019
|
-
text: msg.message,
|
|
1020
|
-
isIntermediate: false,
|
|
1021
|
-
turnId: this.currentTurnId || void 0
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
break;
|
|
1025
|
-
}
|
|
1026
|
-
case "agent_message_delta": {
|
|
1027
|
-
const delta = event;
|
|
1028
|
-
if (delta.delta) {
|
|
1029
|
-
events.push({
|
|
1030
|
-
type: "text_delta",
|
|
1031
|
-
text: delta.delta,
|
|
1032
|
-
turnId: this.currentTurnId || void 0
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
break;
|
|
1036
|
-
}
|
|
1037
|
-
case "agent_reasoning": {
|
|
1038
|
-
const reasoning = event;
|
|
1039
|
-
if (reasoning.text) {
|
|
1040
|
-
events.push({
|
|
1041
|
-
type: "text_complete",
|
|
1042
|
-
text: reasoning.text,
|
|
1043
|
-
isIntermediate: true,
|
|
1044
|
-
turnId: this.currentTurnId || void 0
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
break;
|
|
1048
|
-
}
|
|
1049
|
-
case "agent_reasoning_delta": {
|
|
1050
|
-
const delta = event;
|
|
1051
|
-
if (delta.delta) {
|
|
1052
|
-
events.push({
|
|
1053
|
-
type: "text_delta",
|
|
1054
|
-
text: delta.delta,
|
|
1055
|
-
turnId: this.currentTurnId || void 0
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
break;
|
|
1059
|
-
}
|
|
1060
|
-
// ====================================================================
|
|
1061
|
-
// Command execution events
|
|
1062
|
-
// ====================================================================
|
|
1063
|
-
case "exec_command_begin": {
|
|
1064
|
-
const cmd = event;
|
|
1065
|
-
const command = Array.isArray(cmd.command) ? cmd.command.join(" ") : String(cmd.command ?? "");
|
|
1066
|
-
const cwd = cmd.cwd ?? "";
|
|
1067
|
-
const readInfo = this.classifyReadCommand(cmd.call_id, command);
|
|
1068
|
-
if (readInfo) {
|
|
1069
|
-
events.push(this.createReadToolStart(cmd.call_id, readInfo));
|
|
1070
|
-
} else {
|
|
1071
|
-
events.push(
|
|
1072
|
-
this.createToolStart(cmd.call_id, "Bash", {
|
|
1073
|
-
command,
|
|
1074
|
-
cwd
|
|
1075
|
-
}, void 0, "Execute Command")
|
|
1076
|
-
);
|
|
1077
|
-
}
|
|
1078
|
-
this.toolIndex.append(cmd.call_id, "Bash", { command, cwd });
|
|
1079
|
-
break;
|
|
1080
|
-
}
|
|
1081
|
-
case "exec_command_output_delta": {
|
|
1082
|
-
const delta = event;
|
|
1083
|
-
const decoded = decodeBase64Chunk(delta.chunk);
|
|
1084
|
-
if (decoded) {
|
|
1085
|
-
this.accumulateOutput(delta.call_id, decoded);
|
|
1086
|
-
}
|
|
1087
|
-
break;
|
|
1088
|
-
}
|
|
1089
|
-
case "exec_command_end": {
|
|
1090
|
-
const cmdEnd = event;
|
|
1091
|
-
const accumulated = this.consumeOutput(cmdEnd.call_id);
|
|
1092
|
-
const output = accumulated ?? cmdEnd.stdout ?? cmdEnd.formatted_output ?? "";
|
|
1093
|
-
const cleanOutput = stripShellEnvelope(output);
|
|
1094
|
-
const isError = cmdEnd.exit_code !== 0;
|
|
1095
|
-
const readInfo = this.consumeReadCommand(cmdEnd.call_id);
|
|
1096
|
-
events.push(
|
|
1097
|
-
this.createToolResult(
|
|
1098
|
-
cmdEnd.call_id,
|
|
1099
|
-
readInfo ? "Read" : "Bash",
|
|
1100
|
-
cleanOutput,
|
|
1101
|
-
isError
|
|
1102
|
-
)
|
|
1103
|
-
);
|
|
1104
|
-
this.pendingAssistantText = null;
|
|
1105
|
-
break;
|
|
1106
|
-
}
|
|
1107
|
-
// ====================================================================
|
|
1108
|
-
// Patch / file modification events
|
|
1109
|
-
// ====================================================================
|
|
1110
|
-
case "apply_patch_approval_request":
|
|
1111
|
-
case "patch_apply_begin": {
|
|
1112
|
-
const patch = event;
|
|
1113
|
-
const callId = patch.call_id ?? `patch-${this.turnIndex}`;
|
|
1114
|
-
const changes = patch.changes ?? {};
|
|
1115
|
-
const filePaths = Object.keys(changes);
|
|
1116
|
-
const input = {
|
|
1117
|
-
changes,
|
|
1118
|
-
file_paths: filePaths
|
|
1119
|
-
};
|
|
1120
|
-
if (filePaths.length === 1) {
|
|
1121
|
-
input.file_path = filePaths[0];
|
|
1122
|
-
const change = changes[filePaths[0]];
|
|
1123
|
-
if (change && typeof change === "object") {
|
|
1124
|
-
if ("unified_diff" in change) input.unified_diff = change.unified_diff;
|
|
1125
|
-
if ("content" in change) input.content = change.content;
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
events.push(
|
|
1129
|
-
this.createToolStart(callId, "Edit", input, void 0, "Apply Patch")
|
|
1130
|
-
);
|
|
1131
|
-
this.toolIndex.append(callId, "Edit", input);
|
|
1132
|
-
break;
|
|
1133
|
-
}
|
|
1134
|
-
case "patch_apply_end": {
|
|
1135
|
-
const end = event;
|
|
1136
|
-
const callId = end.call_id ?? `patch-${this.turnIndex}`;
|
|
1137
|
-
const result = end.stdout ?? (end.success ? "Patch applied successfully" : end.error ?? "Patch failed");
|
|
1138
|
-
events.push(
|
|
1139
|
-
this.createToolResult(callId, "Edit", result, !end.success)
|
|
1140
|
-
);
|
|
1141
|
-
break;
|
|
1142
|
-
}
|
|
1143
|
-
// ====================================================================
|
|
1144
|
-
// MCP tool events
|
|
1145
|
-
// ====================================================================
|
|
1146
|
-
case "mcp_tool_call_begin": {
|
|
1147
|
-
const mcp = event;
|
|
1148
|
-
const callId = mcp.call_id ?? `mcp-${this.turnIndex}`;
|
|
1149
|
-
const invocation = mcp.invocation ?? {};
|
|
1150
|
-
const toolName = this.buildMcpToolName(invocation.server ?? "unknown", invocation.tool ?? "unknown");
|
|
1151
|
-
const input = invocation.arguments ?? {};
|
|
1152
|
-
events.push(
|
|
1153
|
-
this.createToolStart(callId, toolName, input, void 0, invocation.tool ?? toolName)
|
|
1154
|
-
);
|
|
1155
|
-
this.toolIndex.append(callId, toolName, input);
|
|
1156
|
-
break;
|
|
1157
|
-
}
|
|
1158
|
-
case "mcp_tool_call_end": {
|
|
1159
|
-
const mcpEnd = event;
|
|
1160
|
-
const callId = mcpEnd.call_id ?? `mcp-${this.turnIndex}`;
|
|
1161
|
-
const result = mcpEnd.result ?? (mcpEnd.error ?? "MCP call completed");
|
|
1162
|
-
const isError = Boolean(mcpEnd.error);
|
|
1163
|
-
events.push(
|
|
1164
|
-
this.createToolResult(callId, "MCP", typeof result === "string" ? result : JSON.stringify(result), isError)
|
|
1165
|
-
);
|
|
1166
|
-
break;
|
|
1167
|
-
}
|
|
1168
|
-
// ====================================================================
|
|
1169
|
-
// Web search events
|
|
1170
|
-
// ====================================================================
|
|
1171
|
-
case "web_search_begin": {
|
|
1172
|
-
const ws = event;
|
|
1173
|
-
const callId = ws.call_id ?? `search-${this.turnIndex}`;
|
|
1174
|
-
events.push(
|
|
1175
|
-
this.createToolStart(callId, "WebSearch", {}, void 0, "Web Search")
|
|
1176
|
-
);
|
|
1177
|
-
this.toolIndex.append(callId, "WebSearch", {});
|
|
1178
|
-
break;
|
|
1179
|
-
}
|
|
1180
|
-
case "web_search_end": {
|
|
1181
|
-
const wsEnd = event;
|
|
1182
|
-
const callId = wsEnd.call_id ?? `search-${this.turnIndex}`;
|
|
1183
|
-
const result = wsEnd.query ?? "Search completed";
|
|
1184
|
-
events.push(
|
|
1185
|
-
this.createToolResult(callId, "WebSearch", result, false)
|
|
1186
|
-
);
|
|
1187
|
-
break;
|
|
1188
|
-
}
|
|
1189
|
-
// ====================================================================
|
|
1190
|
-
// Turn diff (file change summary)
|
|
1191
|
-
// ====================================================================
|
|
1192
|
-
case "turn_diff": {
|
|
1193
|
-
const diff = event;
|
|
1194
|
-
if (diff.unified_diff) {
|
|
1195
|
-
const filePaths = extractFilePathsFromDiff(diff.unified_diff);
|
|
1196
|
-
for (const fp of filePaths) {
|
|
1197
|
-
events.push(
|
|
1198
|
-
this.createToolStart(
|
|
1199
|
-
`diff-${fp}-${this.turnIndex}`,
|
|
1200
|
-
"Edit",
|
|
1201
|
-
{ file_path: fp, unified_diff: diff.unified_diff },
|
|
1202
|
-
void 0,
|
|
1203
|
-
`Changed: ${fp}`
|
|
1204
|
-
)
|
|
1205
|
-
);
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
break;
|
|
1209
|
-
}
|
|
1210
|
-
case "write_stdin": {
|
|
1211
|
-
const stdin = event;
|
|
1212
|
-
events.push({
|
|
1213
|
-
type: "status",
|
|
1214
|
-
message: stdin.content ? `Terminal input: ${stdin.content.slice(0, 80)}${stdin.content.length > 80 ? "..." : ""}` : "Terminal interaction"
|
|
1215
|
-
});
|
|
1216
|
-
break;
|
|
1217
|
-
}
|
|
1218
|
-
case "function_call_output": {
|
|
1219
|
-
const fco = event;
|
|
1220
|
-
const toolName = this.toolIndex.find(fco.call_id)?.name ?? "tool";
|
|
1221
|
-
events.push(
|
|
1222
|
-
this.createToolResult(fco.call_id, toolName, fco.output ?? "", fco.is_error ?? false)
|
|
1223
|
-
);
|
|
1224
|
-
this.toolIndex.markMatched(fco.call_id);
|
|
1225
|
-
break;
|
|
1226
|
-
}
|
|
1227
|
-
// ====================================================================
|
|
1228
|
-
// Lifecycle events
|
|
1229
|
-
// ====================================================================
|
|
1230
|
-
case "task_complete": {
|
|
1231
|
-
const tc = event;
|
|
1232
|
-
if (this.pendingAssistantText) {
|
|
1233
|
-
events.push({
|
|
1234
|
-
type: "text_complete",
|
|
1235
|
-
text: this.pendingAssistantText,
|
|
1236
|
-
isIntermediate: false,
|
|
1237
|
-
turnId: this.pendingAssistantTurnId || this.currentTurnId || void 0
|
|
1238
|
-
});
|
|
1239
|
-
this.pendingAssistantText = null;
|
|
1240
|
-
}
|
|
1241
|
-
events.push({ type: "complete" });
|
|
1242
|
-
break;
|
|
1243
|
-
}
|
|
1244
|
-
// ====================================================================
|
|
1245
|
-
// Ignored events (no UI value or handled elsewhere)
|
|
1246
|
-
// ====================================================================
|
|
1247
|
-
case "session_configured":
|
|
1248
|
-
case "task_started":
|
|
1249
|
-
case "token_count":
|
|
1250
|
-
case "user_message":
|
|
1251
|
-
// Filter synthetic, handle real user messages separately
|
|
1252
|
-
case "agent_message":
|
|
1253
|
-
// Full message, redundant with delta/complete
|
|
1254
|
-
case "conversation_path":
|
|
1255
|
-
case "background_event":
|
|
1256
|
-
case "turn_aborted":
|
|
1257
|
-
break;
|
|
1258
|
-
default:
|
|
1259
|
-
break;
|
|
1260
|
-
}
|
|
1261
|
-
return events;
|
|
1262
|
-
}
|
|
1263
|
-
};
|
|
1264
|
-
function extractTextFromContent(content) {
|
|
1265
|
-
if (!content) return null;
|
|
1266
|
-
let text = "";
|
|
1267
|
-
for (const block of content) {
|
|
1268
|
-
if (block.type === "text" && block.text) {
|
|
1269
|
-
text += block.text;
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
return text || null;
|
|
1273
|
-
}
|
|
1274
|
-
function hasToolUseInContent(content) {
|
|
1275
|
-
if (!content) return false;
|
|
1276
|
-
return content.some((block) => block.type === "tool_use");
|
|
1277
|
-
}
|
|
1278
|
-
function extractToolUsesFromContent(content) {
|
|
1279
|
-
if (!content) return [];
|
|
1280
|
-
const result = [];
|
|
1281
|
-
for (const block of content) {
|
|
1282
|
-
if (block.type === "tool_use" && block.id && block.name) {
|
|
1283
|
-
result.push({ id: block.id, name: block.name, input: block.input ?? {} });
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
return result;
|
|
1287
|
-
}
|
|
1288
|
-
function isSyntheticMessage(item) {
|
|
1289
|
-
const content = item.content;
|
|
1290
|
-
if (!content) return false;
|
|
1291
|
-
for (const block of content) {
|
|
1292
|
-
if (block.type === "text" && block.text) {
|
|
1293
|
-
if (block.text.startsWith("<environment>") || block.text.startsWith("<system-reminder>") || block.text.includes("is not available") && block.text.includes("Working directory")) {
|
|
1294
|
-
return true;
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
return false;
|
|
1299
|
-
}
|
|
1300
|
-
function decodeBase64Chunk(chunk) {
|
|
1301
|
-
if (!chunk) return null;
|
|
1302
|
-
try {
|
|
1303
|
-
return atob(chunk);
|
|
1304
|
-
} catch {
|
|
1305
|
-
return chunk;
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
function stripShellEnvelope(output) {
|
|
1309
|
-
return output.replace(/^\[(stdout|stderr)\]\s*/i, "").replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").trim();
|
|
1310
|
-
}
|
|
1311
|
-
function extractFilePathsFromDiff(diff) {
|
|
1312
|
-
const paths = [];
|
|
1313
|
-
for (const line of diff.split("\n")) {
|
|
1314
|
-
const match = line.match(/^diff --git\s+a\/(.+)\s+b\/(.+)/);
|
|
1315
|
-
if (match) {
|
|
1316
|
-
paths.push(match[2]);
|
|
1317
|
-
}
|
|
1318
|
-
const plusMatch = line.match(/^\+\+\+\s+b\/(.+)/);
|
|
1319
|
-
if (plusMatch && !paths.includes(plusMatch[1])) {
|
|
1320
|
-
paths.push(plusMatch[1]);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
return paths;
|
|
1324
|
-
}
|
|
1325
|
-
function parseCodexRolloutTrace(rolloutJsonl) {
|
|
1326
|
-
return new CodexRolloutAdapter().parseRollout(rolloutJsonl);
|
|
1327
|
-
}
|
|
1328
|
-
export {
|
|
1329
|
-
ClaudeStdoutAdapter,
|
|
1330
|
-
CodexRolloutAdapter,
|
|
1331
|
-
PushAgentEventStream,
|
|
1332
|
-
TraceEventAdapter,
|
|
1333
|
-
TraceToolIndex,
|
|
1334
|
-
createFakeLocalAgentSession,
|
|
1335
|
-
createLocalTimelineProjector,
|
|
1336
|
-
generateTraceToolUseId,
|
|
1337
|
-
generateTraceTurnId,
|
|
1338
|
-
initialRuntimeState,
|
|
1339
|
-
mapClaudeStreamJsonLine,
|
|
1340
|
-
mapCodexExecJsonLine,
|
|
1341
|
-
parseClaudeStdoutTrace,
|
|
1342
|
-
parseCodexRolloutTrace,
|
|
1343
|
-
parseTraceReadCommand,
|
|
1344
|
-
reduceRuntimeState as reduceRuntimeEvents
|
|
1345
|
-
};
|