agex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/assets/cursor.js +88 -0
- package/assets/cursor.js +88 -0
- package/dist/agents-2OHWEGTE.js +10 -0
- package/dist/chunk-3FGK7LUI.js +849 -0
- package/dist/chunk-KVAOIDJ4.js +419 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +392 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -0
- package/package.json +32 -0
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
// ../run/dist/agents/index.js
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
|
|
4
|
+
// ../run/dist/agents/utils.js
|
|
5
|
+
import { spawn } from "child_process";
|
|
6
|
+
|
|
7
|
+
// ../run/dist/parsers/claude.js
|
|
8
|
+
function createClaudeParser() {
|
|
9
|
+
const state = {
|
|
10
|
+
inThinking: false,
|
|
11
|
+
inTool: false,
|
|
12
|
+
currentToolId: null,
|
|
13
|
+
currentMessageId: null,
|
|
14
|
+
streamedMessageIds: /* @__PURE__ */ new Set()
|
|
15
|
+
};
|
|
16
|
+
function processContentBlock(block) {
|
|
17
|
+
switch (block.type) {
|
|
18
|
+
case "thinking":
|
|
19
|
+
if (block.thinking) {
|
|
20
|
+
return { type: "thinking_delta", text: block.thinking };
|
|
21
|
+
}
|
|
22
|
+
break;
|
|
23
|
+
case "text":
|
|
24
|
+
if (block.text) {
|
|
25
|
+
if (state.inTool) {
|
|
26
|
+
state.inTool = false;
|
|
27
|
+
state.currentToolId = null;
|
|
28
|
+
}
|
|
29
|
+
return { type: "text", text: block.text };
|
|
30
|
+
}
|
|
31
|
+
break;
|
|
32
|
+
case "tool_use":
|
|
33
|
+
if (block.name && block.id) {
|
|
34
|
+
state.inTool = true;
|
|
35
|
+
state.currentToolId = block.id;
|
|
36
|
+
return {
|
|
37
|
+
type: "tool_start",
|
|
38
|
+
name: block.name,
|
|
39
|
+
args: block.input
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case "tool_result":
|
|
44
|
+
if (block.tool_use_id && state.currentToolId === block.tool_use_id) {
|
|
45
|
+
state.inTool = false;
|
|
46
|
+
state.currentToolId = null;
|
|
47
|
+
return { type: "tool_end", name: "" };
|
|
48
|
+
}
|
|
49
|
+
if (state.inTool) {
|
|
50
|
+
state.inTool = false;
|
|
51
|
+
state.currentToolId = null;
|
|
52
|
+
return { type: "tool_end", name: "" };
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return (line) => {
|
|
59
|
+
if (!line.startsWith("{")) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
let msg;
|
|
63
|
+
try {
|
|
64
|
+
msg = JSON.parse(line);
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
switch (msg.type) {
|
|
69
|
+
case "content_block_start": {
|
|
70
|
+
if (msg.content_block?.type === "thinking") {
|
|
71
|
+
state.inThinking = true;
|
|
72
|
+
return { type: "thinking_start" };
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
case "content_block_delta": {
|
|
77
|
+
if (msg.delta?.type === "thinking_delta" && msg.delta.thinking) {
|
|
78
|
+
return { type: "thinking_delta", text: msg.delta.thinking };
|
|
79
|
+
}
|
|
80
|
+
if (msg.delta?.type === "text_delta" && msg.delta.text) {
|
|
81
|
+
if (state.currentMessageId) {
|
|
82
|
+
state.streamedMessageIds.add(state.currentMessageId);
|
|
83
|
+
}
|
|
84
|
+
return { type: "text", text: msg.delta.text };
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
case "content_block_stop": {
|
|
89
|
+
if (state.inThinking) {
|
|
90
|
+
state.inThinking = false;
|
|
91
|
+
return { type: "thinking_end" };
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
case "assistant": {
|
|
96
|
+
const messageId = msg.message?.id;
|
|
97
|
+
if (messageId) {
|
|
98
|
+
state.currentMessageId = messageId;
|
|
99
|
+
}
|
|
100
|
+
const content = msg.message?.content;
|
|
101
|
+
if (!content || !Array.isArray(content)) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (messageId && state.streamedMessageIds.has(messageId)) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
for (const block of content) {
|
|
108
|
+
const event = processContentBlock(block);
|
|
109
|
+
if (event) {
|
|
110
|
+
return event;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
case "user": {
|
|
116
|
+
const content = msg.message?.content;
|
|
117
|
+
if (!content || !Array.isArray(content)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
for (const block of content) {
|
|
121
|
+
if (block.type === "tool_result") {
|
|
122
|
+
const toolUseId = block.tool_use_id;
|
|
123
|
+
if (toolUseId && state.currentToolId === toolUseId) {
|
|
124
|
+
state.inTool = false;
|
|
125
|
+
state.currentToolId = null;
|
|
126
|
+
return { type: "tool_end", name: "" };
|
|
127
|
+
}
|
|
128
|
+
if (state.inTool) {
|
|
129
|
+
state.inTool = false;
|
|
130
|
+
state.currentToolId = null;
|
|
131
|
+
return { type: "tool_end", name: "" };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
case "system": {
|
|
138
|
+
if (msg.subtype === "init") {
|
|
139
|
+
return {
|
|
140
|
+
type: "init",
|
|
141
|
+
model: msg.model,
|
|
142
|
+
tools: msg.tools?.length,
|
|
143
|
+
mcpServers: msg.mcp_servers?.length
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
case "result": {
|
|
149
|
+
if (state.inTool) {
|
|
150
|
+
state.inTool = false;
|
|
151
|
+
state.currentToolId = null;
|
|
152
|
+
return { type: "tool_end", name: "" };
|
|
153
|
+
}
|
|
154
|
+
if (msg.is_error && msg.result) {
|
|
155
|
+
return { type: "error", message: msg.result };
|
|
156
|
+
}
|
|
157
|
+
const usage = msg.usage ? {
|
|
158
|
+
inputTokens: msg.usage.input_tokens,
|
|
159
|
+
outputTokens: msg.usage.output_tokens,
|
|
160
|
+
costUsd: msg.total_cost_usd
|
|
161
|
+
} : void 0;
|
|
162
|
+
return { type: "done", durationMs: msg.duration_ms, usage };
|
|
163
|
+
}
|
|
164
|
+
case "error": {
|
|
165
|
+
if (msg.error) {
|
|
166
|
+
return { type: "error", message: msg.error };
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ../run/dist/parsers/codex.js
|
|
176
|
+
function createCodexParser() {
|
|
177
|
+
const state = {
|
|
178
|
+
inThinking: false,
|
|
179
|
+
inTool: false,
|
|
180
|
+
currentToolId: null
|
|
181
|
+
};
|
|
182
|
+
return (line) => {
|
|
183
|
+
if (!line.startsWith("{")) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
let msg;
|
|
187
|
+
try {
|
|
188
|
+
msg = JSON.parse(line);
|
|
189
|
+
} catch {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
switch (msg.type) {
|
|
193
|
+
case "thread.started": {
|
|
194
|
+
return { type: "session_start", threadId: msg.thread_id };
|
|
195
|
+
}
|
|
196
|
+
case "turn.started": {
|
|
197
|
+
return { type: "turn_start" };
|
|
198
|
+
}
|
|
199
|
+
case "item.started": {
|
|
200
|
+
const itemType = msg.item?.type;
|
|
201
|
+
if (itemType === "reasoning") {
|
|
202
|
+
state.inThinking = true;
|
|
203
|
+
return { type: "thinking_start" };
|
|
204
|
+
}
|
|
205
|
+
if (itemType === "mcp_tool_call") {
|
|
206
|
+
const server = msg.item?.server ?? "";
|
|
207
|
+
const tool = msg.item?.tool ?? "";
|
|
208
|
+
const toolName = server ? `${server}:${tool}` : tool;
|
|
209
|
+
const args = msg.item?.arguments ?? msg.item?.args ?? msg.item?.input;
|
|
210
|
+
state.inTool = true;
|
|
211
|
+
state.currentToolId = msg.item?.id ?? null;
|
|
212
|
+
return { type: "tool_start", name: toolName, args };
|
|
213
|
+
}
|
|
214
|
+
if (itemType === "command_execution") {
|
|
215
|
+
const command = msg.item?.command ?? "";
|
|
216
|
+
state.inTool = true;
|
|
217
|
+
state.currentToolId = msg.item?.id ?? null;
|
|
218
|
+
return { type: "tool_start", name: "shell", args: { command } };
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
case "item.delta": {
|
|
223
|
+
if (msg.item?.type === "reasoning") {
|
|
224
|
+
const delta = msg.delta ?? msg.item?.delta;
|
|
225
|
+
if (delta) {
|
|
226
|
+
return { type: "thinking_delta", text: delta };
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
case "item.completed": {
|
|
232
|
+
const itemType = msg.item?.type;
|
|
233
|
+
if (itemType === "mcp_tool_call" || itemType === "command_execution") {
|
|
234
|
+
if (state.inTool) {
|
|
235
|
+
state.inTool = false;
|
|
236
|
+
state.currentToolId = null;
|
|
237
|
+
return { type: "tool_end", name: "" };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (itemType === "agent_message") {
|
|
241
|
+
const text = msg.item?.text;
|
|
242
|
+
if (text) {
|
|
243
|
+
if (state.inTool) {
|
|
244
|
+
state.inTool = false;
|
|
245
|
+
state.currentToolId = null;
|
|
246
|
+
}
|
|
247
|
+
return { type: "text", text };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (itemType === "reasoning") {
|
|
251
|
+
const text = msg.item?.text;
|
|
252
|
+
if (state.inThinking) {
|
|
253
|
+
state.inThinking = false;
|
|
254
|
+
if (text) {
|
|
255
|
+
return { type: "thinking_delta", text };
|
|
256
|
+
}
|
|
257
|
+
return { type: "thinking_end" };
|
|
258
|
+
}
|
|
259
|
+
if (text) {
|
|
260
|
+
return { type: "thinking_delta", text };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
case "turn.completed": {
|
|
266
|
+
const usage = msg.usage ? {
|
|
267
|
+
inputTokens: msg.usage.input_tokens,
|
|
268
|
+
outputTokens: msg.usage.output_tokens
|
|
269
|
+
} : void 0;
|
|
270
|
+
if (state.inTool) {
|
|
271
|
+
state.inTool = false;
|
|
272
|
+
state.currentToolId = null;
|
|
273
|
+
return { type: "tool_end", name: "" };
|
|
274
|
+
}
|
|
275
|
+
return { type: "turn_end", usage };
|
|
276
|
+
}
|
|
277
|
+
case "error": {
|
|
278
|
+
const errorMsg = typeof msg.error === "object" ? msg.error?.message : msg.error ?? msg.message;
|
|
279
|
+
if (errorMsg) {
|
|
280
|
+
return { type: "error", message: errorMsg };
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ../run/dist/parsers/cursor.js
|
|
290
|
+
function extractToolInfo(toolCall) {
|
|
291
|
+
if (!toolCall)
|
|
292
|
+
return null;
|
|
293
|
+
if (toolCall.mcpToolCall) {
|
|
294
|
+
const toolName = toolCall.mcpToolCall.args?.toolName || toolCall.mcpToolCall.args?.name;
|
|
295
|
+
if (toolName) {
|
|
296
|
+
return { name: toolName, args: toolCall.mcpToolCall.args?.args };
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
for (const key of Object.keys(toolCall)) {
|
|
300
|
+
if (key === "mcpToolCall")
|
|
301
|
+
continue;
|
|
302
|
+
if (key.endsWith("ToolCall")) {
|
|
303
|
+
const toolName = key.replace("ToolCall", "");
|
|
304
|
+
const callData = toolCall[key];
|
|
305
|
+
return { name: toolName, args: callData?.args };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
function createCursorParser() {
|
|
311
|
+
const state = { inThinking: false, inTool: false };
|
|
312
|
+
return (line) => {
|
|
313
|
+
if (!line.startsWith("{")) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
let msg;
|
|
317
|
+
try {
|
|
318
|
+
msg = JSON.parse(line);
|
|
319
|
+
} catch {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
switch (msg.type) {
|
|
323
|
+
case "system": {
|
|
324
|
+
if (msg.subtype === "init") {
|
|
325
|
+
return {
|
|
326
|
+
type: "init",
|
|
327
|
+
model: msg.model,
|
|
328
|
+
sessionId: msg.session_id,
|
|
329
|
+
cwd: msg.cwd
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
case "assistant": {
|
|
335
|
+
if (!msg.timestamp_ms) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
const text = msg.message?.content?.[0]?.text;
|
|
339
|
+
if (text) {
|
|
340
|
+
return { type: "text", text };
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
case "thinking": {
|
|
345
|
+
if (msg.subtype === "delta") {
|
|
346
|
+
const text = msg.text;
|
|
347
|
+
if (text) {
|
|
348
|
+
if (!state.inThinking) {
|
|
349
|
+
state.inThinking = true;
|
|
350
|
+
return { type: "thinking_start" };
|
|
351
|
+
}
|
|
352
|
+
return { type: "thinking_delta", text };
|
|
353
|
+
}
|
|
354
|
+
} else if (msg.subtype === "completed") {
|
|
355
|
+
if (state.inThinking) {
|
|
356
|
+
state.inThinking = false;
|
|
357
|
+
return { type: "thinking_end" };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
case "tool_call": {
|
|
363
|
+
if (msg.subtype === "started") {
|
|
364
|
+
const toolInfo = extractToolInfo(msg.tool_call);
|
|
365
|
+
if (toolInfo) {
|
|
366
|
+
state.inTool = true;
|
|
367
|
+
return { type: "tool_start", name: toolInfo.name, args: toolInfo.args };
|
|
368
|
+
}
|
|
369
|
+
} else if (msg.subtype === "completed") {
|
|
370
|
+
state.inTool = false;
|
|
371
|
+
return { type: "tool_end", name: "" };
|
|
372
|
+
}
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
case "result": {
|
|
376
|
+
if (state.inTool) {
|
|
377
|
+
state.inTool = false;
|
|
378
|
+
}
|
|
379
|
+
if (msg.is_error && msg.result) {
|
|
380
|
+
return { type: "error", message: msg.result };
|
|
381
|
+
}
|
|
382
|
+
return { type: "done", durationMs: msg.duration_ms };
|
|
383
|
+
}
|
|
384
|
+
case "error": {
|
|
385
|
+
if (msg.error) {
|
|
386
|
+
return { type: "error", message: msg.error };
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return null;
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ../run/dist/parsers/format.js
|
|
396
|
+
function shouldUseColors() {
|
|
397
|
+
if (process.env.TINO_NO_COLOR === "1")
|
|
398
|
+
return false;
|
|
399
|
+
if (process.env.TINO_COLOR === "1")
|
|
400
|
+
return true;
|
|
401
|
+
if (process.env.FORCE_COLOR === "1")
|
|
402
|
+
return true;
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
var useColors = shouldUseColors();
|
|
406
|
+
var colors = {
|
|
407
|
+
reset: useColors ? "\x1B[0m" : "",
|
|
408
|
+
dim: useColors ? "\x1B[2m" : "",
|
|
409
|
+
bold: useColors ? "\x1B[1m" : "",
|
|
410
|
+
cyan: useColors ? "\x1B[36m" : "",
|
|
411
|
+
green: useColors ? "\x1B[32m" : "",
|
|
412
|
+
yellow: useColors ? "\x1B[33m" : "",
|
|
413
|
+
red: useColors ? "\x1B[31m" : "",
|
|
414
|
+
magenta: useColors ? "\x1B[35m" : ""
|
|
415
|
+
};
|
|
416
|
+
var box = {
|
|
417
|
+
topLeft: "\u250C",
|
|
418
|
+
topRight: "\u2510",
|
|
419
|
+
bottomLeft: "\u2514",
|
|
420
|
+
bottomRight: "\u2518",
|
|
421
|
+
horizontal: "\u2500",
|
|
422
|
+
vertical: "\u2502"
|
|
423
|
+
};
|
|
424
|
+
var MAX_ARG_LENGTH = 180;
|
|
425
|
+
function escapeValue(value) {
|
|
426
|
+
if (typeof value === "string") {
|
|
427
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t")}"`;
|
|
428
|
+
}
|
|
429
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
430
|
+
return String(value);
|
|
431
|
+
}
|
|
432
|
+
if (value === null) {
|
|
433
|
+
return "null";
|
|
434
|
+
}
|
|
435
|
+
return JSON.stringify(value);
|
|
436
|
+
}
|
|
437
|
+
function formatToolArgs(args) {
|
|
438
|
+
if (!args || Object.keys(args).length === 0) {
|
|
439
|
+
return "";
|
|
440
|
+
}
|
|
441
|
+
const formatted = Object.entries(args).map(([key, value]) => `${key}=${escapeValue(value)}`).join(" ");
|
|
442
|
+
if (formatted.length > MAX_ARG_LENGTH) {
|
|
443
|
+
return formatted.slice(0, MAX_ARG_LENGTH) + "\u2026";
|
|
444
|
+
}
|
|
445
|
+
return formatted;
|
|
446
|
+
}
|
|
447
|
+
function formatThinkingStart() {
|
|
448
|
+
return `
|
|
449
|
+
|
|
450
|
+
${colors.dim}${box.topLeft}${box.horizontal} \u{1F4AD} thinking ${box.horizontal.repeat(30)}
|
|
451
|
+
${box.vertical} `;
|
|
452
|
+
}
|
|
453
|
+
function formatThinkingContent(text) {
|
|
454
|
+
return text.replace(/\n/g, `
|
|
455
|
+
${colors.dim}${box.vertical}${colors.reset} `);
|
|
456
|
+
}
|
|
457
|
+
function formatThinkingEnd() {
|
|
458
|
+
return `
|
|
459
|
+
${box.bottomLeft}${box.horizontal.repeat(41)}${colors.reset}
|
|
460
|
+
|
|
461
|
+
`;
|
|
462
|
+
}
|
|
463
|
+
function formatToolStart(name, args) {
|
|
464
|
+
const argsLine = formatToolArgs(args);
|
|
465
|
+
let output = `
|
|
466
|
+
|
|
467
|
+
${colors.dim}${box.topLeft}${box.horizontal}${box.horizontal}${colors.reset} ${colors.cyan}${colors.bold}${name}${colors.reset}
|
|
468
|
+
`;
|
|
469
|
+
if (argsLine) {
|
|
470
|
+
output += `${colors.dim}${box.vertical}${colors.reset} ${argsLine}
|
|
471
|
+
`;
|
|
472
|
+
}
|
|
473
|
+
output += `${colors.dim}${box.vertical}${colors.reset} ${colors.yellow}\u23F3 running...${colors.reset}`;
|
|
474
|
+
return output;
|
|
475
|
+
}
|
|
476
|
+
function formatToolEnd() {
|
|
477
|
+
return `\r${colors.dim}${box.vertical}${colors.reset} ${colors.green}\u2713 done${colors.reset}
|
|
478
|
+
${colors.dim}${box.bottomLeft}${box.horizontal.repeat(30)}${colors.reset}
|
|
479
|
+
|
|
480
|
+
`;
|
|
481
|
+
}
|
|
482
|
+
function formatText(text) {
|
|
483
|
+
return text;
|
|
484
|
+
}
|
|
485
|
+
function formatError(message) {
|
|
486
|
+
return `
|
|
487
|
+
${colors.red}${colors.bold}\u274C ERROR:${colors.reset} ${colors.red}${message}${colors.reset}
|
|
488
|
+
`;
|
|
489
|
+
}
|
|
490
|
+
function createFormatterState() {
|
|
491
|
+
return {
|
|
492
|
+
inTool: false,
|
|
493
|
+
inThinking: false,
|
|
494
|
+
currentTool: ""
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ../run/dist/parsers/index.js
|
|
499
|
+
function createParser(agent) {
|
|
500
|
+
switch (agent) {
|
|
501
|
+
case "cursor":
|
|
502
|
+
return createCursorParser();
|
|
503
|
+
case "claude":
|
|
504
|
+
return createClaudeParser();
|
|
505
|
+
case "codex":
|
|
506
|
+
return createCodexParser();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function createStreamFormatter() {
|
|
510
|
+
const state = createFormatterState();
|
|
511
|
+
function format(event) {
|
|
512
|
+
switch (event.type) {
|
|
513
|
+
case "session_start":
|
|
514
|
+
return "";
|
|
515
|
+
case "turn_start":
|
|
516
|
+
return "";
|
|
517
|
+
case "turn_end": {
|
|
518
|
+
let output = "";
|
|
519
|
+
if (state.inTool) {
|
|
520
|
+
state.inTool = false;
|
|
521
|
+
output += ` ${colors.green}\u2713${colors.reset}
|
|
522
|
+
`;
|
|
523
|
+
}
|
|
524
|
+
if (event.usage) {
|
|
525
|
+
output += `
|
|
526
|
+
${colors.dim}tokens: ${event.usage.inputTokens ?? 0} in / ${event.usage.outputTokens ?? 0} out${colors.reset}
|
|
527
|
+
`;
|
|
528
|
+
}
|
|
529
|
+
return output;
|
|
530
|
+
}
|
|
531
|
+
case "thinking_start":
|
|
532
|
+
state.inThinking = true;
|
|
533
|
+
return formatThinkingStart();
|
|
534
|
+
case "thinking_delta":
|
|
535
|
+
if (state.inThinking) {
|
|
536
|
+
return formatThinkingContent(event.text);
|
|
537
|
+
}
|
|
538
|
+
state.inThinking = true;
|
|
539
|
+
return `${formatThinkingStart()}${formatThinkingContent(event.text)}`;
|
|
540
|
+
case "thinking_end":
|
|
541
|
+
if (state.inThinking) {
|
|
542
|
+
state.inThinking = false;
|
|
543
|
+
return formatThinkingEnd();
|
|
544
|
+
}
|
|
545
|
+
return "";
|
|
546
|
+
case "text":
|
|
547
|
+
if (state.inTool) {
|
|
548
|
+
state.inTool = false;
|
|
549
|
+
return formatToolEnd() + "\n" + formatText(event.text);
|
|
550
|
+
}
|
|
551
|
+
if (state.inThinking) {
|
|
552
|
+
state.inThinking = false;
|
|
553
|
+
return formatThinkingEnd() + formatText(event.text);
|
|
554
|
+
}
|
|
555
|
+
return formatText(event.text);
|
|
556
|
+
case "tool_start":
|
|
557
|
+
if (state.inThinking) {
|
|
558
|
+
state.inThinking = false;
|
|
559
|
+
}
|
|
560
|
+
if (state.inTool) {
|
|
561
|
+
state.inTool = false;
|
|
562
|
+
return formatToolEnd() + formatToolStart(event.name, event.args);
|
|
563
|
+
}
|
|
564
|
+
state.inTool = true;
|
|
565
|
+
state.currentTool = event.name;
|
|
566
|
+
return formatToolStart(event.name, event.args);
|
|
567
|
+
case "tool_end":
|
|
568
|
+
if (state.inTool) {
|
|
569
|
+
state.inTool = false;
|
|
570
|
+
state.currentTool = "";
|
|
571
|
+
return formatToolEnd();
|
|
572
|
+
}
|
|
573
|
+
return "";
|
|
574
|
+
case "error":
|
|
575
|
+
return formatError(event.message);
|
|
576
|
+
case "init":
|
|
577
|
+
return "";
|
|
578
|
+
case "done":
|
|
579
|
+
if (state.inTool) {
|
|
580
|
+
state.inTool = false;
|
|
581
|
+
return ` ${colors.green}\u2713${colors.reset}
|
|
582
|
+
`;
|
|
583
|
+
}
|
|
584
|
+
return "";
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
function flush() {
|
|
588
|
+
let output = "";
|
|
589
|
+
if (state.inThinking) {
|
|
590
|
+
output += formatThinkingEnd();
|
|
591
|
+
state.inThinking = false;
|
|
592
|
+
}
|
|
593
|
+
if (state.inTool) {
|
|
594
|
+
output += ` ${colors.green}\u2713${colors.reset}
|
|
595
|
+
`;
|
|
596
|
+
state.inTool = false;
|
|
597
|
+
}
|
|
598
|
+
return output;
|
|
599
|
+
}
|
|
600
|
+
return { format, flush };
|
|
601
|
+
}
|
|
602
|
+
function createLineProcessor(agent) {
|
|
603
|
+
const parser = createParser(agent);
|
|
604
|
+
const formatter = createStreamFormatter();
|
|
605
|
+
return {
|
|
606
|
+
processLine: (line) => {
|
|
607
|
+
const event = parser(line);
|
|
608
|
+
if (!event) {
|
|
609
|
+
return "";
|
|
610
|
+
}
|
|
611
|
+
return formatter.format(event);
|
|
612
|
+
},
|
|
613
|
+
flush: () => formatter.flush()
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// ../run/dist/agents/utils.js
|
|
618
|
+
function buildEnv({ apiKeyEnv, apiKey, request }) {
|
|
619
|
+
const forceColor = process.stdout.isTTY ? "1" : process.env.FORCE_COLOR ?? "1";
|
|
620
|
+
return {
|
|
621
|
+
...Object.fromEntries(Object.entries(process.env).filter((entry) => entry[1] !== void 0)),
|
|
622
|
+
...Object.fromEntries(Object.entries(request.env ?? {}).filter((entry) => entry[1] !== void 0)),
|
|
623
|
+
...apiKey ? { [apiKeyEnv]: apiKey } : {},
|
|
624
|
+
FORCE_COLOR: forceColor
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function shellEscape(arg) {
|
|
628
|
+
if (!/[^a-zA-Z0-9_\-=.:\/]/.test(arg)) {
|
|
629
|
+
return arg;
|
|
630
|
+
}
|
|
631
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
632
|
+
}
|
|
633
|
+
async function runWithStreaming({ command, args, request, env, runInShell, stdinInput }) {
|
|
634
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
635
|
+
const escapedArgs = runInShell ? args.map(shellEscape) : args;
|
|
636
|
+
const baseCommand = [command, ...escapedArgs].join(" ");
|
|
637
|
+
const execCommand = runInShell ? "/bin/bash" : command;
|
|
638
|
+
const execArgs = runInShell ? ["-lc", baseCommand] : args;
|
|
639
|
+
const child = spawn(execCommand, execArgs, {
|
|
640
|
+
cwd: request.cwd,
|
|
641
|
+
env,
|
|
642
|
+
stdio: [stdinInput ? "pipe" : "ignore", "pipe", "pipe"]
|
|
643
|
+
});
|
|
644
|
+
if (stdinInput && child.stdin) {
|
|
645
|
+
child.stdin.write(stdinInput);
|
|
646
|
+
child.stdin.end();
|
|
647
|
+
}
|
|
648
|
+
const stdoutChunks = [];
|
|
649
|
+
const stderrChunks = [];
|
|
650
|
+
const formattedChunks = [];
|
|
651
|
+
const shouldFormat = request.streamOutput ?? false;
|
|
652
|
+
const lineProcessor = shouldFormat ? createLineProcessor(request.agent) : null;
|
|
653
|
+
let stdoutBuffer = "";
|
|
654
|
+
const quietOutput = request.quietOutput ?? false;
|
|
655
|
+
child.stdout?.on("data", (chunk) => {
|
|
656
|
+
stdoutChunks.push(chunk);
|
|
657
|
+
if (lineProcessor) {
|
|
658
|
+
stdoutBuffer += chunk.toString("utf-8");
|
|
659
|
+
const lines = stdoutBuffer.split("\n");
|
|
660
|
+
stdoutBuffer = lines.pop() ?? "";
|
|
661
|
+
for (const line of lines) {
|
|
662
|
+
const formatted = lineProcessor.processLine(line);
|
|
663
|
+
if (formatted) {
|
|
664
|
+
formattedChunks.push(formatted);
|
|
665
|
+
if (!quietOutput) {
|
|
666
|
+
process.stdout.write(formatted);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
} else if (!quietOutput) {
|
|
671
|
+
process.stdout.write(chunk);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
child.stderr?.on("data", (chunk) => {
|
|
675
|
+
stderrChunks.push(chunk);
|
|
676
|
+
if (!quietOutput) {
|
|
677
|
+
process.stderr.write(chunk);
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
const exitCode = await new Promise((resolve) => {
|
|
681
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
682
|
+
});
|
|
683
|
+
if (lineProcessor) {
|
|
684
|
+
if (stdoutBuffer) {
|
|
685
|
+
const formatted = lineProcessor.processLine(stdoutBuffer);
|
|
686
|
+
if (formatted) {
|
|
687
|
+
formattedChunks.push(formatted);
|
|
688
|
+
if (!quietOutput) {
|
|
689
|
+
process.stdout.write(formatted);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
const flushed = lineProcessor.flush();
|
|
694
|
+
if (flushed) {
|
|
695
|
+
formattedChunks.push(flushed);
|
|
696
|
+
if (!quietOutput) {
|
|
697
|
+
process.stdout.write(flushed);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
const endedAt = /* @__PURE__ */ new Date();
|
|
702
|
+
return {
|
|
703
|
+
output: {
|
|
704
|
+
agent: request.agent,
|
|
705
|
+
model: request.model,
|
|
706
|
+
prompt: request.prompt,
|
|
707
|
+
startedAt: startedAt.toISOString(),
|
|
708
|
+
endedAt: endedAt.toISOString(),
|
|
709
|
+
durationMs: endedAt.getTime() - startedAt.getTime(),
|
|
710
|
+
exitCode,
|
|
711
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
712
|
+
stderr: Buffer.concat(stderrChunks).toString("utf-8"),
|
|
713
|
+
status: exitCode === 0 ? "success" : "failure"
|
|
714
|
+
},
|
|
715
|
+
formattedText: formattedChunks.join("")
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// ../run/dist/agents/claude.js
|
|
720
|
+
var claudeAgent = {
|
|
721
|
+
name: "claude",
|
|
722
|
+
command: "claude",
|
|
723
|
+
runInShell: false,
|
|
724
|
+
args: ({ model, streamOutput, mcpConfigPath }) => {
|
|
725
|
+
const args = ["-p", "--dangerously-skip-permissions"];
|
|
726
|
+
if (streamOutput) {
|
|
727
|
+
args.push("--output-format", "stream-json", "--verbose");
|
|
728
|
+
} else {
|
|
729
|
+
args.push("--output-format", "text");
|
|
730
|
+
}
|
|
731
|
+
if (mcpConfigPath) {
|
|
732
|
+
args.push("--mcp-config", mcpConfigPath);
|
|
733
|
+
}
|
|
734
|
+
if (model) {
|
|
735
|
+
args.push("--model", model);
|
|
736
|
+
}
|
|
737
|
+
return args;
|
|
738
|
+
},
|
|
739
|
+
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
740
|
+
installCommand: "npm i -g @anthropic-ai/claude-code"
|
|
741
|
+
};
|
|
742
|
+
async function runClaude(request, args, env) {
|
|
743
|
+
return runWithStreaming({
|
|
744
|
+
command: "claude",
|
|
745
|
+
args,
|
|
746
|
+
request,
|
|
747
|
+
env,
|
|
748
|
+
runInShell: false,
|
|
749
|
+
stdinInput: request.prompt
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// ../run/dist/agents/codex.js
|
|
754
|
+
var codexAgent = {
|
|
755
|
+
name: "codex",
|
|
756
|
+
command: "codex",
|
|
757
|
+
runInShell: false,
|
|
758
|
+
args: ({ workspacePath }) => {
|
|
759
|
+
const args = ["exec", "--full-auto", "--json", "--skip-git-repo-check"];
|
|
760
|
+
if (workspacePath) {
|
|
761
|
+
args.push("-C", workspacePath);
|
|
762
|
+
}
|
|
763
|
+
return args;
|
|
764
|
+
},
|
|
765
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
766
|
+
installCommand: "npm i -g @openai/codex"
|
|
767
|
+
};
|
|
768
|
+
async function runCodex(request, args, env) {
|
|
769
|
+
return runWithStreaming({
|
|
770
|
+
command: "codex",
|
|
771
|
+
args,
|
|
772
|
+
request,
|
|
773
|
+
env,
|
|
774
|
+
runInShell: false,
|
|
775
|
+
stdinInput: request.prompt
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// ../run/dist/agents/cursor.js
|
|
780
|
+
var cursorAgent = {
|
|
781
|
+
name: "cursor",
|
|
782
|
+
command: "cursor",
|
|
783
|
+
runInShell: true,
|
|
784
|
+
args: ({ prompt, model, approveMcps, browser, streamOutput, approvalPolicy, workspacePath }) => {
|
|
785
|
+
const args = ["agent", "--print", "--force"];
|
|
786
|
+
args.push("--output-format", streamOutput ? "stream-json" : "text");
|
|
787
|
+
if (streamOutput) {
|
|
788
|
+
args.push("--stream-partial-output");
|
|
789
|
+
}
|
|
790
|
+
if ((approvalPolicy ?? "on-request") !== "never" && approveMcps) {
|
|
791
|
+
args.push("--approve-mcps");
|
|
792
|
+
}
|
|
793
|
+
if (browser) {
|
|
794
|
+
args.push("--browser");
|
|
795
|
+
}
|
|
796
|
+
if (workspacePath) {
|
|
797
|
+
args.push("--workspace", workspacePath);
|
|
798
|
+
}
|
|
799
|
+
if (model) {
|
|
800
|
+
args.push("--model", model);
|
|
801
|
+
}
|
|
802
|
+
args.push(prompt);
|
|
803
|
+
return args;
|
|
804
|
+
},
|
|
805
|
+
apiKeyEnv: "CURSOR_API_KEY",
|
|
806
|
+
installCommand: "curl https://cursor.com/install -fsS | bash"
|
|
807
|
+
};
|
|
808
|
+
async function runCursor(request, args, env) {
|
|
809
|
+
return runWithStreaming({
|
|
810
|
+
command: "cursor",
|
|
811
|
+
args,
|
|
812
|
+
request,
|
|
813
|
+
env,
|
|
814
|
+
runInShell: true
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// ../run/dist/agents/index.js
|
|
819
|
+
var AGENTS = {
|
|
820
|
+
cursor: cursorAgent,
|
|
821
|
+
claude: claudeAgent,
|
|
822
|
+
codex: codexAgent
|
|
823
|
+
};
|
|
824
|
+
function getAgentConfig(agent) {
|
|
825
|
+
return AGENTS[agent];
|
|
826
|
+
}
|
|
827
|
+
async function ensureAgentInstalled(agent, command, installCommand) {
|
|
828
|
+
const config = getAgentConfig(agent);
|
|
829
|
+
const agentCommand = command ?? config.command;
|
|
830
|
+
try {
|
|
831
|
+
await execa("bash", ["-lc", `command -v ${agentCommand}`]);
|
|
832
|
+
} catch {
|
|
833
|
+
const commandToRun = installCommand ?? config.installCommand;
|
|
834
|
+
await execa("bash", ["-lc", commandToRun], { stdio: "inherit" });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
function getRequiredApiKey(agent) {
|
|
838
|
+
return getAgentConfig(agent).apiKeyEnv;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
export {
|
|
842
|
+
buildEnv,
|
|
843
|
+
runClaude,
|
|
844
|
+
runCodex,
|
|
845
|
+
runCursor,
|
|
846
|
+
getAgentConfig,
|
|
847
|
+
ensureAgentInstalled,
|
|
848
|
+
getRequiredApiKey
|
|
849
|
+
};
|