0agent 1.0.25 → 1.0.27
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/0agent.js +19 -1
- package/bin/chat.js +111 -39
- package/dist/daemon.mjs +177 -110
- package/package.json +1 -1
package/bin/0agent.js
CHANGED
|
@@ -1318,8 +1318,26 @@ async function isDaemonRunning() {
|
|
|
1318
1318
|
}
|
|
1319
1319
|
}
|
|
1320
1320
|
|
|
1321
|
+
async function isDaemonFresh() {
|
|
1322
|
+
// Check if the running daemon has the /api/llm/ping route (1.0.26+)
|
|
1323
|
+
try {
|
|
1324
|
+
const res = await fetch(`${BASE_URL}/api/llm/ping`, { method: 'POST', signal: AbortSignal.timeout(2000) });
|
|
1325
|
+
return res.status !== 404;
|
|
1326
|
+
} catch { return false; }
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1321
1329
|
async function requireDaemon() {
|
|
1322
|
-
if (await isDaemonRunning())
|
|
1330
|
+
if (await isDaemonRunning()) {
|
|
1331
|
+
// Kill and restart if it's an old version without key routes
|
|
1332
|
+
if (!(await isDaemonFresh())) {
|
|
1333
|
+
process.stdout.write(' Updating daemon...');
|
|
1334
|
+
try { execSync('pkill -f "daemon.mjs" 2>/dev/null; true', { stdio: 'ignore' }); } catch {}
|
|
1335
|
+
await sleep(800);
|
|
1336
|
+
// fall through to start fresh daemon below
|
|
1337
|
+
} else {
|
|
1338
|
+
return; // up to date, no action needed
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1323
1341
|
|
|
1324
1342
|
// Auto-start if config exists — no manual `0agent start` needed
|
|
1325
1343
|
if (!existsSync(CONFIG_PATH)) {
|
package/bin/chat.js
CHANGED
|
@@ -457,54 +457,108 @@ printInsights();
|
|
|
457
457
|
// Connect WebSocket for live events
|
|
458
458
|
connectWS();
|
|
459
459
|
|
|
460
|
-
// ── Startup:
|
|
460
|
+
// ── Startup: ensure fresh daemon + verify LLM ────────────────────────────────
|
|
461
|
+
async function _spawnDaemon() {
|
|
462
|
+
const pkgRoot = resolve(new URL(import.meta.url).pathname, '..', '..');
|
|
463
|
+
const bundled = resolve(pkgRoot, 'dist', 'daemon.mjs');
|
|
464
|
+
if (!existsSync(bundled) || !existsSync(CONFIG_PATH)) return false;
|
|
465
|
+
const { spawn } = await import('node:child_process');
|
|
466
|
+
const child = spawn(process.execPath, [bundled], {
|
|
467
|
+
detached: true, stdio: 'ignore',
|
|
468
|
+
env: { ...process.env, ZEROAGENT_CONFIG: CONFIG_PATH },
|
|
469
|
+
});
|
|
470
|
+
child.unref();
|
|
471
|
+
// Wait up to 10s for daemon to be ready
|
|
472
|
+
for (let i = 0; i < 20; i++) {
|
|
473
|
+
await new Promise(r => setTimeout(r, 500));
|
|
474
|
+
try {
|
|
475
|
+
await fetch(`${BASE_URL}/api/health`, { signal: AbortSignal.timeout(500) });
|
|
476
|
+
return true;
|
|
477
|
+
} catch {}
|
|
478
|
+
}
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
async function _safeJsonFetch(url, opts) {
|
|
483
|
+
const res = await fetch(url, opts);
|
|
484
|
+
const text = await res.text();
|
|
485
|
+
try { return { status: res.status, data: JSON.parse(text) }; }
|
|
486
|
+
catch { return { status: res.status, data: null, raw: text }; }
|
|
487
|
+
}
|
|
488
|
+
|
|
461
489
|
(async () => {
|
|
462
490
|
const startSpin = new Spinner('Starting daemon');
|
|
463
491
|
|
|
464
|
-
// Step 1:
|
|
492
|
+
// Step 1: Check if daemon is running AND up-to-date (has /api/llm/ping)
|
|
465
493
|
let daemonOk = false;
|
|
494
|
+
let needsRestart = false;
|
|
495
|
+
|
|
466
496
|
try {
|
|
467
497
|
await fetch(`${BASE_URL}/api/health`, { signal: AbortSignal.timeout(1500) });
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
child.unref();
|
|
478
|
-
for (let i = 0; i < 20; i++) {
|
|
479
|
-
await new Promise(r => setTimeout(r, 500));
|
|
480
|
-
try { await fetch(`${BASE_URL}/api/health`, { signal: AbortSignal.timeout(500) }); daemonOk = true; break; } catch {}
|
|
481
|
-
}
|
|
498
|
+
// Daemon running — check if it has the new /api/llm/ping route
|
|
499
|
+
const probe = await _safeJsonFetch(`${BASE_URL}/api/llm/ping`, {
|
|
500
|
+
method: 'POST', signal: AbortSignal.timeout(3000),
|
|
501
|
+
});
|
|
502
|
+
if (probe.status === 404 || probe.data === null) {
|
|
503
|
+
// Old daemon without this route — needs restart
|
|
504
|
+
needsRestart = true;
|
|
505
|
+
} else {
|
|
506
|
+
daemonOk = true;
|
|
482
507
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
else { console.log(` ${fmt(C.red, '✗')} Daemon failed. Run: 0agent start`); rl.prompt(); return; }
|
|
508
|
+
} catch {
|
|
509
|
+
// Daemon not running at all
|
|
486
510
|
}
|
|
487
511
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
console.log(` ${fmt(C.yellow, '⚠')} No API key. Use: ${fmt(C.cyan, '/key ' + (provider?.provider ?? 'anthropic') + ' <key>')}\n`);
|
|
492
|
-
} else {
|
|
493
|
-
const llmSpin = new Spinner(`Checking ${provider.provider}/${provider.model}`);
|
|
494
|
-
llmSpin.start();
|
|
512
|
+
if (needsRestart) {
|
|
513
|
+
startSpin.start('Restarting daemon (new version)');
|
|
514
|
+
// Kill old daemon
|
|
495
515
|
try {
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
516
|
+
const { execSync } = await import('node:child_process');
|
|
517
|
+
execSync('pkill -f "daemon.mjs" 2>/dev/null; true', { stdio: 'ignore' });
|
|
518
|
+
} catch {}
|
|
519
|
+
await new Promise(r => setTimeout(r, 800));
|
|
520
|
+
daemonOk = await _spawnDaemon();
|
|
521
|
+
} else if (!daemonOk) {
|
|
522
|
+
startSpin.start('Starting daemon');
|
|
523
|
+
daemonOk = await _spawnDaemon();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
startSpin.stop();
|
|
527
|
+
if (!daemonOk) {
|
|
528
|
+
console.log(` ${fmt(C.red, '✗')} Daemon failed to start. Run: 0agent start`);
|
|
529
|
+
rl.prompt();
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
if (needsRestart) {
|
|
533
|
+
process.stdout.write(` ${fmt(C.green, '✓')} Daemon updated\n`);
|
|
534
|
+
} else if (!daemonOk) {
|
|
535
|
+
process.stdout.write(` ${fmt(C.green, '✓')} Daemon ready\n`);
|
|
536
|
+
} else {
|
|
537
|
+
// Was already running and up to date — show nothing (already running)
|
|
538
|
+
process.stdout.write(` ${fmt(C.green, '✓')} Daemon ready\n`);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Step 2: LLM check via daemon (not direct — this proves daemon↔API works)
|
|
542
|
+
const provider = getCurrentProvider(cfg);
|
|
543
|
+
const llmSpin = new Spinner(`Checking ${provider?.provider ?? 'LLM'}/${provider?.model ?? '...'}`);
|
|
544
|
+
llmSpin.start();
|
|
545
|
+
try {
|
|
546
|
+
const { data } = await _safeJsonFetch(`${BASE_URL}/api/llm/ping`, {
|
|
547
|
+
method: 'POST',
|
|
548
|
+
signal: AbortSignal.timeout(15_000),
|
|
549
|
+
});
|
|
550
|
+
llmSpin.stop();
|
|
551
|
+
if (data?.ok) {
|
|
552
|
+
console.log(` ${fmt(C.green, '✓')} ${fmt(C.cyan, (data.provider ?? '') + '/' + (data.model ?? ''))} — ${data.latency_ms}ms\n`);
|
|
553
|
+
} else if (data) {
|
|
554
|
+
console.log(` ${fmt(C.red, '✗')} LLM error: ${data.error}`);
|
|
555
|
+
console.log(` ${fmt(C.dim, 'Fix: /key ' + (provider?.provider ?? 'anthropic') + ' <api-key>')}\n`);
|
|
556
|
+
} else {
|
|
557
|
+
console.log(` ${fmt(C.yellow, '⚠')} LLM ping returned unexpected response\n`);
|
|
507
558
|
}
|
|
559
|
+
} catch (e) {
|
|
560
|
+
llmSpin.stop();
|
|
561
|
+
console.log(` ${fmt(C.yellow, '⚠')} LLM check failed: ${e.message}\n`);
|
|
508
562
|
}
|
|
509
563
|
|
|
510
564
|
rl.prompt();
|
|
@@ -532,6 +586,24 @@ rl.on('close', () => {
|
|
|
532
586
|
});
|
|
533
587
|
|
|
534
588
|
process.on('SIGINT', () => {
|
|
535
|
-
|
|
536
|
-
|
|
589
|
+
if (pendingResolve) {
|
|
590
|
+
// Session in progress — cancel it, don't exit
|
|
591
|
+
process.stdout.write(`\n ${fmt(C.yellow, '↩')} Cancelled\n`);
|
|
592
|
+
spinner.stop();
|
|
593
|
+
if (sessionId) {
|
|
594
|
+
fetch(`${BASE_URL}/api/sessions/${sessionId}`, { method: 'DELETE' }).catch(() => {});
|
|
595
|
+
}
|
|
596
|
+
const resolve_ = pendingResolve;
|
|
597
|
+
pendingResolve = null;
|
|
598
|
+
sessionId = null;
|
|
599
|
+
resolve_();
|
|
600
|
+
rl.prompt();
|
|
601
|
+
} else {
|
|
602
|
+
// Not busy — show hint on first press
|
|
603
|
+
process.stdout.write(`\n ${fmt(C.dim, 'Press Ctrl+C again to exit')}\n`);
|
|
604
|
+
rl.prompt();
|
|
605
|
+
// Second Ctrl+C within 1.5s exits
|
|
606
|
+
const timeout = setTimeout(() => {}, 1500);
|
|
607
|
+
process.once('SIGINT', () => { clearTimeout(timeout); process.exit(0); });
|
|
608
|
+
}
|
|
537
609
|
});
|
package/dist/daemon.mjs
CHANGED
|
@@ -1490,7 +1490,7 @@ var init_EdgeWeightUpdater = __esm({
|
|
|
1490
1490
|
this.weightLog.append(event);
|
|
1491
1491
|
}
|
|
1492
1492
|
sleep(ms) {
|
|
1493
|
-
return new Promise((
|
|
1493
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
1494
1494
|
}
|
|
1495
1495
|
};
|
|
1496
1496
|
}
|
|
@@ -2613,7 +2613,7 @@ var init_AgentExecutor = __esm({
|
|
|
2613
2613
|
}
|
|
2614
2614
|
}
|
|
2615
2615
|
shellExec(command, timeoutMs) {
|
|
2616
|
-
return new Promise((
|
|
2616
|
+
return new Promise((resolve14) => {
|
|
2617
2617
|
const chunks = [];
|
|
2618
2618
|
const proc = spawn2("bash", ["-c", command], {
|
|
2619
2619
|
cwd: this.cwd,
|
|
@@ -2624,10 +2624,10 @@ var init_AgentExecutor = __esm({
|
|
|
2624
2624
|
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
2625
2625
|
proc.on("close", (code) => {
|
|
2626
2626
|
const output = chunks.join("").trim();
|
|
2627
|
-
|
|
2627
|
+
resolve14(output || (code === 0 ? "(command completed, no output)" : `exit code ${code}`));
|
|
2628
2628
|
});
|
|
2629
2629
|
proc.on("error", (err) => {
|
|
2630
|
-
|
|
2630
|
+
resolve14(`Error: ${err.message}`);
|
|
2631
2631
|
});
|
|
2632
2632
|
});
|
|
2633
2633
|
}
|
|
@@ -2933,8 +2933,8 @@ __export(ProactiveSurface_exports, {
|
|
|
2933
2933
|
ProactiveSurface: () => ProactiveSurface
|
|
2934
2934
|
});
|
|
2935
2935
|
import { execSync as execSync4 } from "node:child_process";
|
|
2936
|
-
import { existsSync as
|
|
2937
|
-
import { resolve as
|
|
2936
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12, statSync, readdirSync as readdirSync5 } from "node:fs";
|
|
2937
|
+
import { resolve as resolve11, join as join3 } from "node:path";
|
|
2938
2938
|
function readdirSafe(dir) {
|
|
2939
2939
|
try {
|
|
2940
2940
|
return readdirSync5(dir);
|
|
@@ -2983,7 +2983,7 @@ var init_ProactiveSurface = __esm({
|
|
|
2983
2983
|
return [...this.insights];
|
|
2984
2984
|
}
|
|
2985
2985
|
async poll() {
|
|
2986
|
-
if (!
|
|
2986
|
+
if (!existsSync12(resolve11(this.cwd, ".git"))) return;
|
|
2987
2987
|
const newInsights = [];
|
|
2988
2988
|
const gitInsight = this.checkGitActivity();
|
|
2989
2989
|
if (gitInsight) newInsights.push(gitInsight);
|
|
@@ -3027,13 +3027,13 @@ var init_ProactiveSurface = __esm({
|
|
|
3027
3027
|
];
|
|
3028
3028
|
for (const dir of outputPaths) {
|
|
3029
3029
|
try {
|
|
3030
|
-
if (!
|
|
3030
|
+
if (!existsSync12(dir)) continue;
|
|
3031
3031
|
const xmlFiles = readdirSafe(dir).filter((f) => f.endsWith(".xml"));
|
|
3032
3032
|
for (const xml of xmlFiles) {
|
|
3033
3033
|
const path = join3(dir, xml);
|
|
3034
3034
|
const stat = statSync(path);
|
|
3035
3035
|
if (stat.mtimeMs < this.lastPollAt) continue;
|
|
3036
|
-
const content =
|
|
3036
|
+
const content = readFileSync12(path, "utf8");
|
|
3037
3037
|
const failures = [...content.matchAll(/<failure[^>]*message="([^"]+)"/g)].length;
|
|
3038
3038
|
if (failures > 0) {
|
|
3039
3039
|
return this.makeInsight(
|
|
@@ -3088,9 +3088,9 @@ var init_ProactiveSurface = __esm({
|
|
|
3088
3088
|
|
|
3089
3089
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
3090
3090
|
init_src();
|
|
3091
|
-
import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync2, existsSync as
|
|
3092
|
-
import { resolve as
|
|
3093
|
-
import { homedir as
|
|
3091
|
+
import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync2, existsSync as existsSync13, mkdirSync as mkdirSync6 } from "node:fs";
|
|
3092
|
+
import { resolve as resolve12 } from "node:path";
|
|
3093
|
+
import { homedir as homedir8 } from "node:os";
|
|
3094
3094
|
|
|
3095
3095
|
// packages/daemon/src/config/DaemonConfig.ts
|
|
3096
3096
|
import { readFileSync, existsSync } from "node:fs";
|
|
@@ -3391,7 +3391,9 @@ var LLMExecutor = class {
|
|
|
3391
3391
|
"x-api-key": this.config.api_key,
|
|
3392
3392
|
"anthropic-version": "2023-06-01"
|
|
3393
3393
|
},
|
|
3394
|
-
body: JSON.stringify(body)
|
|
3394
|
+
body: JSON.stringify(body),
|
|
3395
|
+
signal: AbortSignal.timeout(6e4)
|
|
3396
|
+
// 60s timeout
|
|
3395
3397
|
});
|
|
3396
3398
|
if (!res.ok) {
|
|
3397
3399
|
const err = await res.text();
|
|
@@ -3514,7 +3516,8 @@ var LLMExecutor = class {
|
|
|
3514
3516
|
"Content-Type": "application/json",
|
|
3515
3517
|
"Authorization": `Bearer ${this.config.api_key}`
|
|
3516
3518
|
},
|
|
3517
|
-
body: JSON.stringify(body)
|
|
3519
|
+
body: JSON.stringify(body),
|
|
3520
|
+
signal: AbortSignal.timeout(6e4)
|
|
3518
3521
|
});
|
|
3519
3522
|
if (!res.ok) {
|
|
3520
3523
|
const err = await res.text();
|
|
@@ -3839,19 +3842,19 @@ var ProjectScanner = class {
|
|
|
3839
3842
|
async getRunningPorts() {
|
|
3840
3843
|
const open = [];
|
|
3841
3844
|
await Promise.all(PORTS_TO_CHECK.map(
|
|
3842
|
-
(port) => new Promise((
|
|
3845
|
+
(port) => new Promise((resolve14) => {
|
|
3843
3846
|
const s = createServer();
|
|
3844
3847
|
s.listen(port, "127.0.0.1", () => {
|
|
3845
3848
|
s.close();
|
|
3846
|
-
|
|
3849
|
+
resolve14();
|
|
3847
3850
|
});
|
|
3848
3851
|
s.on("error", () => {
|
|
3849
3852
|
open.push(port);
|
|
3850
|
-
|
|
3853
|
+
resolve14();
|
|
3851
3854
|
});
|
|
3852
3855
|
setTimeout(() => {
|
|
3853
3856
|
s.close();
|
|
3854
|
-
|
|
3857
|
+
resolve14();
|
|
3855
3858
|
}, 200);
|
|
3856
3859
|
})
|
|
3857
3860
|
));
|
|
@@ -3984,7 +3987,7 @@ var SessionManager = class {
|
|
|
3984
3987
|
session.started_at = Date.now();
|
|
3985
3988
|
this.emit({
|
|
3986
3989
|
type: "session.started",
|
|
3987
|
-
session_id:
|
|
3990
|
+
session_id: id,
|
|
3988
3991
|
task: session.task
|
|
3989
3992
|
});
|
|
3990
3993
|
if (this.inferenceEngine) {
|
|
@@ -4013,7 +4016,7 @@ var SessionManager = class {
|
|
|
4013
4016
|
session.steps.push(step);
|
|
4014
4017
|
this.emit({
|
|
4015
4018
|
type: "session.step",
|
|
4016
|
-
session_id:
|
|
4019
|
+
session_id: id,
|
|
4017
4020
|
step: description,
|
|
4018
4021
|
result: result ?? null
|
|
4019
4022
|
});
|
|
@@ -4029,7 +4032,7 @@ var SessionManager = class {
|
|
|
4029
4032
|
session.result = result;
|
|
4030
4033
|
this.emit({
|
|
4031
4034
|
type: "session.completed",
|
|
4032
|
-
session_id:
|
|
4035
|
+
session_id: id,
|
|
4033
4036
|
result: result ?? null
|
|
4034
4037
|
});
|
|
4035
4038
|
return session;
|
|
@@ -4044,7 +4047,7 @@ var SessionManager = class {
|
|
|
4044
4047
|
session.error = error;
|
|
4045
4048
|
this.emit({
|
|
4046
4049
|
type: "session.failed",
|
|
4047
|
-
session_id:
|
|
4050
|
+
session_id: id,
|
|
4048
4051
|
error
|
|
4049
4052
|
});
|
|
4050
4053
|
return session;
|
|
@@ -4059,7 +4062,7 @@ var SessionManager = class {
|
|
|
4059
4062
|
session.error = "cancelled";
|
|
4060
4063
|
this.emit({
|
|
4061
4064
|
type: "session.failed",
|
|
4062
|
-
session_id:
|
|
4065
|
+
session_id: id,
|
|
4063
4066
|
error: "cancelled"
|
|
4064
4067
|
});
|
|
4065
4068
|
return session;
|
|
@@ -4082,6 +4085,14 @@ var SessionManager = class {
|
|
|
4082
4085
|
* End-to-end session run: create -> start -> resolve -> step -> complete.
|
|
4083
4086
|
* Wraps everything in try/catch to fail gracefully.
|
|
4084
4087
|
*/
|
|
4088
|
+
/**
|
|
4089
|
+
* Called by the route AFTER it already created the session.
|
|
4090
|
+
* Uses the existing session ID — no duplicate creation.
|
|
4091
|
+
*/
|
|
4092
|
+
async runExistingSession(sessionId, req) {
|
|
4093
|
+
return this._executeSession(sessionId, req);
|
|
4094
|
+
}
|
|
4095
|
+
/** @deprecated Use runExistingSession from routes — this creates a duplicate session. */
|
|
4085
4096
|
async runSession(req) {
|
|
4086
4097
|
let enrichedReq = req;
|
|
4087
4098
|
if (req.entity_id && this.graph) {
|
|
@@ -4103,34 +4114,42 @@ var SessionManager = class {
|
|
|
4103
4114
|
}
|
|
4104
4115
|
}
|
|
4105
4116
|
const session = this.createSession(enrichedReq);
|
|
4117
|
+
return this._executeSession(session.id, enrichedReq);
|
|
4118
|
+
}
|
|
4119
|
+
/**
|
|
4120
|
+
* Core execution — takes an EXISTING session ID and runs it.
|
|
4121
|
+
* All callers must have created the session first.
|
|
4122
|
+
*/
|
|
4123
|
+
async _executeSession(sessionId, enrichedReq) {
|
|
4106
4124
|
try {
|
|
4107
|
-
await this.startSession(
|
|
4108
|
-
this.addStep(
|
|
4109
|
-
this.addStep(
|
|
4110
|
-
|
|
4111
|
-
|
|
4125
|
+
await this.startSession(sessionId);
|
|
4126
|
+
this.addStep(sessionId, `Extracting entities from: "${enrichedReq.task.slice(0, 60)}${enrichedReq.task.length > 60 ? "\u2026" : ""}"`);
|
|
4127
|
+
this.addStep(sessionId, "Querying knowledge graph (structural + semantic)\u2026");
|
|
4128
|
+
const plan = this.getSession(sessionId)?.plan;
|
|
4129
|
+
if (plan) {
|
|
4130
|
+
const edge = plan.selected_edge;
|
|
4112
4131
|
if (edge) {
|
|
4113
4132
|
this.addStep(
|
|
4114
|
-
|
|
4133
|
+
sessionId,
|
|
4115
4134
|
`Selected plan: ${edge.from_label} \u2192 ${edge.to_label} (weight: ${edge.weight.toFixed(2)}, mode: ${edge.mode})`,
|
|
4116
|
-
|
|
4135
|
+
plan
|
|
4117
4136
|
);
|
|
4118
4137
|
} else {
|
|
4119
|
-
this.addStep(
|
|
4138
|
+
this.addStep(sessionId, `No prior plan found \u2014 bootstrapping from scratch`, plan);
|
|
4120
4139
|
}
|
|
4121
|
-
if (
|
|
4122
|
-
this.addStep(
|
|
4140
|
+
if (plan.skill) {
|
|
4141
|
+
this.addStep(sessionId, `Matched skill: /${plan.skill}`);
|
|
4123
4142
|
}
|
|
4124
4143
|
} else {
|
|
4125
|
-
this.addStep(
|
|
4144
|
+
this.addStep(sessionId, "No inference engine connected \u2014 executing task directly");
|
|
4126
4145
|
}
|
|
4127
4146
|
let anthropicContext;
|
|
4128
4147
|
if (enrichedReq.skill && this.anthropicFetcher.isAnthropicSkill(enrichedReq.skill)) {
|
|
4129
|
-
this.addStep(
|
|
4148
|
+
this.addStep(sessionId, `Fetching skill instructions: ${enrichedReq.skill}`);
|
|
4130
4149
|
const fetched = await this.anthropicFetcher.fetch(enrichedReq.skill);
|
|
4131
4150
|
if (fetched) {
|
|
4132
4151
|
anthropicContext = this.anthropicFetcher.buildSystemPrompt(fetched);
|
|
4133
|
-
this.addStep(
|
|
4152
|
+
this.addStep(sessionId, `Loaded skill: ${fetched.name} (${fetched.cached ? "cached" : "fresh"})`);
|
|
4134
4153
|
}
|
|
4135
4154
|
}
|
|
4136
4155
|
const activeLLM = this.getFreshLLM();
|
|
@@ -4139,9 +4158,9 @@ var SessionManager = class {
|
|
|
4139
4158
|
activeLLM,
|
|
4140
4159
|
{ cwd: this.cwd },
|
|
4141
4160
|
// step callback → emit session.step events
|
|
4142
|
-
(step) => this.addStep(
|
|
4161
|
+
(step) => this.addStep(sessionId, step),
|
|
4143
4162
|
// token callback → emit session.token events
|
|
4144
|
-
(token) => this.emit({ type: "session.token", session_id:
|
|
4163
|
+
(token) => this.emit({ type: "session.token", session_id: sessionId, token })
|
|
4145
4164
|
);
|
|
4146
4165
|
const identityContext = this.identity ? `You are talking to ${this.identity.name} (device: ${this.identity.device_id}, timezone: ${this.identity.timezone}).` : void 0;
|
|
4147
4166
|
const projectCtx = this.projectContext ? ProjectScanner.buildContextPrompt(this.projectContext) : void 0;
|
|
@@ -4170,15 +4189,14 @@ Current task:`;
|
|
|
4170
4189
|
const healLoop = new SelfHealLoop2(
|
|
4171
4190
|
activeLLM,
|
|
4172
4191
|
{ cwd: this.cwd },
|
|
4173
|
-
(step) => this.addStep(
|
|
4174
|
-
(token) => this.emit({ type: "session.token", session_id:
|
|
4192
|
+
(step) => this.addStep(sessionId, step),
|
|
4193
|
+
(token) => this.emit({ type: "session.token", session_id: sessionId, token })
|
|
4175
4194
|
);
|
|
4176
4195
|
agentResult = await healLoop.executeWithHealing(enrichedReq.task, systemContext);
|
|
4177
4196
|
} catch {
|
|
4178
4197
|
agentResult = await executor.execute(enrichedReq.task, systemContext);
|
|
4179
4198
|
}
|
|
4180
4199
|
if (this.conversationStore && userEntityId) {
|
|
4181
|
-
const sessionId = session.id;
|
|
4182
4200
|
const now = Date.now();
|
|
4183
4201
|
this.conversationStore.append({
|
|
4184
4202
|
id: crypto.randomUUID(),
|
|
@@ -4198,7 +4216,7 @@ Current task:`;
|
|
|
4198
4216
|
created_at: now + 1
|
|
4199
4217
|
});
|
|
4200
4218
|
}
|
|
4201
|
-
const selectedEdgeId =
|
|
4219
|
+
const selectedEdgeId = this.getSession(sessionId)?.plan?.selected_edge?.edge_id;
|
|
4202
4220
|
if (selectedEdgeId && this.weightUpdater && this.graph) {
|
|
4203
4221
|
const outcomeSignal = this.computeOutcomeSignal(agentResult);
|
|
4204
4222
|
if (outcomeSignal !== 0) {
|
|
@@ -4214,20 +4232,20 @@ Current task:`;
|
|
|
4214
4232
|
edge.weight,
|
|
4215
4233
|
newWeight,
|
|
4216
4234
|
outcomeSignal > 0 ? "task_outcome_positive" : "task_outcome_negative",
|
|
4217
|
-
|
|
4235
|
+
sessionId
|
|
4218
4236
|
);
|
|
4219
4237
|
this.emit({ type: "graph.weight_updated", edge_id: edge.id, old_weight: edge.weight, new_weight: newWeight });
|
|
4220
4238
|
}
|
|
4221
4239
|
}
|
|
4222
4240
|
}
|
|
4223
4241
|
if (agentResult.files_written.length > 0) {
|
|
4224
|
-
this.addStep(
|
|
4242
|
+
this.addStep(sessionId, `Files written: ${agentResult.files_written.join(", ")}`);
|
|
4225
4243
|
}
|
|
4226
4244
|
if (agentResult.commands_run.length > 0) {
|
|
4227
|
-
this.addStep(
|
|
4245
|
+
this.addStep(sessionId, `Commands run: ${agentResult.commands_run.length}`);
|
|
4228
4246
|
}
|
|
4229
|
-
this.addStep(
|
|
4230
|
-
this.completeSession(
|
|
4247
|
+
this.addStep(sessionId, `Done (${agentResult.tokens_used} tokens, ${agentResult.iterations} LLM turns)`);
|
|
4248
|
+
this.completeSession(sessionId, {
|
|
4231
4249
|
output: agentResult.output,
|
|
4232
4250
|
files_written: agentResult.files_written,
|
|
4233
4251
|
commands_run: agentResult.commands_run,
|
|
@@ -4237,14 +4255,14 @@ Current task:`;
|
|
|
4237
4255
|
} else {
|
|
4238
4256
|
const cfgPath = resolve5(homedir2(), ".0agent", "config.yaml");
|
|
4239
4257
|
const output = `No LLM API key found. Add one to ${cfgPath} or run: 0agent init`;
|
|
4240
|
-
this.addStep(
|
|
4241
|
-
this.completeSession(
|
|
4258
|
+
this.addStep(sessionId, "\u26A0 No LLM API key configured \u2014 run: 0agent init");
|
|
4259
|
+
this.completeSession(sessionId, { output });
|
|
4242
4260
|
}
|
|
4243
4261
|
} catch (err) {
|
|
4244
4262
|
const message = err instanceof Error ? err.message : String(err);
|
|
4245
|
-
this.failSession(
|
|
4263
|
+
this.failSession(sessionId, message);
|
|
4246
4264
|
}
|
|
4247
|
-
return this.sessions.get(
|
|
4265
|
+
return this.sessions.get(sessionId);
|
|
4248
4266
|
}
|
|
4249
4267
|
/**
|
|
4250
4268
|
* Return the number of active (running) sessions.
|
|
@@ -4626,10 +4644,10 @@ var SkillRegistry = class {
|
|
|
4626
4644
|
};
|
|
4627
4645
|
|
|
4628
4646
|
// packages/daemon/src/HTTPServer.ts
|
|
4629
|
-
import { Hono as
|
|
4647
|
+
import { Hono as Hono11 } from "hono";
|
|
4630
4648
|
import { serve } from "@hono/node-server";
|
|
4631
|
-
import { readFileSync as
|
|
4632
|
-
import { resolve as
|
|
4649
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
4650
|
+
import { resolve as resolve7, dirname as dirname3 } from "node:path";
|
|
4633
4651
|
import { fileURLToPath } from "node:url";
|
|
4634
4652
|
|
|
4635
4653
|
// packages/daemon/src/routes/health.ts
|
|
@@ -4653,28 +4671,23 @@ function sessionRoutes(deps) {
|
|
|
4653
4671
|
return c.json({ error: "task is required and must be a string" }, 400);
|
|
4654
4672
|
}
|
|
4655
4673
|
const session = deps.sessions.createSession(body);
|
|
4656
|
-
deps.sessions.
|
|
4674
|
+
deps.sessions.runExistingSession(session.id, body).catch(() => {
|
|
4657
4675
|
});
|
|
4658
4676
|
return c.json({ session_id: session.id, status: "pending" }, 201);
|
|
4659
4677
|
});
|
|
4660
4678
|
app.get("/", (c) => {
|
|
4661
|
-
|
|
4662
|
-
return c.json(sessions);
|
|
4679
|
+
return c.json(deps.sessions.listSessions());
|
|
4663
4680
|
});
|
|
4664
4681
|
app.get("/:id", (c) => {
|
|
4665
4682
|
const id = c.req.param("id");
|
|
4666
4683
|
const session = deps.sessions.getSession(id);
|
|
4667
|
-
if (!session) {
|
|
4668
|
-
return c.json({ error: "Session not found" }, 404);
|
|
4669
|
-
}
|
|
4684
|
+
if (!session) return c.json({ error: "Session not found" }, 404);
|
|
4670
4685
|
return c.json(session);
|
|
4671
4686
|
});
|
|
4672
4687
|
app.delete("/:id", (c) => {
|
|
4673
4688
|
const id = c.req.param("id");
|
|
4674
4689
|
const session = deps.sessions.getSession(id);
|
|
4675
|
-
if (!session) {
|
|
4676
|
-
return c.json({ error: "Session not found" }, 404);
|
|
4677
|
-
}
|
|
4690
|
+
if (!session) return c.json({ error: "Session not found" }, 404);
|
|
4678
4691
|
deps.sessions.cancelSession(id);
|
|
4679
4692
|
return c.json({ ok: true });
|
|
4680
4693
|
});
|
|
@@ -4923,18 +4936,71 @@ function memoryRoutes(deps) {
|
|
|
4923
4936
|
return app;
|
|
4924
4937
|
}
|
|
4925
4938
|
|
|
4939
|
+
// packages/daemon/src/routes/llm.ts
|
|
4940
|
+
import { Hono as Hono10 } from "hono";
|
|
4941
|
+
import { readFileSync as readFileSync7, existsSync as existsSync8 } from "node:fs";
|
|
4942
|
+
import { resolve as resolve6 } from "node:path";
|
|
4943
|
+
import { homedir as homedir4 } from "node:os";
|
|
4944
|
+
import YAML4 from "yaml";
|
|
4945
|
+
function llmRoutes() {
|
|
4946
|
+
const app = new Hono10();
|
|
4947
|
+
app.post("/ping", async (c) => {
|
|
4948
|
+
const start = Date.now();
|
|
4949
|
+
try {
|
|
4950
|
+
const configPath = resolve6(homedir4(), ".0agent", "config.yaml");
|
|
4951
|
+
if (!existsSync8(configPath)) {
|
|
4952
|
+
return c.json({ ok: false, error: "Config not found. Run: 0agent init" });
|
|
4953
|
+
}
|
|
4954
|
+
const cfg = YAML4.parse(readFileSync7(configPath, "utf8"));
|
|
4955
|
+
const providers = cfg.llm_providers;
|
|
4956
|
+
const def = providers?.find((p) => p.is_default) ?? providers?.[0];
|
|
4957
|
+
if (!def) {
|
|
4958
|
+
return c.json({ ok: false, error: "No LLM provider in config" });
|
|
4959
|
+
}
|
|
4960
|
+
const apiKey = String(def.api_key ?? "").trim();
|
|
4961
|
+
if (!apiKey && def.provider !== "ollama") {
|
|
4962
|
+
return c.json({ ok: false, error: `No API key for ${def.provider}. Run: 0agent init` });
|
|
4963
|
+
}
|
|
4964
|
+
const executor = new LLMExecutor({
|
|
4965
|
+
provider: String(def.provider),
|
|
4966
|
+
model: String(def.model),
|
|
4967
|
+
api_key: apiKey,
|
|
4968
|
+
base_url: def.base_url ? String(def.base_url) : void 0
|
|
4969
|
+
});
|
|
4970
|
+
const result = await executor.complete(
|
|
4971
|
+
[{ role: "user", content: "Reply with the word: ready" }],
|
|
4972
|
+
"You are a helpful assistant. Reply with exactly one word."
|
|
4973
|
+
);
|
|
4974
|
+
return c.json({
|
|
4975
|
+
ok: true,
|
|
4976
|
+
model: String(def.model),
|
|
4977
|
+
provider: String(def.provider),
|
|
4978
|
+
latency_ms: Date.now() - start,
|
|
4979
|
+
response: result.content.trim().slice(0, 20)
|
|
4980
|
+
});
|
|
4981
|
+
} catch (err) {
|
|
4982
|
+
return c.json({
|
|
4983
|
+
ok: false,
|
|
4984
|
+
error: err instanceof Error ? err.message : String(err),
|
|
4985
|
+
latency_ms: Date.now() - start
|
|
4986
|
+
});
|
|
4987
|
+
}
|
|
4988
|
+
});
|
|
4989
|
+
return app;
|
|
4990
|
+
}
|
|
4991
|
+
|
|
4926
4992
|
// packages/daemon/src/HTTPServer.ts
|
|
4927
4993
|
function findGraphHtml() {
|
|
4928
4994
|
const candidates = [
|
|
4929
|
-
|
|
4995
|
+
resolve7(dirname3(fileURLToPath(import.meta.url)), "graph.html"),
|
|
4930
4996
|
// dev (src/)
|
|
4931
|
-
|
|
4997
|
+
resolve7(dirname3(fileURLToPath(import.meta.url)), "..", "graph.html"),
|
|
4932
4998
|
// bundled (dist/../)
|
|
4933
|
-
|
|
4999
|
+
resolve7(dirname3(fileURLToPath(import.meta.url)), "..", "dist", "graph.html")
|
|
4934
5000
|
];
|
|
4935
5001
|
for (const p of candidates) {
|
|
4936
5002
|
try {
|
|
4937
|
-
|
|
5003
|
+
readFileSync8(p);
|
|
4938
5004
|
return p;
|
|
4939
5005
|
} catch {
|
|
4940
5006
|
}
|
|
@@ -4948,7 +5014,7 @@ var HTTPServer = class {
|
|
|
4948
5014
|
deps;
|
|
4949
5015
|
constructor(deps) {
|
|
4950
5016
|
this.deps = deps;
|
|
4951
|
-
this.app = new
|
|
5017
|
+
this.app = new Hono11();
|
|
4952
5018
|
this.app.route("/api/health", healthRoutes({ getStatus: deps.getStatus }));
|
|
4953
5019
|
this.app.route("/api/sessions", sessionRoutes({ sessions: deps.sessions }));
|
|
4954
5020
|
this.app.route("/api/graph", graphRoutes({ graph: deps.graph }));
|
|
@@ -4958,9 +5024,10 @@ var HTTPServer = class {
|
|
|
4958
5024
|
this.app.route("/api/skills", skillRoutes({ skillRegistry: deps.skillRegistry }));
|
|
4959
5025
|
this.app.route("/api/insights", insightsRoutes({ proactiveSurface: deps.proactiveSurface ?? null }));
|
|
4960
5026
|
this.app.route("/api/memory", memoryRoutes({ getSync: deps.getMemorySync ?? (() => null) }));
|
|
5027
|
+
this.app.route("/api/llm", llmRoutes());
|
|
4961
5028
|
const serveGraph = (c) => {
|
|
4962
5029
|
try {
|
|
4963
|
-
const html =
|
|
5030
|
+
const html = readFileSync8(GRAPH_HTML_PATH, "utf8");
|
|
4964
5031
|
return c.html(html);
|
|
4965
5032
|
} catch {
|
|
4966
5033
|
return c.html("<p>Graph UI not found. Run: pnpm build</p>");
|
|
@@ -4970,7 +5037,7 @@ var HTTPServer = class {
|
|
|
4970
5037
|
this.app.get("/graph", serveGraph);
|
|
4971
5038
|
}
|
|
4972
5039
|
start() {
|
|
4973
|
-
return new Promise((
|
|
5040
|
+
return new Promise((resolve14) => {
|
|
4974
5041
|
this.server = serve(
|
|
4975
5042
|
{
|
|
4976
5043
|
fetch: this.app.fetch,
|
|
@@ -4978,20 +5045,20 @@ var HTTPServer = class {
|
|
|
4978
5045
|
hostname: this.deps.host
|
|
4979
5046
|
},
|
|
4980
5047
|
() => {
|
|
4981
|
-
|
|
5048
|
+
resolve14();
|
|
4982
5049
|
}
|
|
4983
5050
|
);
|
|
4984
5051
|
});
|
|
4985
5052
|
}
|
|
4986
5053
|
stop() {
|
|
4987
|
-
return new Promise((
|
|
5054
|
+
return new Promise((resolve14, reject) => {
|
|
4988
5055
|
if (!this.server) {
|
|
4989
|
-
|
|
5056
|
+
resolve14();
|
|
4990
5057
|
return;
|
|
4991
5058
|
}
|
|
4992
5059
|
this.server.close((err) => {
|
|
4993
5060
|
if (err) reject(err);
|
|
4994
|
-
else
|
|
5061
|
+
else resolve14();
|
|
4995
5062
|
});
|
|
4996
5063
|
});
|
|
4997
5064
|
}
|
|
@@ -5002,11 +5069,11 @@ var HTTPServer = class {
|
|
|
5002
5069
|
|
|
5003
5070
|
// packages/daemon/src/IdentityManager.ts
|
|
5004
5071
|
init_src();
|
|
5005
|
-
import { readFileSync as
|
|
5006
|
-
import { resolve as
|
|
5007
|
-
import { homedir as
|
|
5008
|
-
import
|
|
5009
|
-
var IDENTITY_PATH =
|
|
5072
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "node:fs";
|
|
5073
|
+
import { resolve as resolve8, dirname as dirname4 } from "node:path";
|
|
5074
|
+
import { homedir as homedir5, hostname } from "node:os";
|
|
5075
|
+
import YAML5 from "yaml";
|
|
5076
|
+
var IDENTITY_PATH = resolve8(homedir5(), ".0agent", "identity.yaml");
|
|
5010
5077
|
var DEFAULT_IDENTITY = {
|
|
5011
5078
|
name: "User",
|
|
5012
5079
|
device_id: `unknown-device`,
|
|
@@ -5022,9 +5089,9 @@ var IdentityManager = class {
|
|
|
5022
5089
|
* Load or create identity. Call once at daemon startup.
|
|
5023
5090
|
*/
|
|
5024
5091
|
async init() {
|
|
5025
|
-
if (
|
|
5026
|
-
const raw =
|
|
5027
|
-
this.identity =
|
|
5092
|
+
if (existsSync9(IDENTITY_PATH)) {
|
|
5093
|
+
const raw = readFileSync9(IDENTITY_PATH, "utf8");
|
|
5094
|
+
this.identity = YAML5.parse(raw);
|
|
5028
5095
|
} else {
|
|
5029
5096
|
this.identity = {
|
|
5030
5097
|
...DEFAULT_IDENTITY,
|
|
@@ -5075,24 +5142,24 @@ var IdentityManager = class {
|
|
|
5075
5142
|
}
|
|
5076
5143
|
save() {
|
|
5077
5144
|
const dir = dirname4(IDENTITY_PATH);
|
|
5078
|
-
if (!
|
|
5145
|
+
if (!existsSync9(dir)) {
|
|
5079
5146
|
mkdirSync4(dir, { recursive: true });
|
|
5080
5147
|
}
|
|
5081
|
-
writeFileSync4(IDENTITY_PATH,
|
|
5148
|
+
writeFileSync4(IDENTITY_PATH, YAML5.stringify(this.identity), "utf8");
|
|
5082
5149
|
}
|
|
5083
5150
|
};
|
|
5084
5151
|
|
|
5085
5152
|
// packages/daemon/src/TeamManager.ts
|
|
5086
|
-
import { readFileSync as
|
|
5087
|
-
import { resolve as
|
|
5088
|
-
import { homedir as
|
|
5089
|
-
import
|
|
5090
|
-
var TEAMS_PATH =
|
|
5153
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "node:fs";
|
|
5154
|
+
import { resolve as resolve9 } from "node:path";
|
|
5155
|
+
import { homedir as homedir6 } from "node:os";
|
|
5156
|
+
import YAML6 from "yaml";
|
|
5157
|
+
var TEAMS_PATH = resolve9(homedir6(), ".0agent", "teams.yaml");
|
|
5091
5158
|
var TeamManager = class {
|
|
5092
5159
|
config;
|
|
5093
5160
|
constructor() {
|
|
5094
|
-
if (
|
|
5095
|
-
this.config =
|
|
5161
|
+
if (existsSync10(TEAMS_PATH)) {
|
|
5162
|
+
this.config = YAML6.parse(readFileSync10(TEAMS_PATH, "utf8"));
|
|
5096
5163
|
} else {
|
|
5097
5164
|
this.config = { memberships: [] };
|
|
5098
5165
|
}
|
|
@@ -5147,8 +5214,8 @@ var TeamManager = class {
|
|
|
5147
5214
|
}
|
|
5148
5215
|
}
|
|
5149
5216
|
save() {
|
|
5150
|
-
mkdirSync5(
|
|
5151
|
-
writeFileSync5(TEAMS_PATH,
|
|
5217
|
+
mkdirSync5(resolve9(homedir6(), ".0agent"), { recursive: true });
|
|
5218
|
+
writeFileSync5(TEAMS_PATH, YAML6.stringify(this.config), "utf8");
|
|
5152
5219
|
}
|
|
5153
5220
|
};
|
|
5154
5221
|
|
|
@@ -5231,9 +5298,9 @@ var TeamSync = class {
|
|
|
5231
5298
|
};
|
|
5232
5299
|
|
|
5233
5300
|
// packages/daemon/src/GitHubMemorySync.ts
|
|
5234
|
-
import { readFileSync as
|
|
5235
|
-
import { resolve as
|
|
5236
|
-
import { homedir as
|
|
5301
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
|
|
5302
|
+
import { resolve as resolve10 } from "node:path";
|
|
5303
|
+
import { homedir as homedir7 } from "node:os";
|
|
5237
5304
|
var GITHUB_API = "https://api.github.com";
|
|
5238
5305
|
async function ghFetch(path, token, opts) {
|
|
5239
5306
|
return fetch(`${GITHUB_API}${path}`, {
|
|
@@ -5352,10 +5419,10 @@ var GitHubMemorySync = class {
|
|
|
5352
5419
|
)
|
|
5353
5420
|
);
|
|
5354
5421
|
}
|
|
5355
|
-
const customSkillsDir =
|
|
5356
|
-
if (
|
|
5422
|
+
const customSkillsDir = resolve10(homedir7(), ".0agent", "skills", "custom");
|
|
5423
|
+
if (existsSync11(customSkillsDir)) {
|
|
5357
5424
|
for (const file of readdirSync4(customSkillsDir).filter((f) => f.endsWith(".yaml"))) {
|
|
5358
|
-
const content =
|
|
5425
|
+
const content = readFileSync11(resolve10(customSkillsDir, file), "utf8");
|
|
5359
5426
|
pushes.push(putFile(token, owner, repo, `skills/custom/${file}`, content, commitMsg));
|
|
5360
5427
|
}
|
|
5361
5428
|
}
|
|
@@ -5540,7 +5607,7 @@ var GitHubMemorySync = class {
|
|
|
5540
5607
|
}
|
|
5541
5608
|
async pullCustomSkills() {
|
|
5542
5609
|
const { token, owner, repo } = this.config;
|
|
5543
|
-
const dir =
|
|
5610
|
+
const dir = resolve10(homedir7(), ".0agent", "skills", "custom");
|
|
5544
5611
|
try {
|
|
5545
5612
|
const res = await ghFetch(`/repos/${owner}/${repo}/contents/skills/custom`, token);
|
|
5546
5613
|
if (!res.ok) return;
|
|
@@ -5550,7 +5617,7 @@ var GitHubMemorySync = class {
|
|
|
5550
5617
|
if (content) {
|
|
5551
5618
|
const { mkdirSync: mkdirSync7 } = await import("node:fs");
|
|
5552
5619
|
mkdirSync7(dir, { recursive: true });
|
|
5553
|
-
writeFileSync6(
|
|
5620
|
+
writeFileSync6(resolve10(dir, file.name), content, "utf8");
|
|
5554
5621
|
}
|
|
5555
5622
|
}
|
|
5556
5623
|
} catch {
|
|
@@ -5614,12 +5681,12 @@ var ZeroAgentDaemon = class {
|
|
|
5614
5681
|
startedAt = 0;
|
|
5615
5682
|
pidFilePath;
|
|
5616
5683
|
constructor() {
|
|
5617
|
-
this.pidFilePath =
|
|
5684
|
+
this.pidFilePath = resolve12(homedir8(), ".0agent", "daemon.pid");
|
|
5618
5685
|
}
|
|
5619
5686
|
async start(opts) {
|
|
5620
5687
|
this.config = await loadConfig(opts?.config_path);
|
|
5621
|
-
const dotDir =
|
|
5622
|
-
if (!
|
|
5688
|
+
const dotDir = resolve12(homedir8(), ".0agent");
|
|
5689
|
+
if (!existsSync13(dotDir)) {
|
|
5623
5690
|
mkdirSync6(dotDir, { recursive: true });
|
|
5624
5691
|
}
|
|
5625
5692
|
this.adapter = new SQLiteAdapter({ db_path: this.config.graph.db_path });
|
|
@@ -5771,7 +5838,7 @@ var ZeroAgentDaemon = class {
|
|
|
5771
5838
|
this.graph = null;
|
|
5772
5839
|
}
|
|
5773
5840
|
this.adapter = null;
|
|
5774
|
-
if (
|
|
5841
|
+
if (existsSync13(this.pidFilePath)) {
|
|
5775
5842
|
try {
|
|
5776
5843
|
unlinkSync2(this.pidFilePath);
|
|
5777
5844
|
} catch {
|
|
@@ -5801,11 +5868,11 @@ var ZeroAgentDaemon = class {
|
|
|
5801
5868
|
};
|
|
5802
5869
|
|
|
5803
5870
|
// packages/daemon/src/start.ts
|
|
5804
|
-
import { resolve as
|
|
5805
|
-
import { homedir as
|
|
5806
|
-
import { existsSync as
|
|
5807
|
-
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ??
|
|
5808
|
-
if (!
|
|
5871
|
+
import { resolve as resolve13 } from "node:path";
|
|
5872
|
+
import { homedir as homedir9 } from "node:os";
|
|
5873
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
5874
|
+
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ?? resolve13(homedir9(), ".0agent", "config.yaml");
|
|
5875
|
+
if (!existsSync14(CONFIG_PATH)) {
|
|
5809
5876
|
console.error(`
|
|
5810
5877
|
0agent is not initialised.
|
|
5811
5878
|
|