@testchimp/cli 0.1.37 → 0.1.38
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/chimphands/run.js +79 -28
- package/package.json +1 -1
package/dist/chimphands/run.js
CHANGED
|
@@ -63,7 +63,11 @@ function extractOpencodeFatalError(raw) {
|
|
|
63
63
|
try {
|
|
64
64
|
const ev = JSON.parse(line);
|
|
65
65
|
if (ev.type === "error" || ev.name === "UnknownError") {
|
|
66
|
-
const msg = ev.data?.message ||
|
|
66
|
+
const msg = ev.error?.data?.message ||
|
|
67
|
+
ev.error?.message ||
|
|
68
|
+
ev.data?.message ||
|
|
69
|
+
ev.message ||
|
|
70
|
+
line;
|
|
67
71
|
const ref = ev.data?.ref ? ` (ref ${ev.data.ref})` : "";
|
|
68
72
|
return `${msg}${ref}`;
|
|
69
73
|
}
|
|
@@ -83,6 +87,27 @@ function extractOpencodeFatalError(raw) {
|
|
|
83
87
|
}
|
|
84
88
|
return null;
|
|
85
89
|
}
|
|
90
|
+
function parseOpencodeEvent(line) {
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(line);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function formatToolUseContent(part) {
|
|
99
|
+
const title = part.state?.title || part.tool || "tool";
|
|
100
|
+
const output = part.state?.output?.trim();
|
|
101
|
+
if (output)
|
|
102
|
+
return `[${title}]\n${output}`;
|
|
103
|
+
return `[${title}]`;
|
|
104
|
+
}
|
|
105
|
+
function opencodeMessageId(prefix, part) {
|
|
106
|
+
const raw = part?.id || part?.messageID;
|
|
107
|
+
if (!raw)
|
|
108
|
+
return undefined;
|
|
109
|
+
return `${prefix}${raw}`;
|
|
110
|
+
}
|
|
86
111
|
function summarizeOpencodeFailure(stderr, stdout, exitCode) {
|
|
87
112
|
for (const chunk of [stderr, stdout]) {
|
|
88
113
|
for (const line of chunk.split("\n")) {
|
|
@@ -169,41 +194,65 @@ function runOpencode(prompt, model, childEnv, postEvent) {
|
|
|
169
194
|
return new Promise((resolve) => {
|
|
170
195
|
let buf = "";
|
|
171
196
|
let fatalError = null;
|
|
197
|
+
const textByPartId = new Map();
|
|
198
|
+
const handleOpencodeLine = (line) => {
|
|
199
|
+
if (!line.trim())
|
|
200
|
+
return;
|
|
201
|
+
const fatal = extractOpencodeFatalError(line);
|
|
202
|
+
if (fatal) {
|
|
203
|
+
fatalError = fatal;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const ev = parseOpencodeEvent(line);
|
|
207
|
+
if (!ev?.type)
|
|
208
|
+
return;
|
|
209
|
+
switch (ev.type) {
|
|
210
|
+
case "text": {
|
|
211
|
+
const chunk = ev.part?.text;
|
|
212
|
+
if (!chunk)
|
|
213
|
+
return;
|
|
214
|
+
const partId = ev.part?.id || ev.part?.messageID;
|
|
215
|
+
if (!partId) {
|
|
216
|
+
postEvent(ROLE_ASSISTANT, chunk);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const next = (textByPartId.get(partId) || "") + chunk;
|
|
220
|
+
textByPartId.set(partId, next);
|
|
221
|
+
postEvent(ROLE_ASSISTANT, next, undefined, opencodeMessageId("oc_text_", ev.part));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
case "tool_use": {
|
|
225
|
+
if (ev.part?.state?.status !== "completed")
|
|
226
|
+
return;
|
|
227
|
+
postEvent(ROLE_TOOL, formatToolUseContent(ev.part), undefined, opencodeMessageId("oc_tool_", ev.part));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
case "error": {
|
|
231
|
+
const msg = ev.error?.data?.message ||
|
|
232
|
+
ev.error?.message ||
|
|
233
|
+
line.trim();
|
|
234
|
+
if (msg)
|
|
235
|
+
fatalError = msg;
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
case "step_start":
|
|
239
|
+
case "step_finish":
|
|
240
|
+
return;
|
|
241
|
+
default:
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
172
245
|
child.stdout.on("data", (chunk) => {
|
|
173
246
|
buf += chunk.toString();
|
|
174
247
|
const lines = buf.split("\n");
|
|
175
248
|
buf = lines.pop() || "";
|
|
176
249
|
for (const line of lines) {
|
|
177
|
-
|
|
178
|
-
continue;
|
|
179
|
-
const fatal = extractOpencodeFatalError(line);
|
|
180
|
-
if (fatal) {
|
|
181
|
-
fatalError = fatal;
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
let content = line;
|
|
185
|
-
let role = ROLE_ASSISTANT;
|
|
186
|
-
try {
|
|
187
|
-
const ev = JSON.parse(line);
|
|
188
|
-
content = ev.content || ev.message || ev.text || JSON.stringify(ev);
|
|
189
|
-
if (ev.type === "tool" || ev.role === "tool")
|
|
190
|
-
role = ROLE_TOOL;
|
|
191
|
-
if (ev.type === "status")
|
|
192
|
-
role = ROLE_STATUS;
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
/* plain line */
|
|
196
|
-
}
|
|
197
|
-
postEvent(role, content);
|
|
250
|
+
handleOpencodeLine(line);
|
|
198
251
|
}
|
|
199
252
|
});
|
|
200
253
|
child.on("close", (code) => {
|
|
201
254
|
if (buf.trim()) {
|
|
202
|
-
|
|
203
|
-
if (fatal)
|
|
204
|
-
fatalError = fatal;
|
|
205
|
-
else if (!fatalError)
|
|
206
|
-
postEvent(ROLE_ASSISTANT, buf.trim());
|
|
255
|
+
handleOpencodeLine(buf.trim());
|
|
207
256
|
}
|
|
208
257
|
const stderrFatal = extractOpencodeFatalError(err);
|
|
209
258
|
if (stderrFatal)
|
|
@@ -327,12 +376,14 @@ export async function runChimphands(opts) {
|
|
|
327
376
|
let idle = false;
|
|
328
377
|
let closed = false;
|
|
329
378
|
let lastUserActivity = Date.now();
|
|
330
|
-
const postEvent = (role, content, status) => {
|
|
379
|
+
const postEvent = (role, content, status, messageId) => {
|
|
331
380
|
const body = {
|
|
332
381
|
sessionId,
|
|
333
382
|
role,
|
|
334
383
|
content: String(content || "").slice(0, 20000),
|
|
335
384
|
};
|
|
385
|
+
if (messageId)
|
|
386
|
+
body.messageId = messageId;
|
|
336
387
|
if (status != null)
|
|
337
388
|
body.status = status;
|
|
338
389
|
postJsonFireAndForget(backend, apiKey, "/api/chimphands/post_agent_event", body);
|
package/package.json
CHANGED