0agent 1.0.41 → 1.0.42

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.
Files changed (2) hide show
  1. package/bin/0agent.js +46 -20
  2. package/package.json +1 -1
package/bin/0agent.js CHANGED
@@ -369,11 +369,20 @@ ${ghToken && ghOwner ? `\ngithub_memory:\n enabled: true\n token: "${ghToken}"
369
369
  console.log(' ✓ Built-in skills installed');
370
370
  }
371
371
 
372
- // Always kill any existing daemon so the new config (with API key) is loaded
373
- try { stopDaemon(); await sleep(800); } catch {}
372
+ // Force-kill any running daemon so new config is loaded fresh
373
+ await forceStopDaemon();
374
374
 
375
- console.log('\n Starting daemon...\n');
375
+ // Start fresh daemon with new config
376
+ console.log('\n Starting...');
376
377
  await startDaemon();
378
+
379
+ // Open chat TUI immediately — no manual steps needed
380
+ const chatSc = resolve(dirname(new URL(import.meta.url).pathname), 'chat.js');
381
+ if (existsSync(chatSc)) {
382
+ const { spawn: sp } = await import('node:child_process');
383
+ const p = sp(process.execPath, [chatSc], { stdio: 'inherit' });
384
+ await new Promise(r => p.on('close', r));
385
+ }
377
386
  }
378
387
 
379
388
  function detectSandboxes() {
@@ -391,9 +400,17 @@ function detectSandboxes() {
391
400
  // ─── Daemon lifecycle ─────────────────────────────────────────────────────
392
401
 
393
402
  async function startDaemon() {
403
+ // If still running (e.g. stop was called just before), wait a bit
394
404
  if (await isDaemonRunning()) {
395
- console.log(' Daemon already running on port 4200. Run `0agent status`.');
396
- return;
405
+ // Give it up to 3s to die before giving up
406
+ for (let i = 0; i < 6; i++) {
407
+ await sleep(500);
408
+ if (!await isDaemonRunning()) break;
409
+ }
410
+ if (await isDaemonRunning()) {
411
+ console.log(' Daemon already running on port 4200. Run `0agent status`.');
412
+ return;
413
+ }
397
414
  }
398
415
 
399
416
  if (!existsSync(CONFIG_PATH)) {
@@ -423,33 +440,42 @@ async function startDaemon() {
423
440
  child.unref();
424
441
 
425
442
  // Wait for daemon to be ready (poll /api/health)
426
- process.stdout.write(' Starting');
427
443
  for (let i = 0; i < 30; i++) {
428
444
  await sleep(500);
429
- process.stdout.write('.');
430
445
  if (await isDaemonRunning()) {
431
- console.log(' ✓\n');
432
- console.log(` Daemon running on http://localhost:4200`);
433
- console.log(` Dashboard: http://localhost:4200`);
434
- console.log(` Run: 0agent run "your task"\n`);
446
+ process.stdout.write(` \x1b[32m✓\x1b[0m Daemon ready\n`);
435
447
  return;
436
448
  }
437
449
  }
438
- console.log('\n Daemon did not start. Check logs: 0agent logs');
450
+ console.log(' Daemon did not start in time. Check: 0agent logs');
439
451
  }
440
452
 
441
453
  function stopDaemon() {
442
- if (!existsSync(PID_PATH)) {
454
+ // Try PID file first
455
+ if (existsSync(PID_PATH)) {
456
+ const pid = parseInt(readFileSync(PID_PATH, 'utf8').trim(), 10);
457
+ try { process.kill(pid, 'SIGTERM'); } catch {}
458
+ } else {
443
459
  console.log(' No daemon PID file found. Is it running?');
444
- return;
445
460
  }
446
- const pid = parseInt(readFileSync(PID_PATH, 'utf8').trim(), 10);
447
- try {
448
- process.kill(pid, 'SIGTERM');
449
- console.log(` Sent SIGTERM to daemon (pid ${pid}). Shutting down...`);
450
- } catch (e) {
451
- console.log(` Could not stop daemon: ${e instanceof Error ? e.message : e}`);
461
+ // Also kill by process name as a fallback
462
+ try { execSync('pkill -f "daemon.mjs" 2>/dev/null; true', { stdio: 'ignore' }); } catch {}
463
+ }
464
+
465
+ // Forcefully kill any running daemon regardless of PID file state.
466
+ // Used after init to ensure fresh config is picked up.
467
+ async function forceStopDaemon() {
468
+ // Kill by PID file if present
469
+ if (existsSync(PID_PATH)) {
470
+ const pid = parseInt(readFileSync(PID_PATH, 'utf8').trim(), 10);
471
+ try { process.kill(pid, 'SIGTERM'); } catch {}
452
472
  }
473
+ // Kill by process name (catches daemons started by chat.js or other means)
474
+ try { execSync('pkill -f "daemon.mjs" 2>/dev/null; true', { stdio: 'ignore' }); } catch {}
475
+ // Kill by port 4200 (last resort)
476
+ try { execSync('lsof -ti:4200 | xargs kill -9 2>/dev/null; true', { stdio: 'ignore' }); } catch {}
477
+ // Wait for port to be free
478
+ await sleep(1200);
453
479
  }
454
480
 
455
481
  async function showStatus() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0agent",
3
- "version": "1.0.41",
3
+ "version": "1.0.42",
4
4
  "description": "A persistent, learning AI agent that runs on your machine. An agent that learns.",
5
5
  "private": false,
6
6
  "license": "Apache-2.0",