0agent 1.0.30 → 1.0.32
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/bin/chat.js +49 -4
- package/dist/daemon.mjs +41 -13
- package/package.json +1 -1
package/bin/chat.js
CHANGED
|
@@ -166,7 +166,7 @@ async function connectWS() {
|
|
|
166
166
|
ws.send(JSON.stringify({ type: 'subscribe', topics: ['sessions', 'graph', 'insights'] }));
|
|
167
167
|
});
|
|
168
168
|
ws.on('message', data => handleWsEvent(JSON.parse(data.toString())));
|
|
169
|
-
ws.on('close', () => { wsReady = false; setTimeout(connectWS,
|
|
169
|
+
ws.on('close', () => { wsReady = false; setTimeout(connectWS, 800); }); // faster reconnect
|
|
170
170
|
ws.on('error', () => { wsReady = false; });
|
|
171
171
|
} catch {}
|
|
172
172
|
}
|
|
@@ -349,6 +349,50 @@ async function runTask(input) {
|
|
|
349
349
|
const s = await res.json();
|
|
350
350
|
sessionId = s.session_id ?? s.id;
|
|
351
351
|
spinner.start('Thinking'); // show immediately after session created
|
|
352
|
+
|
|
353
|
+
// Polling fallback — runs concurrently with WS events.
|
|
354
|
+
// Catches completion when WS is disconnected (e.g. daemon just restarted).
|
|
355
|
+
let lastPolledStep = 0;
|
|
356
|
+
const sid = sessionId;
|
|
357
|
+
const pollTimer = setInterval(async () => {
|
|
358
|
+
if (!pendingResolve || sessionId !== sid) { clearInterval(pollTimer); return; }
|
|
359
|
+
try {
|
|
360
|
+
const r = await fetch(`${BASE_URL}/api/sessions/${sid}`, { signal: AbortSignal.timeout(2000) });
|
|
361
|
+
const session = await r.json();
|
|
362
|
+
|
|
363
|
+
// Show any new steps not yet shown via WS
|
|
364
|
+
const steps = session.steps ?? [];
|
|
365
|
+
for (let j = lastPolledStep; j < steps.length; j++) {
|
|
366
|
+
spinner.stop();
|
|
367
|
+
console.log(` \x1b[2m›\x1b[0m ${steps[j].description}`);
|
|
368
|
+
spinner.start(steps[j].description.slice(0, 50));
|
|
369
|
+
}
|
|
370
|
+
lastPolledStep = steps.length;
|
|
371
|
+
|
|
372
|
+
if (session.status === 'completed' || session.status === 'failed') {
|
|
373
|
+
clearInterval(pollTimer);
|
|
374
|
+
if (!pendingResolve) return; // WS already handled it
|
|
375
|
+
spinner.stop();
|
|
376
|
+
if (session.status === 'completed') {
|
|
377
|
+
const out = session.result?.output;
|
|
378
|
+
if (out && typeof out === 'string') {
|
|
379
|
+
console.log(`\n ${out}`);
|
|
380
|
+
}
|
|
381
|
+
if (session.result?.files_written?.length) console.log(` \x1b[32m✓\x1b[0m Files: ${session.result.files_written.join(', ')}`);
|
|
382
|
+
if (session.result?.tokens_used) console.log(` \x1b[2m${session.result.tokens_used} tokens\x1b[0m`);
|
|
383
|
+
console.log(`\n \x1b[32m✓ Done\x1b[0m\n`);
|
|
384
|
+
} else {
|
|
385
|
+
console.log(`\n \x1b[31m✗ Failed:\x1b[0m ${session.error}\n`);
|
|
386
|
+
}
|
|
387
|
+
const resolve_ = pendingResolve;
|
|
388
|
+
pendingResolve = null;
|
|
389
|
+
sessionId = null;
|
|
390
|
+
resolve_();
|
|
391
|
+
rl.prompt();
|
|
392
|
+
}
|
|
393
|
+
} catch {}
|
|
394
|
+
}, 1500);
|
|
395
|
+
|
|
352
396
|
return new Promise(resolve => { pendingResolve = resolve; });
|
|
353
397
|
} catch (e) {
|
|
354
398
|
console.log(` ${fmt(C.red, '✗')} ${e.message}`);
|
|
@@ -727,9 +771,10 @@ rl.on('line', async (input) => {
|
|
|
727
771
|
rl.prompt();
|
|
728
772
|
} else {
|
|
729
773
|
await runTask(line);
|
|
730
|
-
//
|
|
731
|
-
//
|
|
732
|
-
if
|
|
774
|
+
// runTask resolves when session completes (via WS or polling fallback)
|
|
775
|
+
// rl.prompt() may already have been called by the handler that resolved it,
|
|
776
|
+
// but calling it again is a safe no-op if readline is already prompting
|
|
777
|
+
if (!streaming) rl.prompt();
|
|
733
778
|
}
|
|
734
779
|
});
|
|
735
780
|
|
package/dist/daemon.mjs
CHANGED
|
@@ -2328,7 +2328,7 @@ var init_ShellCapability = __esm({
|
|
|
2328
2328
|
description = "Execute shell commands in the working directory.";
|
|
2329
2329
|
toolDefinition = {
|
|
2330
2330
|
name: "shell_exec",
|
|
2331
|
-
description: "Execute a shell command.
|
|
2331
|
+
description: "Execute a shell command. For background servers use: cmd > /tmp/0agent-server.log 2>&1 & Returns stdout+stderr.",
|
|
2332
2332
|
input_schema: {
|
|
2333
2333
|
type: "object",
|
|
2334
2334
|
properties: {
|
|
@@ -2344,25 +2344,49 @@ var init_ShellCapability = __esm({
|
|
|
2344
2344
|
const start = Date.now();
|
|
2345
2345
|
return new Promise((resolve_) => {
|
|
2346
2346
|
const chunks = [];
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
proc.stdout.on("data", (d) => chunks.push(d.toString()));
|
|
2353
|
-
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
2354
|
-
proc.on("close", (code) => {
|
|
2347
|
+
let settled = false;
|
|
2348
|
+
const done = (code, signal) => {
|
|
2349
|
+
if (settled) return;
|
|
2350
|
+
settled = true;
|
|
2351
|
+
clearTimeout(timer);
|
|
2355
2352
|
const output = chunks.join("").trim();
|
|
2353
|
+
const success = code === 0 || code === null && !!signal;
|
|
2356
2354
|
resolve_({
|
|
2357
|
-
success
|
|
2358
|
-
output: output || (
|
|
2355
|
+
success,
|
|
2356
|
+
output: output || (success ? "(no output)" : `exit ${code ?? signal}`),
|
|
2359
2357
|
duration_ms: Date.now() - start,
|
|
2360
|
-
|
|
2358
|
+
...!success && { error: `exit ${code ?? signal}` }
|
|
2361
2359
|
});
|
|
2360
|
+
};
|
|
2361
|
+
const proc = spawn("bash", ["-c", command], {
|
|
2362
|
+
cwd,
|
|
2363
|
+
env: { ...process.env, TERM: "dumb" }
|
|
2364
|
+
// DO NOT set `timeout` here — we manage it manually via timer
|
|
2365
|
+
// so we can resolve on `exit` rather than waiting for `close`
|
|
2362
2366
|
});
|
|
2367
|
+
proc.stdout.on("data", (d) => chunks.push(d.toString()));
|
|
2368
|
+
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
2369
|
+
proc.on("exit", (code) => done(code));
|
|
2363
2370
|
proc.on("error", (err) => {
|
|
2371
|
+
settled = true;
|
|
2372
|
+
clearTimeout(timer);
|
|
2364
2373
|
resolve_({ success: false, output: err.message, error: err.message, duration_ms: Date.now() - start });
|
|
2365
2374
|
});
|
|
2375
|
+
const timer = setTimeout(() => {
|
|
2376
|
+
if (settled) return;
|
|
2377
|
+
try {
|
|
2378
|
+
proc.kill("SIGKILL");
|
|
2379
|
+
} catch {
|
|
2380
|
+
}
|
|
2381
|
+
settled = true;
|
|
2382
|
+
const output = chunks.join("").trim();
|
|
2383
|
+
resolve_({
|
|
2384
|
+
success: false,
|
|
2385
|
+
output: output || "(timed out)",
|
|
2386
|
+
error: `timed out after ${timeout}ms`,
|
|
2387
|
+
duration_ms: Date.now() - start
|
|
2388
|
+
});
|
|
2389
|
+
}, timeout);
|
|
2366
2390
|
});
|
|
2367
2391
|
}
|
|
2368
2392
|
};
|
|
@@ -2858,7 +2882,11 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
2858
2882
|
``,
|
|
2859
2883
|
`Instructions:`,
|
|
2860
2884
|
`- Use tools to actually accomplish tasks, don't just describe what to do`,
|
|
2861
|
-
`- For web servers:
|
|
2885
|
+
`- For web servers/background processes: ALWAYS redirect output to avoid hanging:`,
|
|
2886
|
+
` cmd > /tmp/0agent-server.log 2>&1 &`,
|
|
2887
|
+
` Example: python3 -m http.server 3000 > /tmp/0agent-server.log 2>&1 &`,
|
|
2888
|
+
` Example: node server.js > /tmp/0agent-server.log 2>&1 &`,
|
|
2889
|
+
` NEVER run background commands without redirecting output.`,
|
|
2862
2890
|
`- For npm/node projects: check package.json first with read_file or list_dir`,
|
|
2863
2891
|
`- After write_file, verify with read_file if needed`,
|
|
2864
2892
|
`- After shell_exec, check output for errors and retry if needed`,
|