0agent 1.0.78 → 1.0.81
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/daemon.mjs +923 -280
- package/package.json +1 -1
package/dist/daemon.mjs
CHANGED
|
@@ -1507,7 +1507,7 @@ var init_EdgeWeightUpdater = __esm({
|
|
|
1507
1507
|
this.weightLog.append(event);
|
|
1508
1508
|
}
|
|
1509
1509
|
sleep(ms) {
|
|
1510
|
-
return new Promise((
|
|
1510
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
1511
1511
|
}
|
|
1512
1512
|
};
|
|
1513
1513
|
}
|
|
@@ -1969,10 +1969,10 @@ var init_src = __esm({
|
|
|
1969
1969
|
}
|
|
1970
1970
|
});
|
|
1971
1971
|
|
|
1972
|
-
// packages/daemon/src/LLMExecutor.ts
|
|
1972
|
+
// packages/daemon/src/services/LLMExecutor.ts
|
|
1973
1973
|
var LLMExecutor;
|
|
1974
1974
|
var init_LLMExecutor = __esm({
|
|
1975
|
-
"packages/daemon/src/LLMExecutor.ts"() {
|
|
1975
|
+
"packages/daemon/src/services/LLMExecutor.ts"() {
|
|
1976
1976
|
"use strict";
|
|
1977
1977
|
LLMExecutor = class _LLMExecutor {
|
|
1978
1978
|
constructor(config) {
|
|
@@ -2022,10 +2022,10 @@ var init_LLMExecutor = __esm({
|
|
|
2022
2022
|
return { content: res.content, tokens_used: res.tokens_used, model: res.model };
|
|
2023
2023
|
}
|
|
2024
2024
|
// ─── Tool-calling completion with optional streaming ─────────────────────
|
|
2025
|
-
async completeWithTools(messages, tools, system, onToken, signal) {
|
|
2025
|
+
async completeWithTools(messages, tools, system, onToken, signal, onToolUseBlock) {
|
|
2026
2026
|
switch (this.config.provider) {
|
|
2027
2027
|
case "anthropic":
|
|
2028
|
-
return this.anthropic(messages, tools, system, onToken, signal);
|
|
2028
|
+
return this.anthropic(messages, tools, system, onToken, signal, onToolUseBlock);
|
|
2029
2029
|
case "openai":
|
|
2030
2030
|
return this.openai(messages, tools, system, onToken, void 0, signal);
|
|
2031
2031
|
case "xai":
|
|
@@ -2039,7 +2039,7 @@ var init_LLMExecutor = __esm({
|
|
|
2039
2039
|
}
|
|
2040
2040
|
}
|
|
2041
2041
|
// ─── Anthropic ───────────────────────────────────────────────────────────
|
|
2042
|
-
async anthropic(messages, tools, system, onToken, signal) {
|
|
2042
|
+
async anthropic(messages, tools, system, onToken, signal, onToolUseBlock) {
|
|
2043
2043
|
const sysContent = system ?? messages.find((m) => m.role === "system")?.content;
|
|
2044
2044
|
const filtered = messages.filter((m) => m.role !== "system");
|
|
2045
2045
|
const anthropicMsgs = filtered.map((m) => {
|
|
@@ -2153,6 +2153,9 @@ var init_LLMExecutor = __esm({
|
|
|
2153
2153
|
tc.input = JSON.parse(toolInputBuffers[currentToolId]);
|
|
2154
2154
|
} catch {
|
|
2155
2155
|
}
|
|
2156
|
+
if (onToolUseBlock && tc.input && Object.keys(tc.input).length > 0) {
|
|
2157
|
+
onToolUseBlock(tc);
|
|
2158
|
+
}
|
|
2156
2159
|
}
|
|
2157
2160
|
}
|
|
2158
2161
|
} else if (type === "message_delta") {
|
|
@@ -2327,11 +2330,11 @@ var init_LLMExecutor = __esm({
|
|
|
2327
2330
|
}
|
|
2328
2331
|
});
|
|
2329
2332
|
|
|
2330
|
-
// packages/daemon/src/
|
|
2333
|
+
// packages/daemon/src/tools/WebSearchCapability.ts
|
|
2331
2334
|
import { execSync, spawnSync } from "node:child_process";
|
|
2332
2335
|
var WebSearchCapability;
|
|
2333
2336
|
var init_WebSearchCapability = __esm({
|
|
2334
|
-
"packages/daemon/src/
|
|
2337
|
+
"packages/daemon/src/tools/WebSearchCapability.ts"() {
|
|
2335
2338
|
"use strict";
|
|
2336
2339
|
WebSearchCapability = class {
|
|
2337
2340
|
name = "web_search";
|
|
@@ -2474,7 +2477,7 @@ var init_WebSearchCapability = __esm({
|
|
|
2474
2477
|
}
|
|
2475
2478
|
});
|
|
2476
2479
|
|
|
2477
|
-
// packages/daemon/src/
|
|
2480
|
+
// packages/daemon/src/tools/BrowserCapability.ts
|
|
2478
2481
|
import { spawnSync as spawnSync2, execSync as execSync2, spawn } from "node:child_process";
|
|
2479
2482
|
import { platform } from "node:os";
|
|
2480
2483
|
function findSystemChrome() {
|
|
@@ -2495,7 +2498,7 @@ function findSystemChrome() {
|
|
|
2495
2498
|
}
|
|
2496
2499
|
var BrowserCapability;
|
|
2497
2500
|
var init_BrowserCapability = __esm({
|
|
2498
|
-
"packages/daemon/src/
|
|
2501
|
+
"packages/daemon/src/tools/BrowserCapability.ts"() {
|
|
2499
2502
|
"use strict";
|
|
2500
2503
|
BrowserCapability = class {
|
|
2501
2504
|
name = "browser_open";
|
|
@@ -2610,11 +2613,11 @@ var init_BrowserCapability = __esm({
|
|
|
2610
2613
|
}
|
|
2611
2614
|
});
|
|
2612
2615
|
|
|
2613
|
-
// packages/daemon/src/
|
|
2616
|
+
// packages/daemon/src/tools/ScraperCapability.ts
|
|
2614
2617
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
2615
2618
|
var ScraperCapability;
|
|
2616
2619
|
var init_ScraperCapability = __esm({
|
|
2617
|
-
"packages/daemon/src/
|
|
2620
|
+
"packages/daemon/src/tools/ScraperCapability.ts"() {
|
|
2618
2621
|
"use strict";
|
|
2619
2622
|
init_BrowserCapability();
|
|
2620
2623
|
ScraperCapability = class {
|
|
@@ -2706,11 +2709,11 @@ else:
|
|
|
2706
2709
|
}
|
|
2707
2710
|
});
|
|
2708
2711
|
|
|
2709
|
-
// packages/daemon/src/
|
|
2712
|
+
// packages/daemon/src/tools/ShellCapability.ts
|
|
2710
2713
|
import { spawn as spawn2 } from "node:child_process";
|
|
2711
2714
|
var ShellCapability;
|
|
2712
2715
|
var init_ShellCapability = __esm({
|
|
2713
|
-
"packages/daemon/src/
|
|
2716
|
+
"packages/daemon/src/tools/ShellCapability.ts"() {
|
|
2714
2717
|
"use strict";
|
|
2715
2718
|
ShellCapability = class _ShellCapability {
|
|
2716
2719
|
name = "shell_exec";
|
|
@@ -2823,12 +2826,12 @@ var init_ShellCapability = __esm({
|
|
|
2823
2826
|
}
|
|
2824
2827
|
});
|
|
2825
2828
|
|
|
2826
|
-
// packages/daemon/src/
|
|
2829
|
+
// packages/daemon/src/tools/FileCapability.ts
|
|
2827
2830
|
import { readFileSync as readFileSync2, writeFileSync, readdirSync, mkdirSync, existsSync as existsSync2 } from "node:fs";
|
|
2828
2831
|
import { resolve as resolve2, dirname } from "node:path";
|
|
2829
2832
|
var FileCapability;
|
|
2830
2833
|
var init_FileCapability = __esm({
|
|
2831
|
-
"packages/daemon/src/
|
|
2834
|
+
"packages/daemon/src/tools/FileCapability.ts"() {
|
|
2832
2835
|
"use strict";
|
|
2833
2836
|
FileCapability = class {
|
|
2834
2837
|
name = "file_op";
|
|
@@ -2913,10 +2916,10 @@ var init_FileCapability = __esm({
|
|
|
2913
2916
|
}
|
|
2914
2917
|
});
|
|
2915
2918
|
|
|
2916
|
-
// packages/daemon/src/
|
|
2919
|
+
// packages/daemon/src/tools/MemoryCapability.ts
|
|
2917
2920
|
var MemoryCapability;
|
|
2918
2921
|
var init_MemoryCapability = __esm({
|
|
2919
|
-
"packages/daemon/src/
|
|
2922
|
+
"packages/daemon/src/tools/MemoryCapability.ts"() {
|
|
2920
2923
|
"use strict";
|
|
2921
2924
|
init_src();
|
|
2922
2925
|
MemoryCapability = class {
|
|
@@ -3014,14 +3017,14 @@ var init_MemoryCapability = __esm({
|
|
|
3014
3017
|
}
|
|
3015
3018
|
});
|
|
3016
3019
|
|
|
3017
|
-
// packages/daemon/src/
|
|
3020
|
+
// packages/daemon/src/tools/GUICapability.ts
|
|
3018
3021
|
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
3019
3022
|
import { writeFileSync as writeFileSync2, unlinkSync } from "node:fs";
|
|
3020
3023
|
import { resolve as resolve3 } from "node:path";
|
|
3021
3024
|
import { tmpdir, platform as platform2 } from "node:os";
|
|
3022
3025
|
var GUICapability;
|
|
3023
3026
|
var init_GUICapability = __esm({
|
|
3024
|
-
"packages/daemon/src/
|
|
3027
|
+
"packages/daemon/src/tools/GUICapability.ts"() {
|
|
3025
3028
|
"use strict";
|
|
3026
3029
|
GUICapability = class {
|
|
3027
3030
|
name = "gui_automation";
|
|
@@ -4012,14 +4015,14 @@ else:
|
|
|
4012
4015
|
}
|
|
4013
4016
|
});
|
|
4014
4017
|
|
|
4015
|
-
// packages/daemon/src/
|
|
4018
|
+
// packages/daemon/src/tools/OpenInterpreterCapability.ts
|
|
4016
4019
|
import { spawn as spawn4 } from "node:child_process";
|
|
4017
4020
|
import { writeFileSync as writeFileSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
4018
4021
|
import { resolve as resolve4 } from "node:path";
|
|
4019
4022
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
4020
4023
|
var OI_SCRIPT, OpenInterpreterCapability;
|
|
4021
4024
|
var init_OpenInterpreterCapability = __esm({
|
|
4022
|
-
"packages/daemon/src/
|
|
4025
|
+
"packages/daemon/src/tools/OpenInterpreterCapability.ts"() {
|
|
4023
4026
|
"use strict";
|
|
4024
4027
|
OI_SCRIPT = `
|
|
4025
4028
|
import sys
|
|
@@ -4152,7 +4155,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4152
4155
|
}
|
|
4153
4156
|
/** Async pip install — never blocks the event loop (unlike spawnSync). */
|
|
4154
4157
|
_pipInstall(pkg, signal) {
|
|
4155
|
-
return new Promise((
|
|
4158
|
+
return new Promise((resolve19) => {
|
|
4156
4159
|
const proc = spawn4("pip3", ["install", pkg, "-q"], {
|
|
4157
4160
|
env: process.env,
|
|
4158
4161
|
stdio: "ignore"
|
|
@@ -4163,7 +4166,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4163
4166
|
settled = true;
|
|
4164
4167
|
signal?.removeEventListener("abort", onAbort);
|
|
4165
4168
|
clearTimeout(timer);
|
|
4166
|
-
|
|
4169
|
+
resolve19(ok);
|
|
4167
4170
|
};
|
|
4168
4171
|
const onAbort = () => {
|
|
4169
4172
|
try {
|
|
@@ -4185,7 +4188,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4185
4188
|
});
|
|
4186
4189
|
}
|
|
4187
4190
|
_runScript(scriptPath, stdinData, signal) {
|
|
4188
|
-
return new Promise((
|
|
4191
|
+
return new Promise((resolve19) => {
|
|
4189
4192
|
const proc = spawn4("python3", [scriptPath], {
|
|
4190
4193
|
env: process.env,
|
|
4191
4194
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4198,7 +4201,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4198
4201
|
settled = true;
|
|
4199
4202
|
signal?.removeEventListener("abort", onAbort);
|
|
4200
4203
|
clearTimeout(timer);
|
|
4201
|
-
|
|
4204
|
+
resolve19({ stdout: out.join(""), stderr: err.join(""), code });
|
|
4202
4205
|
};
|
|
4203
4206
|
const onAbort = () => {
|
|
4204
4207
|
try {
|
|
@@ -4227,13 +4230,13 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4227
4230
|
}
|
|
4228
4231
|
});
|
|
4229
4232
|
|
|
4230
|
-
// packages/daemon/src/
|
|
4233
|
+
// packages/daemon/src/tools/SurgeCapability.ts
|
|
4231
4234
|
import { execSync as execSync3 } from "node:child_process";
|
|
4232
4235
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, copyFileSync, statSync } from "node:fs";
|
|
4233
4236
|
import { join } from "node:path";
|
|
4234
4237
|
var SurgeCapability;
|
|
4235
4238
|
var init_SurgeCapability = __esm({
|
|
4236
|
-
"packages/daemon/src/
|
|
4239
|
+
"packages/daemon/src/tools/SurgeCapability.ts"() {
|
|
4237
4240
|
"use strict";
|
|
4238
4241
|
SurgeCapability = class {
|
|
4239
4242
|
name = "surge_publish";
|
|
@@ -4307,10 +4310,10 @@ ${out}`,
|
|
|
4307
4310
|
}
|
|
4308
4311
|
});
|
|
4309
4312
|
|
|
4310
|
-
// packages/daemon/src/
|
|
4313
|
+
// packages/daemon/src/tools/BrowserExecuteCapability.ts
|
|
4311
4314
|
var BrowserExecuteCapability;
|
|
4312
4315
|
var init_BrowserExecuteCapability = __esm({
|
|
4313
|
-
"packages/daemon/src/
|
|
4316
|
+
"packages/daemon/src/tools/BrowserExecuteCapability.ts"() {
|
|
4314
4317
|
"use strict";
|
|
4315
4318
|
BrowserExecuteCapability = class {
|
|
4316
4319
|
name = "browser_execute";
|
|
@@ -4584,11 +4587,11 @@ var init_BrowserExecuteCapability = __esm({
|
|
|
4584
4587
|
}
|
|
4585
4588
|
});
|
|
4586
4589
|
|
|
4587
|
-
// packages/daemon/src/
|
|
4590
|
+
// packages/daemon/src/tools/OCRExtractCapability.ts
|
|
4588
4591
|
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "node:fs";
|
|
4589
4592
|
var OCRExtractCapability;
|
|
4590
4593
|
var init_OCRExtractCapability = __esm({
|
|
4591
|
-
"packages/daemon/src/
|
|
4594
|
+
"packages/daemon/src/tools/OCRExtractCapability.ts"() {
|
|
4592
4595
|
"use strict";
|
|
4593
4596
|
OCRExtractCapability = class {
|
|
4594
4597
|
name = "ocr_extract";
|
|
@@ -4747,11 +4750,11 @@ ${JSON.stringify(result.fields, null, 2)}`,
|
|
|
4747
4750
|
}
|
|
4748
4751
|
});
|
|
4749
4752
|
|
|
4750
|
-
// packages/daemon/src/
|
|
4753
|
+
// packages/daemon/src/tools/CredentialVaultCapability.ts
|
|
4751
4754
|
import { randomBytes, createCipheriv, createDecipheriv } from "node:crypto";
|
|
4752
4755
|
var sessionKeys, credStore, CredentialVaultCapability;
|
|
4753
4756
|
var init_CredentialVaultCapability = __esm({
|
|
4754
|
-
"packages/daemon/src/
|
|
4757
|
+
"packages/daemon/src/tools/CredentialVaultCapability.ts"() {
|
|
4755
4758
|
"use strict";
|
|
4756
4759
|
sessionKeys = /* @__PURE__ */ new Map();
|
|
4757
4760
|
credStore = /* @__PURE__ */ new Map();
|
|
@@ -4862,10 +4865,10 @@ var init_CredentialVaultCapability = __esm({
|
|
|
4862
4865
|
}
|
|
4863
4866
|
});
|
|
4864
4867
|
|
|
4865
|
-
// packages/daemon/src/
|
|
4868
|
+
// packages/daemon/src/tools/MonitorWatchCapability.ts
|
|
4866
4869
|
var DAEMON_URL, MonitorWatchCapability;
|
|
4867
4870
|
var init_MonitorWatchCapability = __esm({
|
|
4868
|
-
"packages/daemon/src/
|
|
4871
|
+
"packages/daemon/src/tools/MonitorWatchCapability.ts"() {
|
|
4869
4872
|
"use strict";
|
|
4870
4873
|
DAEMON_URL = "http://localhost:4200";
|
|
4871
4874
|
MonitorWatchCapability = class {
|
|
@@ -5050,10 +5053,10 @@ ${lines.join("\n")}`,
|
|
|
5050
5053
|
}
|
|
5051
5054
|
});
|
|
5052
5055
|
|
|
5053
|
-
// packages/daemon/src/
|
|
5056
|
+
// packages/daemon/src/tools/SessionSearchCapability.ts
|
|
5054
5057
|
var SessionSearchCapability;
|
|
5055
5058
|
var init_SessionSearchCapability = __esm({
|
|
5056
|
-
"packages/daemon/src/
|
|
5059
|
+
"packages/daemon/src/tools/SessionSearchCapability.ts"() {
|
|
5057
5060
|
"use strict";
|
|
5058
5061
|
SessionSearchCapability = class {
|
|
5059
5062
|
name = "session_search";
|
|
@@ -5132,14 +5135,343 @@ ${results.join("\n\n")}`,
|
|
|
5132
5135
|
}
|
|
5133
5136
|
});
|
|
5134
5137
|
|
|
5135
|
-
// packages/daemon/src/
|
|
5138
|
+
// packages/daemon/src/tools/WorktreeCapability.ts
|
|
5139
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
5140
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
5141
|
+
import { resolve as resolve5, basename } from "node:path";
|
|
5142
|
+
var activeWorktrees, WorktreeCapability;
|
|
5143
|
+
var init_WorktreeCapability = __esm({
|
|
5144
|
+
"packages/daemon/src/tools/WorktreeCapability.ts"() {
|
|
5145
|
+
"use strict";
|
|
5146
|
+
activeWorktrees = /* @__PURE__ */ new Map();
|
|
5147
|
+
WorktreeCapability = class {
|
|
5148
|
+
name = "worktree";
|
|
5149
|
+
description = "Create isolated git worktrees for safe parallel branch work.";
|
|
5150
|
+
toolDefinition = {
|
|
5151
|
+
name: "worktree",
|
|
5152
|
+
description: 'Manage git worktrees for isolated parallel development. Operations: "enter" (create worktree + branch), "exit" (remove/keep), "list" (show active). Use this when you need to work on a separate branch without affecting the current working tree.',
|
|
5153
|
+
input_schema: {
|
|
5154
|
+
type: "object",
|
|
5155
|
+
properties: {
|
|
5156
|
+
op: { type: "string", description: "Operation: enter, exit, list" },
|
|
5157
|
+
branch: { type: "string", description: "Branch name for new worktree (enter only). Auto-generated if omitted." },
|
|
5158
|
+
keep: { type: "string", description: 'Set to "true" to keep worktree on exit (default: remove)' },
|
|
5159
|
+
id: { type: "string", description: 'Worktree ID for exit (if multiple active). Use "list" to see IDs.' }
|
|
5160
|
+
},
|
|
5161
|
+
required: ["op"]
|
|
5162
|
+
}
|
|
5163
|
+
};
|
|
5164
|
+
async execute(input, cwd) {
|
|
5165
|
+
const start = Date.now();
|
|
5166
|
+
const op = String(input.op ?? "");
|
|
5167
|
+
switch (op) {
|
|
5168
|
+
case "enter":
|
|
5169
|
+
return this._enter(input, cwd, start);
|
|
5170
|
+
case "exit":
|
|
5171
|
+
return this._exit(input, cwd, start);
|
|
5172
|
+
case "list":
|
|
5173
|
+
return this._list(start);
|
|
5174
|
+
default:
|
|
5175
|
+
return { success: false, output: `Unknown op: ${op}. Use enter, exit, or list.`, duration_ms: 0 };
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
_enter(input, cwd, start) {
|
|
5179
|
+
try {
|
|
5180
|
+
execSync4("git rev-parse --git-dir", { cwd, stdio: "pipe" });
|
|
5181
|
+
} catch {
|
|
5182
|
+
return { success: false, output: "Not in a git repository.", duration_ms: 0 };
|
|
5183
|
+
}
|
|
5184
|
+
const branch = input.branch ? String(input.branch).replace(/[^a-zA-Z0-9\-_\/]/g, "-") : `0agent-wt-${Date.now().toString(36)}`;
|
|
5185
|
+
const repoRoot = execSync4("git rev-parse --show-toplevel", { cwd, encoding: "utf8" }).trim();
|
|
5186
|
+
const worktreePath = resolve5(repoRoot, "..", `${basename(repoRoot)}-${branch}`);
|
|
5187
|
+
if (existsSync5(worktreePath)) {
|
|
5188
|
+
return { success: false, output: `Worktree path already exists: ${worktreePath}`, duration_ms: 0 };
|
|
5189
|
+
}
|
|
5190
|
+
try {
|
|
5191
|
+
execSync4(`git worktree add -b "${branch}" "${worktreePath}"`, { cwd, stdio: "pipe" });
|
|
5192
|
+
const id = `wt-${Date.now().toString(36)}`;
|
|
5193
|
+
activeWorktrees.set(id, { originalCwd: cwd, worktreePath, branch });
|
|
5194
|
+
return {
|
|
5195
|
+
success: true,
|
|
5196
|
+
output: [
|
|
5197
|
+
`Worktree created:`,
|
|
5198
|
+
` ID: ${id}`,
|
|
5199
|
+
` Branch: ${branch}`,
|
|
5200
|
+
` Path: ${worktreePath}`,
|
|
5201
|
+
` Original cwd: ${cwd}`,
|
|
5202
|
+
``,
|
|
5203
|
+
`Switch to the worktree by running commands in: ${worktreePath}`,
|
|
5204
|
+
`When done, call worktree(op:"exit", id:"${id}") to clean up.`
|
|
5205
|
+
].join("\n"),
|
|
5206
|
+
structured: { id, branch, worktreePath, originalCwd: cwd },
|
|
5207
|
+
duration_ms: Date.now() - start
|
|
5208
|
+
};
|
|
5209
|
+
} catch (err) {
|
|
5210
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5211
|
+
return { success: false, output: `Failed to create worktree: ${msg}`, duration_ms: Date.now() - start };
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
_exit(input, _cwd, start) {
|
|
5215
|
+
const id = String(input.id ?? "");
|
|
5216
|
+
const keep = String(input.keep ?? "") === "true";
|
|
5217
|
+
let entry;
|
|
5218
|
+
let entryId = id;
|
|
5219
|
+
if (id) {
|
|
5220
|
+
entry = activeWorktrees.get(id);
|
|
5221
|
+
} else {
|
|
5222
|
+
const keys = [...activeWorktrees.keys()];
|
|
5223
|
+
if (keys.length > 0) {
|
|
5224
|
+
entryId = keys[keys.length - 1];
|
|
5225
|
+
entry = activeWorktrees.get(entryId);
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
if (!entry) {
|
|
5229
|
+
return { success: false, output: id ? `No worktree with ID: ${id}` : "No active worktrees.", duration_ms: 0 };
|
|
5230
|
+
}
|
|
5231
|
+
if (keep) {
|
|
5232
|
+
activeWorktrees.delete(entryId);
|
|
5233
|
+
return {
|
|
5234
|
+
success: true,
|
|
5235
|
+
output: `Worktree kept at: ${entry.worktreePath} (branch: ${entry.branch}). Original cwd: ${entry.originalCwd}`,
|
|
5236
|
+
duration_ms: Date.now() - start
|
|
5237
|
+
};
|
|
5238
|
+
}
|
|
5239
|
+
try {
|
|
5240
|
+
execSync4(`git worktree remove "${entry.worktreePath}" --force`, {
|
|
5241
|
+
cwd: entry.originalCwd,
|
|
5242
|
+
stdio: "pipe"
|
|
5243
|
+
});
|
|
5244
|
+
try {
|
|
5245
|
+
execSync4(`git branch -D "${entry.branch}"`, { cwd: entry.originalCwd, stdio: "pipe" });
|
|
5246
|
+
} catch {
|
|
5247
|
+
}
|
|
5248
|
+
activeWorktrees.delete(entryId);
|
|
5249
|
+
return {
|
|
5250
|
+
success: true,
|
|
5251
|
+
output: `Worktree removed. Branch "${entry.branch}" deleted. Restored to: ${entry.originalCwd}`,
|
|
5252
|
+
duration_ms: Date.now() - start
|
|
5253
|
+
};
|
|
5254
|
+
} catch (err) {
|
|
5255
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5256
|
+
return { success: false, output: `Failed to remove worktree: ${msg}`, duration_ms: Date.now() - start };
|
|
5257
|
+
}
|
|
5258
|
+
}
|
|
5259
|
+
_list(start) {
|
|
5260
|
+
if (activeWorktrees.size === 0) {
|
|
5261
|
+
return { success: true, output: "No active worktrees.", duration_ms: Date.now() - start };
|
|
5262
|
+
}
|
|
5263
|
+
const lines = [...activeWorktrees.entries()].map(
|
|
5264
|
+
([id, wt]) => ` ${id}: ${wt.branch} \u2192 ${wt.worktreePath}`
|
|
5265
|
+
);
|
|
5266
|
+
return {
|
|
5267
|
+
success: true,
|
|
5268
|
+
output: `Active worktrees:
|
|
5269
|
+
${lines.join("\n")}`,
|
|
5270
|
+
structured: [...activeWorktrees.entries()].map(([id, wt]) => ({ id, ...wt })),
|
|
5271
|
+
duration_ms: Date.now() - start
|
|
5272
|
+
};
|
|
5273
|
+
}
|
|
5274
|
+
};
|
|
5275
|
+
}
|
|
5276
|
+
});
|
|
5277
|
+
|
|
5278
|
+
// packages/daemon/src/tools/LSPCapability.ts
|
|
5279
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
5280
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
5281
|
+
import { resolve as resolve6, extname } from "node:path";
|
|
5282
|
+
var LSPCapability;
|
|
5283
|
+
var init_LSPCapability = __esm({
|
|
5284
|
+
"packages/daemon/src/tools/LSPCapability.ts"() {
|
|
5285
|
+
"use strict";
|
|
5286
|
+
LSPCapability = class {
|
|
5287
|
+
name = "lsp";
|
|
5288
|
+
description = "Code intelligence: go-to-definition, find-references, hover, symbols via LSP.";
|
|
5289
|
+
toolDefinition = {
|
|
5290
|
+
name: "lsp",
|
|
5291
|
+
description: 'Language Server Protocol code intelligence. Operations: "definition" (go to definition of symbol at position), "references" (find all references to symbol), "hover" (get type info and docs for symbol), "symbols" (list all symbols in a file). Requires a language server for the file type (auto-detected).',
|
|
5292
|
+
input_schema: {
|
|
5293
|
+
type: "object",
|
|
5294
|
+
properties: {
|
|
5295
|
+
op: { type: "string", description: "Operation: definition, references, hover, symbols" },
|
|
5296
|
+
file: { type: "string", description: "Absolute or relative file path" },
|
|
5297
|
+
line: { type: "string", description: "Line number (1-based) for definition/references/hover" },
|
|
5298
|
+
column: { type: "string", description: "Column number (1-based) for definition/references/hover" },
|
|
5299
|
+
symbol: { type: "string", description: "Symbol name to search for (alternative to line+column \u2014 uses grep to find position)" }
|
|
5300
|
+
},
|
|
5301
|
+
required: ["op", "file"]
|
|
5302
|
+
}
|
|
5303
|
+
};
|
|
5304
|
+
async execute(input, cwd) {
|
|
5305
|
+
const start = Date.now();
|
|
5306
|
+
const op = String(input.op ?? "");
|
|
5307
|
+
let file = String(input.file ?? "");
|
|
5308
|
+
const line = Number(input.line ?? 1) - 1;
|
|
5309
|
+
const column = Number(input.column ?? 1) - 1;
|
|
5310
|
+
const symbol = input.symbol ? String(input.symbol) : void 0;
|
|
5311
|
+
if (!file) return { success: false, output: "file is required", duration_ms: 0 };
|
|
5312
|
+
if (!file.startsWith("/")) file = resolve6(cwd, file);
|
|
5313
|
+
if (!existsSync6(file)) return { success: false, output: `File not found: ${file}`, duration_ms: 0 };
|
|
5314
|
+
let actualLine = line;
|
|
5315
|
+
let actualCol = column;
|
|
5316
|
+
if (symbol) {
|
|
5317
|
+
const pos = this._findSymbolPosition(file, symbol);
|
|
5318
|
+
if (pos) {
|
|
5319
|
+
actualLine = pos.line;
|
|
5320
|
+
actualCol = pos.column;
|
|
5321
|
+
} else {
|
|
5322
|
+
return { success: false, output: `Symbol "${symbol}" not found in ${file}`, duration_ms: Date.now() - start };
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
const ext = extname(file).toLowerCase();
|
|
5326
|
+
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
5327
|
+
return this._tsOperation(op, file, actualLine, actualCol, cwd, start);
|
|
5328
|
+
}
|
|
5329
|
+
return this._grepFallback(op, file, actualLine, actualCol, symbol, cwd, start);
|
|
5330
|
+
}
|
|
5331
|
+
/**
|
|
5332
|
+
* TypeScript/JavaScript operations using tsserver protocol.
|
|
5333
|
+
*/
|
|
5334
|
+
_tsOperation(op, file, line, column, cwd, start) {
|
|
5335
|
+
try {
|
|
5336
|
+
switch (op) {
|
|
5337
|
+
case "definition": {
|
|
5338
|
+
const content = readFileSync4(file, "utf8");
|
|
5339
|
+
const lines = content.split("\n");
|
|
5340
|
+
const targetLine = lines[line] ?? "";
|
|
5341
|
+
const word = this._getWordAt(targetLine, column);
|
|
5342
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5343
|
+
const defPatterns = [
|
|
5344
|
+
`(function|const|let|var|class|interface|type|enum)\\s+${word}\\b`,
|
|
5345
|
+
`${word}\\s*[:=]\\s*(function|\\()`,
|
|
5346
|
+
`export\\s+(default\\s+)?(function|class|const|let|var|type|interface)\\s+${word}`
|
|
5347
|
+
];
|
|
5348
|
+
const results = [];
|
|
5349
|
+
for (const pattern of defPatterns) {
|
|
5350
|
+
try {
|
|
5351
|
+
const grep = execSync5(
|
|
5352
|
+
`rg -n "${pattern}" --type ts --type js "${cwd}" 2>/dev/null | head -10`,
|
|
5353
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5354
|
+
).trim();
|
|
5355
|
+
if (grep) results.push(grep);
|
|
5356
|
+
} catch {
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
if (!results.length) {
|
|
5360
|
+
return { success: true, output: `No definition found for "${word}"`, duration_ms: Date.now() - start };
|
|
5361
|
+
}
|
|
5362
|
+
return {
|
|
5363
|
+
success: true,
|
|
5364
|
+
output: `Definition of "${word}":
|
|
5365
|
+
${results.join("\n")}`,
|
|
5366
|
+
duration_ms: Date.now() - start
|
|
5367
|
+
};
|
|
5368
|
+
}
|
|
5369
|
+
case "references": {
|
|
5370
|
+
const content = readFileSync4(file, "utf8");
|
|
5371
|
+
const lines = content.split("\n");
|
|
5372
|
+
const word = this._getWordAt(lines[line] ?? "", column);
|
|
5373
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5374
|
+
try {
|
|
5375
|
+
const grep = execSync5(
|
|
5376
|
+
`rg -n "\\b${word}\\b" --type ts --type js "${cwd}" 2>/dev/null | head -20`,
|
|
5377
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5378
|
+
).trim();
|
|
5379
|
+
const refCount = grep.split("\n").filter(Boolean).length;
|
|
5380
|
+
return {
|
|
5381
|
+
success: true,
|
|
5382
|
+
output: `References to "${word}" (${refCount} found):
|
|
5383
|
+
${grep}`,
|
|
5384
|
+
duration_ms: Date.now() - start
|
|
5385
|
+
};
|
|
5386
|
+
} catch {
|
|
5387
|
+
return { success: true, output: `No references found for "${word}"`, duration_ms: Date.now() - start };
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
case "hover": {
|
|
5391
|
+
const content = readFileSync4(file, "utf8");
|
|
5392
|
+
const lines = content.split("\n");
|
|
5393
|
+
const word = this._getWordAt(lines[line] ?? "", column);
|
|
5394
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5395
|
+
const surroundingLines = lines.slice(Math.max(0, line - 3), line + 4);
|
|
5396
|
+
return {
|
|
5397
|
+
success: true,
|
|
5398
|
+
output: `Symbol: ${word}
|
|
5399
|
+
Context (${file}:${line + 1}:${column + 1}):
|
|
5400
|
+
${surroundingLines.join("\n")}`,
|
|
5401
|
+
duration_ms: Date.now() - start
|
|
5402
|
+
};
|
|
5403
|
+
}
|
|
5404
|
+
case "symbols": {
|
|
5405
|
+
try {
|
|
5406
|
+
const grep = execSync5(
|
|
5407
|
+
`rg -n "^\\s*(export\\s+)?(function|class|interface|type|enum|const|let|var)\\s+\\w+" "${file}" 2>/dev/null`,
|
|
5408
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5409
|
+
).trim();
|
|
5410
|
+
return {
|
|
5411
|
+
success: true,
|
|
5412
|
+
output: `Symbols in ${file}:
|
|
5413
|
+
${grep || "(no symbols found)"}`,
|
|
5414
|
+
duration_ms: Date.now() - start
|
|
5415
|
+
};
|
|
5416
|
+
} catch {
|
|
5417
|
+
return { success: true, output: `No symbols found in ${file}`, duration_ms: Date.now() - start };
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
default:
|
|
5421
|
+
return { success: false, output: `Unknown op: ${op}`, duration_ms: 0 };
|
|
5422
|
+
}
|
|
5423
|
+
} catch (err) {
|
|
5424
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5425
|
+
return { success: false, output: `LSP operation failed: ${msg}`, duration_ms: Date.now() - start };
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
_grepFallback(op, file, line, column, symbol, cwd, start) {
|
|
5429
|
+
const content = readFileSync4(file, "utf8");
|
|
5430
|
+
const lines = content.split("\n");
|
|
5431
|
+
const word = symbol || this._getWordAt(lines[line] ?? "", column);
|
|
5432
|
+
if (!word) return { success: false, output: "No symbol to search for", duration_ms: 0 };
|
|
5433
|
+
try {
|
|
5434
|
+
const grep = execSync5(
|
|
5435
|
+
`rg -n "\\b${word}\\b" "${cwd}" 2>/dev/null | head -20`,
|
|
5436
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5437
|
+
).trim();
|
|
5438
|
+
return {
|
|
5439
|
+
success: true,
|
|
5440
|
+
output: `${op} for "${word}" (grep fallback):
|
|
5441
|
+
${grep || "(no results)"}`,
|
|
5442
|
+
duration_ms: Date.now() - start
|
|
5443
|
+
};
|
|
5444
|
+
} catch {
|
|
5445
|
+
return { success: true, output: `No results for "${word}"`, duration_ms: Date.now() - start };
|
|
5446
|
+
}
|
|
5447
|
+
}
|
|
5448
|
+
_findSymbolPosition(file, symbol) {
|
|
5449
|
+
const content = readFileSync4(file, "utf8");
|
|
5450
|
+
const lines = content.split("\n");
|
|
5451
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5452
|
+
const col = lines[i].indexOf(symbol);
|
|
5453
|
+
if (col !== -1) return { line: i, column: col };
|
|
5454
|
+
}
|
|
5455
|
+
return null;
|
|
5456
|
+
}
|
|
5457
|
+
_getWordAt(line, col) {
|
|
5458
|
+
const before = line.slice(0, col + 1).match(/[\w$]+$/)?.[0] ?? "";
|
|
5459
|
+
const after = line.slice(col + 1).match(/^[\w$]*/)?.[0] ?? "";
|
|
5460
|
+
const word = before + after;
|
|
5461
|
+
return word.length > 0 ? word : null;
|
|
5462
|
+
}
|
|
5463
|
+
};
|
|
5464
|
+
}
|
|
5465
|
+
});
|
|
5466
|
+
|
|
5467
|
+
// packages/daemon/src/tools/CodespaceBrowserCapability.ts
|
|
5136
5468
|
var CodespaceBrowserCapability_exports = {};
|
|
5137
5469
|
__export(CodespaceBrowserCapability_exports, {
|
|
5138
5470
|
CodespaceBrowserCapability: () => CodespaceBrowserCapability
|
|
5139
5471
|
});
|
|
5140
5472
|
var CodespaceBrowserCapability;
|
|
5141
5473
|
var init_CodespaceBrowserCapability = __esm({
|
|
5142
|
-
"packages/daemon/src/
|
|
5474
|
+
"packages/daemon/src/tools/CodespaceBrowserCapability.ts"() {
|
|
5143
5475
|
"use strict";
|
|
5144
5476
|
init_BrowserCapability();
|
|
5145
5477
|
CodespaceBrowserCapability = class {
|
|
@@ -5206,10 +5538,10 @@ var init_CodespaceBrowserCapability = __esm({
|
|
|
5206
5538
|
}
|
|
5207
5539
|
});
|
|
5208
5540
|
|
|
5209
|
-
// packages/daemon/src/
|
|
5541
|
+
// packages/daemon/src/tools/CapabilityRegistry.ts
|
|
5210
5542
|
var CapabilityRegistry;
|
|
5211
5543
|
var init_CapabilityRegistry = __esm({
|
|
5212
|
-
"packages/daemon/src/
|
|
5544
|
+
"packages/daemon/src/tools/CapabilityRegistry.ts"() {
|
|
5213
5545
|
"use strict";
|
|
5214
5546
|
init_WebSearchCapability();
|
|
5215
5547
|
init_BrowserCapability();
|
|
@@ -5225,6 +5557,8 @@ var init_CapabilityRegistry = __esm({
|
|
|
5225
5557
|
init_CredentialVaultCapability();
|
|
5226
5558
|
init_MonitorWatchCapability();
|
|
5227
5559
|
init_SessionSearchCapability();
|
|
5560
|
+
init_WorktreeCapability();
|
|
5561
|
+
init_LSPCapability();
|
|
5228
5562
|
CapabilityRegistry = class {
|
|
5229
5563
|
capabilities = /* @__PURE__ */ new Map();
|
|
5230
5564
|
/**
|
|
@@ -5262,6 +5596,8 @@ var init_CapabilityRegistry = __esm({
|
|
|
5262
5596
|
if (dbPath) {
|
|
5263
5597
|
this.register(new SessionSearchCapability(() => dbPath));
|
|
5264
5598
|
}
|
|
5599
|
+
this.register(new WorktreeCapability());
|
|
5600
|
+
this.register(new LSPCapability());
|
|
5265
5601
|
if (graph) {
|
|
5266
5602
|
this.register(new MemoryCapability(graph, onMemoryWrite));
|
|
5267
5603
|
}
|
|
@@ -5302,6 +5638,10 @@ var init_CapabilityRegistry = __esm({
|
|
|
5302
5638
|
active.add("computer_use");
|
|
5303
5639
|
active.add("gui_automation");
|
|
5304
5640
|
}
|
|
5641
|
+
if (/implement|build|write|fix|refactor|debug|test|definition|reference|hover|symbol|branch|worktree|isolat|parallel.*work/i.test(lower)) {
|
|
5642
|
+
active.add("lsp");
|
|
5643
|
+
active.add("worktree");
|
|
5644
|
+
}
|
|
5305
5645
|
if (/book|file|itr|tax|irctc|train|ticket|flight|passport|appointment|login|portal|form.*fill|ocr|extract|document|pan.*card|aadhaar|credential|password|otp|monitor|watch|alert|notify.*when|price.*drop|slot.*available|justdo/i.test(lower)) {
|
|
5306
5646
|
active.add("browser_execute");
|
|
5307
5647
|
active.add("ocr_extract");
|
|
@@ -5332,9 +5672,9 @@ var init_CapabilityRegistry = __esm({
|
|
|
5332
5672
|
}
|
|
5333
5673
|
});
|
|
5334
5674
|
|
|
5335
|
-
// packages/daemon/src/
|
|
5336
|
-
var
|
|
5337
|
-
"packages/daemon/src/
|
|
5675
|
+
// packages/daemon/src/tools/index.ts
|
|
5676
|
+
var init_tools = __esm({
|
|
5677
|
+
"packages/daemon/src/tools/index.ts"() {
|
|
5338
5678
|
"use strict";
|
|
5339
5679
|
init_CapabilityRegistry();
|
|
5340
5680
|
init_WebSearchCapability();
|
|
@@ -5349,13 +5689,15 @@ var init_capabilities = __esm({
|
|
|
5349
5689
|
init_CredentialVaultCapability();
|
|
5350
5690
|
init_MonitorWatchCapability();
|
|
5351
5691
|
init_SessionSearchCapability();
|
|
5692
|
+
init_WorktreeCapability();
|
|
5693
|
+
init_LSPCapability();
|
|
5352
5694
|
}
|
|
5353
5695
|
});
|
|
5354
5696
|
|
|
5355
|
-
// packages/daemon/src/IterationBudget.ts
|
|
5697
|
+
// packages/daemon/src/utils/IterationBudget.ts
|
|
5356
5698
|
var IterationBudget;
|
|
5357
5699
|
var init_IterationBudget = __esm({
|
|
5358
|
-
"packages/daemon/src/IterationBudget.ts"() {
|
|
5700
|
+
"packages/daemon/src/utils/IterationBudget.ts"() {
|
|
5359
5701
|
"use strict";
|
|
5360
5702
|
IterationBudget = class _IterationBudget {
|
|
5361
5703
|
constructor(maxIterations, parent, childAllocation) {
|
|
@@ -5432,7 +5774,7 @@ var init_IterationBudget = __esm({
|
|
|
5432
5774
|
}
|
|
5433
5775
|
});
|
|
5434
5776
|
|
|
5435
|
-
// packages/daemon/src/PromptInjectionScanner.ts
|
|
5777
|
+
// packages/daemon/src/utils/PromptInjectionScanner.ts
|
|
5436
5778
|
function scanForInjection(content, source) {
|
|
5437
5779
|
const warnings = [];
|
|
5438
5780
|
let sanitized = content;
|
|
@@ -5469,7 +5811,7 @@ function sanitizeContextFile(content, filePath, log) {
|
|
|
5469
5811
|
}
|
|
5470
5812
|
var INJECTION_PATTERNS, INVISIBLE_CHARS;
|
|
5471
5813
|
var init_PromptInjectionScanner = __esm({
|
|
5472
|
-
"packages/daemon/src/PromptInjectionScanner.ts"() {
|
|
5814
|
+
"packages/daemon/src/utils/PromptInjectionScanner.ts"() {
|
|
5473
5815
|
"use strict";
|
|
5474
5816
|
INJECTION_PATTERNS = [
|
|
5475
5817
|
// Direct instruction override
|
|
@@ -5495,19 +5837,160 @@ var init_PromptInjectionScanner = __esm({
|
|
|
5495
5837
|
}
|
|
5496
5838
|
});
|
|
5497
5839
|
|
|
5840
|
+
// packages/daemon/src/utils/ContextCollapse.ts
|
|
5841
|
+
function collapseContext(messages, tailKeep = 10) {
|
|
5842
|
+
if (messages.length <= tailKeep) return messages;
|
|
5843
|
+
const cutIndex = messages.length - tailKeep;
|
|
5844
|
+
const prefix = messages.slice(0, cutIndex);
|
|
5845
|
+
const tail = messages.slice(cutIndex);
|
|
5846
|
+
const collapsed = [];
|
|
5847
|
+
for (const msg of prefix) {
|
|
5848
|
+
if (msg.role === "tool") {
|
|
5849
|
+
collapsed.push({
|
|
5850
|
+
...msg,
|
|
5851
|
+
content: collapseToolResult(msg.content, msg.tool_call_id)
|
|
5852
|
+
});
|
|
5853
|
+
} else if (msg.role === "assistant" && msg.tool_calls) {
|
|
5854
|
+
collapsed.push({
|
|
5855
|
+
...msg,
|
|
5856
|
+
content: msg.content.length > 200 ? msg.content.slice(0, 200) + "\u2026" : msg.content
|
|
5857
|
+
});
|
|
5858
|
+
} else {
|
|
5859
|
+
collapsed.push(msg);
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
return [...collapsed, ...tail];
|
|
5863
|
+
}
|
|
5864
|
+
function collapseToolResult(content, toolCallId) {
|
|
5865
|
+
const lineCount = content.split("\n").length;
|
|
5866
|
+
const charCount = content.length;
|
|
5867
|
+
if (charCount <= 200) return content;
|
|
5868
|
+
if (/^(1\t| 1\t|\d+\|)/.test(content)) {
|
|
5869
|
+
const lastLine = content.trim().split("\n").pop() ?? "";
|
|
5870
|
+
const lineNum = lastLine.match(/^(\d+)/)?.[1] ?? String(lineCount);
|
|
5871
|
+
return `[file content: ${lineNum} lines, ${charCount} chars \u2014 collapsed]`;
|
|
5872
|
+
}
|
|
5873
|
+
if (content.startsWith("(no output)") || content.startsWith("exit ")) {
|
|
5874
|
+
return content.slice(0, 100);
|
|
5875
|
+
}
|
|
5876
|
+
if (/^(Error|FAIL|Traceback|SyntaxError|TypeError|ReferenceError)/i.test(content)) {
|
|
5877
|
+
const lines = content.split("\n");
|
|
5878
|
+
return lines.slice(0, 2).join("\n") + (lines.length > 2 ? `
|
|
5879
|
+
[...${lines.length - 2} more lines]` : "");
|
|
5880
|
+
}
|
|
5881
|
+
const fileMatches = content.match(/^[^\n]+:\d+:/gm);
|
|
5882
|
+
if (fileMatches) {
|
|
5883
|
+
const uniqueFiles = new Set(fileMatches.map((m) => m.split(":")[0]));
|
|
5884
|
+
return `[search: ${fileMatches.length} matches in ${uniqueFiles.size} files \u2014 collapsed]`;
|
|
5885
|
+
}
|
|
5886
|
+
if (content.startsWith("{") || content.startsWith("[")) {
|
|
5887
|
+
return `[JSON output: ${charCount} chars \u2014 collapsed]`;
|
|
5888
|
+
}
|
|
5889
|
+
const urlMatch = content.match(/https?:\/\/[^\s]+\.surge\.sh/);
|
|
5890
|
+
if (urlMatch) {
|
|
5891
|
+
return `[published: ${urlMatch[0]}]`;
|
|
5892
|
+
}
|
|
5893
|
+
const firstLine = content.split("\n")[0].slice(0, 100);
|
|
5894
|
+
return `${firstLine}\u2026 [${lineCount} lines, ${charCount} chars \u2014 collapsed]`;
|
|
5895
|
+
}
|
|
5896
|
+
var init_ContextCollapse = __esm({
|
|
5897
|
+
"packages/daemon/src/utils/ContextCollapse.ts"() {
|
|
5898
|
+
"use strict";
|
|
5899
|
+
}
|
|
5900
|
+
});
|
|
5901
|
+
|
|
5902
|
+
// packages/daemon/src/services/StreamingToolExecutor.ts
|
|
5903
|
+
function isPreExecSafe(tc) {
|
|
5904
|
+
if (PRE_EXEC_SAFE.has(tc.name)) return true;
|
|
5905
|
+
if (tc.name === "file_op" && tc.input.op === "read") return true;
|
|
5906
|
+
if (tc.name === "file_op" && tc.input.op === "list") return true;
|
|
5907
|
+
if (tc.name === "ocr_extract") return true;
|
|
5908
|
+
return false;
|
|
5909
|
+
}
|
|
5910
|
+
var PRE_EXEC_SAFE, StreamingToolExecutor;
|
|
5911
|
+
var init_StreamingToolExecutor = __esm({
|
|
5912
|
+
"packages/daemon/src/services/StreamingToolExecutor.ts"() {
|
|
5913
|
+
"use strict";
|
|
5914
|
+
PRE_EXEC_SAFE = /* @__PURE__ */ new Set([
|
|
5915
|
+
"web_search",
|
|
5916
|
+
"scrape_url",
|
|
5917
|
+
"session_search",
|
|
5918
|
+
"lsp"
|
|
5919
|
+
]);
|
|
5920
|
+
StreamingToolExecutor = class {
|
|
5921
|
+
pending = /* @__PURE__ */ new Map();
|
|
5922
|
+
registry;
|
|
5923
|
+
cwd;
|
|
5924
|
+
signal;
|
|
5925
|
+
constructor(registry, cwd, signal) {
|
|
5926
|
+
this.registry = registry;
|
|
5927
|
+
this.cwd = cwd;
|
|
5928
|
+
this.signal = signal;
|
|
5929
|
+
}
|
|
5930
|
+
/**
|
|
5931
|
+
* Called by LLMExecutor's onToolUseBlock callback during streaming.
|
|
5932
|
+
* Starts executing the tool immediately if it's safe to pre-execute.
|
|
5933
|
+
*/
|
|
5934
|
+
onToolBlock(tc) {
|
|
5935
|
+
if (!isPreExecSafe(tc)) return;
|
|
5936
|
+
const promise = this.registry.execute(tc.name, tc.input, this.cwd, this.signal);
|
|
5937
|
+
this.pending.set(tc.id, { promise, toolCall: tc, started: Date.now() });
|
|
5938
|
+
}
|
|
5939
|
+
/**
|
|
5940
|
+
* Get a pre-executed result if available, or execute now.
|
|
5941
|
+
* Returns the result string (same contract as _executeSingleTool).
|
|
5942
|
+
*/
|
|
5943
|
+
async getOrExecute(tc, fallbackExecute) {
|
|
5944
|
+
const pending = this.pending.get(tc.id);
|
|
5945
|
+
if (pending) {
|
|
5946
|
+
try {
|
|
5947
|
+
const capResult = await pending.promise;
|
|
5948
|
+
const MAX_TOOL_OUTPUT = 4e3;
|
|
5949
|
+
let result = capResult.output;
|
|
5950
|
+
if (result.length > MAX_TOOL_OUTPUT) {
|
|
5951
|
+
result = result.slice(0, MAX_TOOL_OUTPUT) + `
|
|
5952
|
+
[...${result.length - MAX_TOOL_OUTPUT} chars truncated]`;
|
|
5953
|
+
}
|
|
5954
|
+
return { result, preExecuted: true };
|
|
5955
|
+
} catch (err) {
|
|
5956
|
+
return { result: `Error: ${err instanceof Error ? err.message : String(err)}`, preExecuted: true };
|
|
5957
|
+
} finally {
|
|
5958
|
+
this.pending.delete(tc.id);
|
|
5959
|
+
}
|
|
5960
|
+
}
|
|
5961
|
+
return { result: await fallbackExecute(), preExecuted: false };
|
|
5962
|
+
}
|
|
5963
|
+
/**
|
|
5964
|
+
* Number of tools currently pre-executing.
|
|
5965
|
+
*/
|
|
5966
|
+
get activeCount() {
|
|
5967
|
+
return this.pending.size;
|
|
5968
|
+
}
|
|
5969
|
+
/**
|
|
5970
|
+
* Cancel all pending pre-executions.
|
|
5971
|
+
*/
|
|
5972
|
+
clear() {
|
|
5973
|
+
this.pending.clear();
|
|
5974
|
+
}
|
|
5975
|
+
};
|
|
5976
|
+
}
|
|
5977
|
+
});
|
|
5978
|
+
|
|
5498
5979
|
// packages/daemon/src/AgentExecutor.ts
|
|
5499
|
-
import { spawn as
|
|
5500
|
-
import { writeFileSync as writeFileSync4, readFileSync as
|
|
5501
|
-
import { resolve as
|
|
5980
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
5981
|
+
import { writeFileSync as writeFileSync4, readFileSync as readFileSync5, readdirSync as readdirSync2, mkdirSync as mkdirSync3, existsSync as existsSync7 } from "node:fs";
|
|
5982
|
+
import { resolve as resolve7, dirname as dirname2, relative } from "node:path";
|
|
5502
5983
|
import { homedir as homedir2 } from "node:os";
|
|
5503
5984
|
var SELF_MOD_PATTERN, AgentExecutor;
|
|
5504
5985
|
var init_AgentExecutor = __esm({
|
|
5505
5986
|
"packages/daemon/src/AgentExecutor.ts"() {
|
|
5506
5987
|
"use strict";
|
|
5507
5988
|
init_LLMExecutor();
|
|
5508
|
-
|
|
5989
|
+
init_tools();
|
|
5509
5990
|
init_IterationBudget();
|
|
5510
5991
|
init_PromptInjectionScanner();
|
|
5992
|
+
init_ContextCollapse();
|
|
5993
|
+
init_StreamingToolExecutor();
|
|
5511
5994
|
SELF_MOD_PATTERN = /\b(yourself|the agent|this agent|this cli|0agent|your code|your source|agent cli|improve.*agent|update.*agent|add.*to.*agent|fix.*agent|self.?improv)\b/i;
|
|
5512
5995
|
AgentExecutor = class {
|
|
5513
5996
|
constructor(llm, config, onStep, onToken) {
|
|
@@ -5519,7 +6002,7 @@ var init_AgentExecutor = __esm({
|
|
|
5519
6002
|
this.maxIterations = config.max_iterations ?? 50;
|
|
5520
6003
|
this.maxCommandMs = config.max_command_ms ?? 3e4;
|
|
5521
6004
|
this.agentRoot = config.agent_root;
|
|
5522
|
-
this.registry = new CapabilityRegistry(void 0, config.graph, config.onMemoryWrite);
|
|
6005
|
+
this.registry = new CapabilityRegistry(void 0, config.graph, config.onMemoryWrite, config.dbPath);
|
|
5523
6006
|
if (config.entityNodeId) {
|
|
5524
6007
|
this.registry.setEntityNodeId(config.entityNodeId);
|
|
5525
6008
|
}
|
|
@@ -5572,12 +6055,26 @@ var init_AgentExecutor = __esm({
|
|
|
5572
6055
|
}
|
|
5573
6056
|
this.onStep(i === 0 ? "Thinking\u2026" : "Continuing\u2026");
|
|
5574
6057
|
const estimatedTokens = this._estimateTokens(messages);
|
|
5575
|
-
if (estimatedTokens > contextLimit
|
|
5576
|
-
|
|
6058
|
+
if (estimatedTokens > contextLimit * 0.6) {
|
|
6059
|
+
const before = messages.length;
|
|
6060
|
+
const collapsed = collapseContext(messages, 12);
|
|
6061
|
+
if (collapsed !== messages) {
|
|
6062
|
+
messages.length = 0;
|
|
6063
|
+
messages.push(...collapsed);
|
|
6064
|
+
const afterTokens = this._estimateTokens(messages);
|
|
6065
|
+
if (afterTokens < estimatedTokens * 0.8) {
|
|
6066
|
+
this.onStep(`Context collapsed (${Math.round(estimatedTokens / 1e3)}k \u2192 ${Math.round(afterTokens / 1e3)}k tokens)`);
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
}
|
|
6070
|
+
const tokensAfterCollapse = this._estimateTokens(messages);
|
|
6071
|
+
if (tokensAfterCollapse > contextLimit - 16384) {
|
|
6072
|
+
this.onStep(`Compacting context (${Math.round(tokensAfterCollapse / 1e3)}k tokens)\u2026`);
|
|
5577
6073
|
this._compactHistory(messages);
|
|
5578
6074
|
}
|
|
5579
6075
|
let response;
|
|
5580
6076
|
let llmFailed = false;
|
|
6077
|
+
const streamExec = new StreamingToolExecutor(this.registry, this.cwd, signal);
|
|
5581
6078
|
{
|
|
5582
6079
|
let llmRetry = 0;
|
|
5583
6080
|
while (true) {
|
|
@@ -5591,7 +6088,9 @@ var init_AgentExecutor = __esm({
|
|
|
5591
6088
|
this.onToken(token);
|
|
5592
6089
|
finalOutput += token;
|
|
5593
6090
|
},
|
|
5594
|
-
signal
|
|
6091
|
+
signal,
|
|
6092
|
+
// Streaming tool execution: start safe tools as their blocks complete
|
|
6093
|
+
(tc) => streamExec.onToolBlock(tc)
|
|
5595
6094
|
);
|
|
5596
6095
|
break;
|
|
5597
6096
|
} catch (err) {
|
|
@@ -5627,6 +6126,12 @@ var init_AgentExecutor = __esm({
|
|
|
5627
6126
|
totalTokens += response.tokens_used;
|
|
5628
6127
|
totalCost += response.cost_usd;
|
|
5629
6128
|
modelName = response.model;
|
|
6129
|
+
const maxBudget = this.config.max_budget_usd ?? Infinity;
|
|
6130
|
+
if (totalCost >= maxBudget) {
|
|
6131
|
+
this.onStep(`Budget limit reached: $${totalCost.toFixed(4)} \u2265 $${maxBudget} \u2014 stopping session.`);
|
|
6132
|
+
finalOutput = `Session stopped: cost budget of $${maxBudget} exceeded ($${totalCost.toFixed(4)} used).`;
|
|
6133
|
+
break;
|
|
6134
|
+
}
|
|
5630
6135
|
if (response.tool_calls?.some((tc) => !toolSet.find((t) => t.name === tc.name))) {
|
|
5631
6136
|
toolSet = this.registry.getToolDefinitions();
|
|
5632
6137
|
}
|
|
@@ -5644,8 +6149,13 @@ var init_AgentExecutor = __esm({
|
|
|
5644
6149
|
const { parallel, serial } = this._partitionToolCalls(toolCalls);
|
|
5645
6150
|
if (parallel.length > 0) {
|
|
5646
6151
|
const results = await Promise.all(parallel.map(async (tc) => {
|
|
5647
|
-
|
|
5648
|
-
|
|
6152
|
+
const { result, preExecuted } = await streamExec.getOrExecute(
|
|
6153
|
+
tc,
|
|
6154
|
+
() => this._executeSingleTool(tc, signal, filesWritten, commandsRun)
|
|
6155
|
+
);
|
|
6156
|
+
const tag = preExecuted ? " [pre-exec]" : " [parallel]";
|
|
6157
|
+
this.onStep(`\u25B6 ${tc.name}(${this.summariseInput(tc.name, tc.input)})${tag}`);
|
|
6158
|
+
return { tc, result };
|
|
5649
6159
|
}));
|
|
5650
6160
|
for (const { tc, result } of results) {
|
|
5651
6161
|
this.onStep(` \u21B3 ${result.slice(0, 120)}${result.length > 120 ? "\u2026" : ""}`);
|
|
@@ -5653,8 +6163,11 @@ var init_AgentExecutor = __esm({
|
|
|
5653
6163
|
}
|
|
5654
6164
|
}
|
|
5655
6165
|
for (const tc of serial) {
|
|
5656
|
-
|
|
5657
|
-
|
|
6166
|
+
const { result, preExecuted } = await streamExec.getOrExecute(
|
|
6167
|
+
tc,
|
|
6168
|
+
() => this._executeSingleTool(tc, signal, filesWritten, commandsRun)
|
|
6169
|
+
);
|
|
6170
|
+
this.onStep(`\u25B6 ${tc.name}(${this.summariseInput(tc.name, tc.input)})${preExecuted ? " [pre-exec]" : ""}`);
|
|
5658
6171
|
this.onStep(` \u21B3 ${result.slice(0, 120)}${result.length > 120 ? "\u2026" : ""}`);
|
|
5659
6172
|
messages.push({ role: "tool", content: result, tool_call_id: tc.id });
|
|
5660
6173
|
}
|
|
@@ -5700,9 +6213,9 @@ var init_AgentExecutor = __esm({
|
|
|
5700
6213
|
}
|
|
5701
6214
|
}
|
|
5702
6215
|
shellExec(command, timeoutMs) {
|
|
5703
|
-
return new Promise((
|
|
6216
|
+
return new Promise((resolve19) => {
|
|
5704
6217
|
const chunks = [];
|
|
5705
|
-
const proc =
|
|
6218
|
+
const proc = spawn6("bash", ["-c", command], {
|
|
5706
6219
|
cwd: this.cwd,
|
|
5707
6220
|
env: { ...process.env, TERM: "dumb" },
|
|
5708
6221
|
timeout: timeoutMs
|
|
@@ -5711,10 +6224,10 @@ var init_AgentExecutor = __esm({
|
|
|
5711
6224
|
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
5712
6225
|
proc.on("close", (code) => {
|
|
5713
6226
|
const output = chunks.join("").trim();
|
|
5714
|
-
|
|
6227
|
+
resolve19(output || (code === 0 ? "(command completed, no output)" : `exit code ${code}`));
|
|
5715
6228
|
});
|
|
5716
6229
|
proc.on("error", (err) => {
|
|
5717
|
-
|
|
6230
|
+
resolve19(`Error: ${err.message}`);
|
|
5718
6231
|
});
|
|
5719
6232
|
});
|
|
5720
6233
|
}
|
|
@@ -5729,8 +6242,8 @@ var init_AgentExecutor = __esm({
|
|
|
5729
6242
|
readFile(filePath) {
|
|
5730
6243
|
const safe = this.safePath(filePath);
|
|
5731
6244
|
if (!safe) return "Error: path outside working directory";
|
|
5732
|
-
if (!
|
|
5733
|
-
const content =
|
|
6245
|
+
if (!existsSync7(safe)) return `File not found: ${filePath}`;
|
|
6246
|
+
const content = readFileSync5(safe, "utf8");
|
|
5734
6247
|
return content.length > 8e3 ? content.slice(0, 8e3) + `
|
|
5735
6248
|
\u2026[truncated, ${content.length} total bytes]` : content;
|
|
5736
6249
|
}
|
|
@@ -5821,7 +6334,7 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5821
6334
|
listDir(dirPath) {
|
|
5822
6335
|
const safe = this.safePath(dirPath ?? ".");
|
|
5823
6336
|
if (!safe) return "Error: path outside working directory";
|
|
5824
|
-
if (!
|
|
6337
|
+
if (!existsSync7(safe)) return `Directory not found: ${dirPath}`;
|
|
5825
6338
|
try {
|
|
5826
6339
|
const entries = readdirSync2(safe, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && e.name !== "node_modules").map((e) => `${e.isDirectory() ? "d" : "f"} ${e.name}`).join("\n");
|
|
5827
6340
|
return entries || "(empty directory)";
|
|
@@ -5831,7 +6344,7 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5831
6344
|
}
|
|
5832
6345
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
5833
6346
|
safePath(p) {
|
|
5834
|
-
const resolved =
|
|
6347
|
+
const resolved = resolve7(this.cwd, p);
|
|
5835
6348
|
return resolved.startsWith(this.cwd) ? resolved : null;
|
|
5836
6349
|
}
|
|
5837
6350
|
buildSystemPrompt(extra, task) {
|
|
@@ -5962,15 +6475,15 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5962
6475
|
);
|
|
5963
6476
|
}
|
|
5964
6477
|
const agentsFiles = [
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
6478
|
+
resolve7(this.cwd, "AGENTS.md"),
|
|
6479
|
+
resolve7(this.cwd, ".0agent", "AGENTS.md"),
|
|
6480
|
+
resolve7(this.cwd, "CLAUDE.md"),
|
|
6481
|
+
resolve7(homedir2(), ".0agent", "AGENTS.md")
|
|
5969
6482
|
];
|
|
5970
6483
|
for (const f of agentsFiles) {
|
|
5971
6484
|
try {
|
|
5972
|
-
if (
|
|
5973
|
-
const content =
|
|
6485
|
+
if (existsSync7(f)) {
|
|
6486
|
+
const content = readFileSync5(f, "utf8").trim();
|
|
5974
6487
|
if (content && content.length < 4e3) {
|
|
5975
6488
|
const sanitized = sanitizeContextFile(content, f);
|
|
5976
6489
|
lines.push(``, `Project instructions:`, sanitized);
|
|
@@ -6152,8 +6665,8 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
6152
6665
|
});
|
|
6153
6666
|
|
|
6154
6667
|
// packages/daemon/src/ExecutionVerifier.ts
|
|
6155
|
-
import { existsSync as
|
|
6156
|
-
import { resolve as
|
|
6668
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
6669
|
+
import { resolve as resolve8 } from "node:path";
|
|
6157
6670
|
var ExecutionVerifier;
|
|
6158
6671
|
var init_ExecutionVerifier = __esm({
|
|
6159
6672
|
"packages/daemon/src/ExecutionVerifier.ts"() {
|
|
@@ -6190,8 +6703,8 @@ var init_ExecutionVerifier = __esm({
|
|
|
6190
6703
|
};
|
|
6191
6704
|
}
|
|
6192
6705
|
if (files.length > 0) {
|
|
6193
|
-
const lastFile =
|
|
6194
|
-
const exists =
|
|
6706
|
+
const lastFile = resolve8(this.cwd, files[files.length - 1]);
|
|
6707
|
+
const exists = existsSync9(lastFile);
|
|
6195
6708
|
return {
|
|
6196
6709
|
success: exists,
|
|
6197
6710
|
method: "file_exists",
|
|
@@ -6230,10 +6743,10 @@ var init_ExecutionVerifier = __esm({
|
|
|
6230
6743
|
});
|
|
6231
6744
|
|
|
6232
6745
|
// packages/daemon/src/RuntimeSelfHeal.ts
|
|
6233
|
-
import { readFileSync as
|
|
6234
|
-
import { resolve as
|
|
6746
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "node:fs";
|
|
6747
|
+
import { resolve as resolve9, dirname as dirname3 } from "node:path";
|
|
6235
6748
|
import { fileURLToPath } from "node:url";
|
|
6236
|
-
import { execSync as
|
|
6749
|
+
import { execSync as execSync7, spawn as spawn7 } from "node:child_process";
|
|
6237
6750
|
function isRuntimeBug(error) {
|
|
6238
6751
|
if (TASK_FAILURE_PATTERNS.some((p) => p.test(error))) return false;
|
|
6239
6752
|
return RUNTIME_BUG_PATTERNS.some((p) => p.test(error));
|
|
@@ -6257,8 +6770,8 @@ function parseStackTrace(stack) {
|
|
|
6257
6770
|
}
|
|
6258
6771
|
function extractContext(filePath, errorLine, contextLines = 30) {
|
|
6259
6772
|
try {
|
|
6260
|
-
if (!
|
|
6261
|
-
const content =
|
|
6773
|
+
if (!existsSync10(filePath)) return null;
|
|
6774
|
+
const content = readFileSync7(filePath, "utf8");
|
|
6262
6775
|
const lines = content.split("\n");
|
|
6263
6776
|
const start = Math.max(0, errorLine - contextLines);
|
|
6264
6777
|
const end = Math.min(lines.length, errorLine + contextLines);
|
|
@@ -6303,8 +6816,8 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6303
6816
|
this.llm = llm;
|
|
6304
6817
|
this.eventBus = eventBus;
|
|
6305
6818
|
let dir = dirname3(fileURLToPath(import.meta.url));
|
|
6306
|
-
while (dir !== "/" && !
|
|
6307
|
-
dir =
|
|
6819
|
+
while (dir !== "/" && !existsSync10(resolve9(dir, "package.json"))) {
|
|
6820
|
+
dir = resolve9(dir, "..");
|
|
6308
6821
|
}
|
|
6309
6822
|
this.projectRoot = dir;
|
|
6310
6823
|
}
|
|
@@ -6340,7 +6853,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6340
6853
|
*/
|
|
6341
6854
|
async applyPatch(proposal) {
|
|
6342
6855
|
const tsPath = this.findSourceFile(proposal.location);
|
|
6343
|
-
if (!tsPath || !
|
|
6856
|
+
if (!tsPath || !existsSync10(tsPath)) {
|
|
6344
6857
|
return {
|
|
6345
6858
|
applied: false,
|
|
6346
6859
|
restarted: false,
|
|
@@ -6348,7 +6861,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6348
6861
|
};
|
|
6349
6862
|
}
|
|
6350
6863
|
try {
|
|
6351
|
-
const original =
|
|
6864
|
+
const original = readFileSync7(tsPath, "utf8");
|
|
6352
6865
|
const backup = tsPath + ".bak";
|
|
6353
6866
|
writeFileSync5(backup, original, "utf8");
|
|
6354
6867
|
if (!original.includes(proposal.original_code.trim())) {
|
|
@@ -6360,10 +6873,10 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6360
6873
|
}
|
|
6361
6874
|
const patched = original.replace(proposal.original_code, proposal.proposed_code);
|
|
6362
6875
|
writeFileSync5(tsPath, patched, "utf8");
|
|
6363
|
-
const bundleScript =
|
|
6364
|
-
if (
|
|
6876
|
+
const bundleScript = resolve9(this.projectRoot, "scripts", "bundle.mjs");
|
|
6877
|
+
if (existsSync10(bundleScript)) {
|
|
6365
6878
|
try {
|
|
6366
|
-
|
|
6879
|
+
execSync7(`node "${bundleScript}"`, {
|
|
6367
6880
|
cwd: this.projectRoot,
|
|
6368
6881
|
timeout: 6e4,
|
|
6369
6882
|
stdio: "ignore"
|
|
@@ -6394,14 +6907,14 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6394
6907
|
// ─── Private helpers ───────────────────────────────────────────────────────
|
|
6395
6908
|
findSourceFile(location) {
|
|
6396
6909
|
const candidates = [
|
|
6397
|
-
|
|
6910
|
+
resolve9(this.projectRoot, location.relPath),
|
|
6398
6911
|
// If relPath starts with dist/, look in src/
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6912
|
+
resolve9(this.projectRoot, location.relPath.replace(/^dist\//, "src/").replace(/\.js$/, ".ts")),
|
|
6913
|
+
resolve9(this.projectRoot, "packages", "daemon", "src", location.relPath.replace(/.*src\//, "")),
|
|
6914
|
+
resolve9(this.projectRoot, "packages", "core", "src", location.relPath.replace(/.*src\//, ""))
|
|
6402
6915
|
];
|
|
6403
6916
|
for (const p of candidates) {
|
|
6404
|
-
if (
|
|
6917
|
+
if (existsSync10(p)) return p;
|
|
6405
6918
|
}
|
|
6406
6919
|
return null;
|
|
6407
6920
|
}
|
|
@@ -6466,9 +6979,9 @@ Rules:
|
|
|
6466
6979
|
}
|
|
6467
6980
|
}
|
|
6468
6981
|
restartDaemon() {
|
|
6469
|
-
const bundlePath =
|
|
6470
|
-
if (
|
|
6471
|
-
const child =
|
|
6982
|
+
const bundlePath = resolve9(this.projectRoot, "dist", "daemon.mjs");
|
|
6983
|
+
if (existsSync10(bundlePath)) {
|
|
6984
|
+
const child = spawn7(process.execPath, [bundlePath], {
|
|
6472
6985
|
detached: true,
|
|
6473
6986
|
stdio: "ignore",
|
|
6474
6987
|
env: process.env
|
|
@@ -6566,14 +7079,14 @@ var init_SelfHealLoop = __esm({
|
|
|
6566
7079
|
}
|
|
6567
7080
|
});
|
|
6568
7081
|
|
|
6569
|
-
// packages/daemon/src/ProactiveSurface.ts
|
|
7082
|
+
// packages/daemon/src/tasks/ProactiveSurface.ts
|
|
6570
7083
|
var ProactiveSurface_exports = {};
|
|
6571
7084
|
__export(ProactiveSurface_exports, {
|
|
6572
7085
|
ProactiveSurface: () => ProactiveSurface
|
|
6573
7086
|
});
|
|
6574
|
-
import { execSync as
|
|
6575
|
-
import { existsSync as
|
|
6576
|
-
import { resolve as
|
|
7087
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
7088
|
+
import { existsSync as existsSync20, readFileSync as readFileSync16, statSync as statSync2, readdirSync as readdirSync5 } from "node:fs";
|
|
7089
|
+
import { resolve as resolve16, join as join7 } from "node:path";
|
|
6577
7090
|
function readdirSafe(dir) {
|
|
6578
7091
|
try {
|
|
6579
7092
|
return readdirSync5(dir);
|
|
@@ -6583,7 +7096,7 @@ function readdirSafe(dir) {
|
|
|
6583
7096
|
}
|
|
6584
7097
|
var ProactiveSurface;
|
|
6585
7098
|
var init_ProactiveSurface = __esm({
|
|
6586
|
-
"packages/daemon/src/ProactiveSurface.ts"() {
|
|
7099
|
+
"packages/daemon/src/tasks/ProactiveSurface.ts"() {
|
|
6587
7100
|
"use strict";
|
|
6588
7101
|
init_src();
|
|
6589
7102
|
ProactiveSurface = class {
|
|
@@ -6622,7 +7135,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6622
7135
|
return [...this.insights];
|
|
6623
7136
|
}
|
|
6624
7137
|
async poll() {
|
|
6625
|
-
if (!
|
|
7138
|
+
if (!existsSync20(resolve16(this.cwd, ".git"))) return;
|
|
6626
7139
|
const newInsights = [];
|
|
6627
7140
|
const gitInsight = this.checkGitActivity();
|
|
6628
7141
|
if (gitInsight) newInsights.push(gitInsight);
|
|
@@ -6640,7 +7153,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6640
7153
|
try {
|
|
6641
7154
|
const currentHead = this.getGitHead();
|
|
6642
7155
|
if (!currentHead || currentHead === this.lastKnownHead) return null;
|
|
6643
|
-
const log =
|
|
7156
|
+
const log = execSync10(
|
|
6644
7157
|
`git log ${this.lastKnownHead}..${currentHead} --oneline --stat`,
|
|
6645
7158
|
{ cwd: this.cwd, timeout: 3e3, encoding: "utf8" }
|
|
6646
7159
|
).trim();
|
|
@@ -6666,13 +7179,13 @@ var init_ProactiveSurface = __esm({
|
|
|
6666
7179
|
];
|
|
6667
7180
|
for (const dir of outputPaths) {
|
|
6668
7181
|
try {
|
|
6669
|
-
if (!
|
|
7182
|
+
if (!existsSync20(dir)) continue;
|
|
6670
7183
|
const xmlFiles = readdirSafe(dir).filter((f) => f.endsWith(".xml"));
|
|
6671
7184
|
for (const xml of xmlFiles) {
|
|
6672
7185
|
const path = join7(dir, xml);
|
|
6673
7186
|
const stat = statSync2(path);
|
|
6674
7187
|
if (stat.mtimeMs < this.lastPollAt) continue;
|
|
6675
|
-
const content =
|
|
7188
|
+
const content = readFileSync16(path, "utf8");
|
|
6676
7189
|
const failures = [...content.matchAll(/<failure[^>]*message="([^"]+)"/g)].length;
|
|
6677
7190
|
if (failures > 0) {
|
|
6678
7191
|
return this.makeInsight(
|
|
@@ -6716,7 +7229,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6716
7229
|
}
|
|
6717
7230
|
getGitHead() {
|
|
6718
7231
|
try {
|
|
6719
|
-
return
|
|
7232
|
+
return execSync10("git rev-parse HEAD", { cwd: this.cwd, timeout: 1e3, encoding: "utf8" }).trim();
|
|
6720
7233
|
} catch {
|
|
6721
7234
|
return "";
|
|
6722
7235
|
}
|
|
@@ -6727,8 +7240,8 @@ var init_ProactiveSurface = __esm({
|
|
|
6727
7240
|
|
|
6728
7241
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
6729
7242
|
init_src();
|
|
6730
|
-
import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, existsSync as
|
|
6731
|
-
import { resolve as
|
|
7243
|
+
import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync17 } from "node:fs";
|
|
7244
|
+
import { resolve as resolve17 } from "node:path";
|
|
6732
7245
|
import { homedir as homedir9 } from "node:os";
|
|
6733
7246
|
|
|
6734
7247
|
// packages/daemon/src/config/DaemonConfig.ts
|
|
@@ -6926,7 +7439,7 @@ ${issues}`);
|
|
|
6926
7439
|
// packages/daemon/src/SessionManager.ts
|
|
6927
7440
|
init_src();
|
|
6928
7441
|
|
|
6929
|
-
// packages/daemon/src/EntityScopedContext.ts
|
|
7442
|
+
// packages/daemon/src/utils/EntityScopedContext.ts
|
|
6930
7443
|
init_src();
|
|
6931
7444
|
var EntityScopedContextLoader = class {
|
|
6932
7445
|
constructor(graph) {
|
|
@@ -7003,7 +7516,7 @@ var EntityScopedContextLoader = class {
|
|
|
7003
7516
|
init_LLMExecutor();
|
|
7004
7517
|
init_AgentExecutor();
|
|
7005
7518
|
|
|
7006
|
-
// packages/daemon/src/AnthropicSkillFetcher.ts
|
|
7519
|
+
// packages/daemon/src/services/AnthropicSkillFetcher.ts
|
|
7007
7520
|
var BASE_URL = "https://raw.githubusercontent.com/anthropics/skills/main";
|
|
7008
7521
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
7009
7522
|
var ANTHROPIC_SKILLS = [
|
|
@@ -7122,9 +7635,9 @@ var AnthropicSkillFetcher = class {
|
|
|
7122
7635
|
}
|
|
7123
7636
|
};
|
|
7124
7637
|
|
|
7125
|
-
// packages/daemon/src/ProjectScanner.ts
|
|
7126
|
-
import { execSync as
|
|
7127
|
-
import { readFileSync as
|
|
7638
|
+
// packages/daemon/src/utils/ProjectScanner.ts
|
|
7639
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
7640
|
+
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "node:fs";
|
|
7128
7641
|
import { join as join2 } from "node:path";
|
|
7129
7642
|
import { createServer } from "node:net";
|
|
7130
7643
|
var PORTS_TO_CHECK = [3e3, 3001, 4e3, 4200, 5e3, 5173, 8e3, 8080, 8888];
|
|
@@ -7173,13 +7686,13 @@ var ProjectScanner = class {
|
|
|
7173
7686
|
const stack = [];
|
|
7174
7687
|
let name = "";
|
|
7175
7688
|
const pkgPath = join2(this.cwd, "package.json");
|
|
7176
|
-
if (
|
|
7689
|
+
if (existsSync8(pkgPath)) {
|
|
7177
7690
|
try {
|
|
7178
|
-
const pkg = JSON.parse(
|
|
7691
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
7179
7692
|
name = pkg.name ?? "";
|
|
7180
7693
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
7181
7694
|
stack.push("node");
|
|
7182
|
-
if (deps.typescript ||
|
|
7695
|
+
if (deps.typescript || existsSync8(join2(this.cwd, "tsconfig.json"))) stack.push("typescript");
|
|
7183
7696
|
if (deps.react) stack.push("react");
|
|
7184
7697
|
if (deps.vue) stack.push("vue");
|
|
7185
7698
|
if (deps.svelte) stack.push("svelte");
|
|
@@ -7188,24 +7701,24 @@ var ProjectScanner = class {
|
|
|
7188
7701
|
} catch {
|
|
7189
7702
|
}
|
|
7190
7703
|
}
|
|
7191
|
-
if (
|
|
7704
|
+
if (existsSync8(join2(this.cwd, "Cargo.toml"))) {
|
|
7192
7705
|
stack.push("rust");
|
|
7193
7706
|
try {
|
|
7194
|
-
const cargo =
|
|
7707
|
+
const cargo = readFileSync6(join2(this.cwd, "Cargo.toml"), "utf8");
|
|
7195
7708
|
const nameMatch = cargo.match(/^name\s*=\s*"([^"]+)"/m);
|
|
7196
7709
|
if (nameMatch && !name) name = nameMatch[1];
|
|
7197
7710
|
} catch {
|
|
7198
7711
|
}
|
|
7199
7712
|
}
|
|
7200
|
-
if (
|
|
7713
|
+
if (existsSync8(join2(this.cwd, "pyproject.toml")) || existsSync8(join2(this.cwd, "requirements.txt"))) {
|
|
7201
7714
|
stack.push("python");
|
|
7202
7715
|
}
|
|
7203
|
-
if (
|
|
7716
|
+
if (existsSync8(join2(this.cwd, "go.mod"))) stack.push("go");
|
|
7204
7717
|
return [stack, name];
|
|
7205
7718
|
}
|
|
7206
7719
|
getRecentCommits() {
|
|
7207
7720
|
try {
|
|
7208
|
-
const out =
|
|
7721
|
+
const out = execSync6("git log --oneline -5 2>/dev/null", {
|
|
7209
7722
|
cwd: this.cwd,
|
|
7210
7723
|
timeout: 3e3,
|
|
7211
7724
|
encoding: "utf8"
|
|
@@ -7217,7 +7730,7 @@ var ProjectScanner = class {
|
|
|
7217
7730
|
}
|
|
7218
7731
|
getDirtyFiles() {
|
|
7219
7732
|
try {
|
|
7220
|
-
const out =
|
|
7733
|
+
const out = execSync6("git status --short 2>/dev/null", {
|
|
7221
7734
|
cwd: this.cwd,
|
|
7222
7735
|
timeout: 3e3,
|
|
7223
7736
|
encoding: "utf8"
|
|
@@ -7230,19 +7743,19 @@ var ProjectScanner = class {
|
|
|
7230
7743
|
async getRunningPorts() {
|
|
7231
7744
|
const open = [];
|
|
7232
7745
|
await Promise.all(PORTS_TO_CHECK.map(
|
|
7233
|
-
(port) => new Promise((
|
|
7746
|
+
(port) => new Promise((resolve19) => {
|
|
7234
7747
|
const s = createServer();
|
|
7235
7748
|
s.listen(port, "127.0.0.1", () => {
|
|
7236
7749
|
s.close();
|
|
7237
|
-
|
|
7750
|
+
resolve19();
|
|
7238
7751
|
});
|
|
7239
7752
|
s.on("error", () => {
|
|
7240
7753
|
open.push(port);
|
|
7241
|
-
|
|
7754
|
+
resolve19();
|
|
7242
7755
|
});
|
|
7243
7756
|
setTimeout(() => {
|
|
7244
7757
|
s.close();
|
|
7245
|
-
|
|
7758
|
+
resolve19();
|
|
7246
7759
|
}, 200);
|
|
7247
7760
|
})
|
|
7248
7761
|
));
|
|
@@ -7251,9 +7764,9 @@ var ProjectScanner = class {
|
|
|
7251
7764
|
getReadmeSummary() {
|
|
7252
7765
|
for (const name of ["README.md", "readme.md", "README.txt", "README"]) {
|
|
7253
7766
|
const p = join2(this.cwd, name);
|
|
7254
|
-
if (
|
|
7767
|
+
if (existsSync8(p)) {
|
|
7255
7768
|
try {
|
|
7256
|
-
return
|
|
7769
|
+
return readFileSync6(p, "utf8").slice(0, 300).replace(/\n+/g, " ").trim();
|
|
7257
7770
|
} catch {
|
|
7258
7771
|
}
|
|
7259
7772
|
}
|
|
@@ -7262,7 +7775,7 @@ var ProjectScanner = class {
|
|
|
7262
7775
|
}
|
|
7263
7776
|
};
|
|
7264
7777
|
|
|
7265
|
-
// packages/daemon/src/ConversationStore.ts
|
|
7778
|
+
// packages/daemon/src/services/ConversationStore.ts
|
|
7266
7779
|
var CREATE_TABLE = `
|
|
7267
7780
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
7268
7781
|
id TEXT PRIMARY KEY,
|
|
@@ -7317,7 +7830,7 @@ var ConversationStore = class {
|
|
|
7317
7830
|
}
|
|
7318
7831
|
};
|
|
7319
7832
|
|
|
7320
|
-
// packages/daemon/src/SmartModelRouter.ts
|
|
7833
|
+
// packages/daemon/src/services/SmartModelRouter.ts
|
|
7321
7834
|
var COMPLEX_PATTERNS = [
|
|
7322
7835
|
// Code-related
|
|
7323
7836
|
/\b(implement|build|write|fix|refactor|debug|test|deploy|compile|lint|bundle|migrate)\b/i,
|
|
@@ -7387,9 +7900,130 @@ function getFastModelId(provider, _currentModel) {
|
|
|
7387
7900
|
}
|
|
7388
7901
|
}
|
|
7389
7902
|
|
|
7903
|
+
// packages/daemon/src/services/AutoMemoryExtractor.ts
|
|
7904
|
+
init_src();
|
|
7905
|
+
var state = {
|
|
7906
|
+
lastMessageIndex: 0,
|
|
7907
|
+
inProgress: false,
|
|
7908
|
+
pendingRun: false,
|
|
7909
|
+
turnsSinceExtraction: 0
|
|
7910
|
+
};
|
|
7911
|
+
var MIN_TURNS_BETWEEN = 3;
|
|
7912
|
+
var MAX_MESSAGES_PER_RUN = 20;
|
|
7913
|
+
var AutoMemoryExtractor = class {
|
|
7914
|
+
constructor(llm, graph, entityNodeId) {
|
|
7915
|
+
this.llm = llm;
|
|
7916
|
+
this.graph = graph;
|
|
7917
|
+
this.entityNodeId = entityNodeId;
|
|
7918
|
+
}
|
|
7919
|
+
/**
|
|
7920
|
+
* Called after each session turn. Decides whether to extract memories
|
|
7921
|
+
* and runs extraction in the background if needed.
|
|
7922
|
+
*
|
|
7923
|
+
* Fire-and-forget — never blocks the main session.
|
|
7924
|
+
*/
|
|
7925
|
+
async maybeExtract(messages, memoryWritesSinceLast) {
|
|
7926
|
+
state.turnsSinceExtraction++;
|
|
7927
|
+
if (memoryWritesSinceLast) {
|
|
7928
|
+
state.turnsSinceExtraction = 0;
|
|
7929
|
+
return;
|
|
7930
|
+
}
|
|
7931
|
+
if (state.turnsSinceExtraction < MIN_TURNS_BETWEEN) return;
|
|
7932
|
+
if (messages.length <= state.lastMessageIndex) return;
|
|
7933
|
+
if (state.inProgress) {
|
|
7934
|
+
state.pendingRun = true;
|
|
7935
|
+
return;
|
|
7936
|
+
}
|
|
7937
|
+
await this._runExtraction(messages);
|
|
7938
|
+
if (state.pendingRun) {
|
|
7939
|
+
state.pendingRun = false;
|
|
7940
|
+
await this._runExtraction(messages);
|
|
7941
|
+
}
|
|
7942
|
+
}
|
|
7943
|
+
async _runExtraction(messages) {
|
|
7944
|
+
if (!this.llm?.isConfigured) return;
|
|
7945
|
+
state.inProgress = true;
|
|
7946
|
+
try {
|
|
7947
|
+
const newMessages = messages.slice(
|
|
7948
|
+
state.lastMessageIndex,
|
|
7949
|
+
state.lastMessageIndex + MAX_MESSAGES_PER_RUN
|
|
7950
|
+
);
|
|
7951
|
+
if (newMessages.length === 0) return;
|
|
7952
|
+
const conversationText = newMessages.filter((m) => m.role === "user" || m.role === "assistant" && !m.tool_calls).map((m) => `${m.role}: ${m.content.slice(0, 500)}`).join("\n");
|
|
7953
|
+
if (conversationText.length < 50) return;
|
|
7954
|
+
const prompt = [
|
|
7955
|
+
"Extract any durable facts from this conversation that are worth remembering across sessions.",
|
|
7956
|
+
"Focus on: user preferences, project decisions, tool configurations, recurring patterns, names, roles.",
|
|
7957
|
+
"Do NOT extract: greetings, transient task details, things already obvious from the code.",
|
|
7958
|
+
"",
|
|
7959
|
+
'Return a JSON array of facts. Each fact: {"label":"snake_case_key","content":"value","type":"identity|tech|preference|project|outcome"}',
|
|
7960
|
+
"Return [] if nothing worth extracting.",
|
|
7961
|
+
"",
|
|
7962
|
+
"Conversation:",
|
|
7963
|
+
conversationText
|
|
7964
|
+
].join("\n");
|
|
7965
|
+
const resp = await this.llm.complete(
|
|
7966
|
+
[{ role: "user", content: prompt }],
|
|
7967
|
+
"You extract durable facts from conversations. Return ONLY a JSON array. No explanation."
|
|
7968
|
+
);
|
|
7969
|
+
const text = resp.content.trim();
|
|
7970
|
+
const jsonMatch = text.match(/\[[\s\S]*\]/);
|
|
7971
|
+
if (!jsonMatch) return;
|
|
7972
|
+
let facts;
|
|
7973
|
+
try {
|
|
7974
|
+
facts = JSON.parse(jsonMatch[0]);
|
|
7975
|
+
} catch {
|
|
7976
|
+
return;
|
|
7977
|
+
}
|
|
7978
|
+
if (!Array.isArray(facts) || facts.length === 0) return;
|
|
7979
|
+
for (const fact of facts.slice(0, 5)) {
|
|
7980
|
+
if (!fact.label || !fact.content) continue;
|
|
7981
|
+
const nodeId = `memory:${fact.label}`;
|
|
7982
|
+
const existing = this.graph.getNode(nodeId);
|
|
7983
|
+
if (existing) {
|
|
7984
|
+
this.graph.updateNode(nodeId, {
|
|
7985
|
+
metadata: {
|
|
7986
|
+
...existing.metadata,
|
|
7987
|
+
content: fact.content,
|
|
7988
|
+
type: fact.type || "note",
|
|
7989
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7990
|
+
}
|
|
7991
|
+
});
|
|
7992
|
+
} else {
|
|
7993
|
+
const node = createNode({
|
|
7994
|
+
id: nodeId,
|
|
7995
|
+
graph_id: "root",
|
|
7996
|
+
label: fact.label,
|
|
7997
|
+
type: "context" /* CONTEXT */,
|
|
7998
|
+
metadata: {
|
|
7999
|
+
content: fact.content,
|
|
8000
|
+
type: fact.type || "note",
|
|
8001
|
+
saved_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8002
|
+
source: "auto_extract"
|
|
8003
|
+
}
|
|
8004
|
+
});
|
|
8005
|
+
this.graph.addNode(node);
|
|
8006
|
+
}
|
|
8007
|
+
}
|
|
8008
|
+
state.lastMessageIndex = messages.length;
|
|
8009
|
+
state.turnsSinceExtraction = 0;
|
|
8010
|
+
} catch {
|
|
8011
|
+
} finally {
|
|
8012
|
+
state.inProgress = false;
|
|
8013
|
+
}
|
|
8014
|
+
}
|
|
8015
|
+
/** Reset state (e.g., on new session). */
|
|
8016
|
+
reset() {
|
|
8017
|
+
state.lastMessageIndex = 0;
|
|
8018
|
+
state.inProgress = false;
|
|
8019
|
+
state.pendingRun = false;
|
|
8020
|
+
state.turnsSinceExtraction = 0;
|
|
8021
|
+
}
|
|
8022
|
+
};
|
|
8023
|
+
|
|
7390
8024
|
// packages/daemon/src/SessionManager.ts
|
|
7391
|
-
import { readFileSync as
|
|
7392
|
-
import { resolve as
|
|
8025
|
+
import { readFileSync as readFileSync8, existsSync as existsSync11 } from "node:fs";
|
|
8026
|
+
import { resolve as resolve10 } from "node:path";
|
|
7393
8027
|
import { homedir as homedir3 } from "node:os";
|
|
7394
8028
|
import YAML2 from "yaml";
|
|
7395
8029
|
var SessionManager = class {
|
|
@@ -7782,6 +8416,15 @@ Current task:`;
|
|
|
7782
8416
|
this._extractAndPersistFacts(enrichedReq.task, agentResult.output, activeLLM, userEntityId).catch((err) => {
|
|
7783
8417
|
console.warn("[0agent] Memory extraction outer error:", err instanceof Error ? err.message : err);
|
|
7784
8418
|
});
|
|
8419
|
+
if (this.graph && activeLLM) {
|
|
8420
|
+
const extractor = new AutoMemoryExtractor(activeLLM, this.graph, userEntityId);
|
|
8421
|
+
extractor.maybeExtract(
|
|
8422
|
+
[{ role: "user", content: enrichedReq.task }, { role: "assistant", content: agentResult.output }],
|
|
8423
|
+
false
|
|
8424
|
+
// memoryWritesSinceLast — checked inside extractor
|
|
8425
|
+
).catch(() => {
|
|
8426
|
+
});
|
|
8427
|
+
}
|
|
7785
8428
|
this.completeSession(sessionId, {
|
|
7786
8429
|
output: agentResult.output,
|
|
7787
8430
|
files_written: agentResult.files_written,
|
|
@@ -7790,7 +8433,7 @@ Current task:`;
|
|
|
7790
8433
|
model: agentResult.model
|
|
7791
8434
|
});
|
|
7792
8435
|
} else {
|
|
7793
|
-
const cfgPath =
|
|
8436
|
+
const cfgPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
7794
8437
|
const output = `No LLM API key found. Add one to ${cfgPath} or run: 0agent init`;
|
|
7795
8438
|
this.addStep(sessionId, "\u26A0 No LLM API key configured \u2014 run: 0agent init");
|
|
7796
8439
|
this.completeSession(sessionId, { output });
|
|
@@ -7833,9 +8476,9 @@ Current task:`;
|
|
|
7833
8476
|
*/
|
|
7834
8477
|
getFreshLLM() {
|
|
7835
8478
|
try {
|
|
7836
|
-
const configPath =
|
|
7837
|
-
if (!
|
|
7838
|
-
const raw =
|
|
8479
|
+
const configPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
8480
|
+
if (!existsSync11(configPath)) return this.llm;
|
|
8481
|
+
const raw = readFileSync8(configPath, "utf8");
|
|
7839
8482
|
const cfg = YAML2.parse(raw);
|
|
7840
8483
|
const providers = cfg.llm_providers;
|
|
7841
8484
|
if (!providers?.length) return this.llm;
|
|
@@ -7861,9 +8504,9 @@ Current task:`;
|
|
|
7861
8504
|
if (!this.graph) return;
|
|
7862
8505
|
let extractLLM;
|
|
7863
8506
|
try {
|
|
7864
|
-
const cfgPath =
|
|
7865
|
-
if (
|
|
7866
|
-
const raw =
|
|
8507
|
+
const cfgPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
8508
|
+
if (existsSync11(cfgPath)) {
|
|
8509
|
+
const raw = readFileSync8(cfgPath, "utf8");
|
|
7867
8510
|
const cfg = YAML2.parse(raw);
|
|
7868
8511
|
const prov = cfg.llm_providers?.find((p) => p.is_default) ?? cfg.llm_providers?.[0];
|
|
7869
8512
|
if (prov?.api_key && prov.provider === "anthropic") {
|
|
@@ -8101,7 +8744,7 @@ var WebSocketEventBus = class {
|
|
|
8101
8744
|
}
|
|
8102
8745
|
};
|
|
8103
8746
|
|
|
8104
|
-
// packages/daemon/src/BackgroundWorkers.ts
|
|
8747
|
+
// packages/daemon/src/tasks/BackgroundWorkers.ts
|
|
8105
8748
|
var DEFAULT_CONFIG2 = {
|
|
8106
8749
|
decay_interval_ms: 6 * 60 * 60 * 1e3,
|
|
8107
8750
|
// 6 hours
|
|
@@ -8225,8 +8868,8 @@ var BackgroundWorkers = class {
|
|
|
8225
8868
|
}
|
|
8226
8869
|
};
|
|
8227
8870
|
|
|
8228
|
-
// packages/daemon/src/SkillRegistry.ts
|
|
8229
|
-
import { readFileSync as
|
|
8871
|
+
// packages/daemon/src/skills/SkillRegistry.ts
|
|
8872
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync3, existsSync as existsSync12, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, mkdirSync as mkdirSync4 } from "node:fs";
|
|
8230
8873
|
import { join as join3 } from "node:path";
|
|
8231
8874
|
import { homedir as homedir4 } from "node:os";
|
|
8232
8875
|
import YAML3 from "yaml";
|
|
@@ -8249,11 +8892,11 @@ var SkillRegistry = class {
|
|
|
8249
8892
|
this.loadFromDir(this.customDir, false);
|
|
8250
8893
|
}
|
|
8251
8894
|
loadFromDir(dir, isBuiltin) {
|
|
8252
|
-
if (!
|
|
8895
|
+
if (!existsSync12(dir)) return;
|
|
8253
8896
|
const files = readdirSync3(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
8254
8897
|
for (const file of files) {
|
|
8255
8898
|
try {
|
|
8256
|
-
const raw =
|
|
8899
|
+
const raw = readFileSync9(join3(dir, file), "utf8");
|
|
8257
8900
|
const skill = YAML3.parse(raw);
|
|
8258
8901
|
if (skill.name) {
|
|
8259
8902
|
this.skills.set(skill.name, skill);
|
|
@@ -8303,7 +8946,7 @@ var SkillRegistry = class {
|
|
|
8303
8946
|
throw new Error(`Cannot delete built-in skill: ${name}`);
|
|
8304
8947
|
}
|
|
8305
8948
|
const filePath = join3(this.customDir, `${name}.yaml`);
|
|
8306
|
-
if (
|
|
8949
|
+
if (existsSync12(filePath)) {
|
|
8307
8950
|
unlinkSync3(filePath);
|
|
8308
8951
|
}
|
|
8309
8952
|
this.skills.delete(name);
|
|
@@ -8316,8 +8959,8 @@ var SkillRegistry = class {
|
|
|
8316
8959
|
// packages/daemon/src/HTTPServer.ts
|
|
8317
8960
|
import { Hono as Hono14 } from "hono";
|
|
8318
8961
|
import { serve } from "@hono/node-server";
|
|
8319
|
-
import { readFileSync as
|
|
8320
|
-
import { resolve as
|
|
8962
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
8963
|
+
import { resolve as resolve12, dirname as dirname4 } from "node:path";
|
|
8321
8964
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
8322
8965
|
|
|
8323
8966
|
// packages/daemon/src/routes/health.ts
|
|
@@ -8609,8 +9252,8 @@ function memoryRoutes(deps) {
|
|
|
8609
9252
|
// packages/daemon/src/routes/llm.ts
|
|
8610
9253
|
init_LLMExecutor();
|
|
8611
9254
|
import { Hono as Hono10 } from "hono";
|
|
8612
|
-
import { readFileSync as
|
|
8613
|
-
import { resolve as
|
|
9255
|
+
import { readFileSync as readFileSync10, existsSync as existsSync13 } from "node:fs";
|
|
9256
|
+
import { resolve as resolve11 } from "node:path";
|
|
8614
9257
|
import { homedir as homedir5 } from "node:os";
|
|
8615
9258
|
import YAML4 from "yaml";
|
|
8616
9259
|
function llmRoutes() {
|
|
@@ -8618,11 +9261,11 @@ function llmRoutes() {
|
|
|
8618
9261
|
app.post("/ping", async (c) => {
|
|
8619
9262
|
const start = Date.now();
|
|
8620
9263
|
try {
|
|
8621
|
-
const configPath =
|
|
8622
|
-
if (!
|
|
9264
|
+
const configPath = resolve11(homedir5(), ".0agent", "config.yaml");
|
|
9265
|
+
if (!existsSync13(configPath)) {
|
|
8623
9266
|
return c.json({ ok: false, error: "Config not found. Run: 0agent init" });
|
|
8624
9267
|
}
|
|
8625
|
-
const cfg = YAML4.parse(
|
|
9268
|
+
const cfg = YAML4.parse(readFileSync10(configPath, "utf8"));
|
|
8626
9269
|
const providers = cfg.llm_providers;
|
|
8627
9270
|
const def = providers?.find((p) => p.is_default) ?? providers?.[0];
|
|
8628
9271
|
if (!def) {
|
|
@@ -8707,7 +9350,7 @@ function codespaceRoutes(deps) {
|
|
|
8707
9350
|
// packages/daemon/src/routes/schedule.ts
|
|
8708
9351
|
import { Hono as Hono12 } from "hono";
|
|
8709
9352
|
|
|
8710
|
-
// packages/daemon/src/SchedulerManager.ts
|
|
9353
|
+
// packages/daemon/src/tasks/SchedulerManager.ts
|
|
8711
9354
|
var DAYS = {
|
|
8712
9355
|
sunday: 0,
|
|
8713
9356
|
sun: 0,
|
|
@@ -9137,15 +9780,15 @@ function runtimeRoutes(deps) {
|
|
|
9137
9780
|
// packages/daemon/src/HTTPServer.ts
|
|
9138
9781
|
function findGraphHtml() {
|
|
9139
9782
|
const candidates = [
|
|
9140
|
-
|
|
9783
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "graph.html"),
|
|
9141
9784
|
// dev (src/)
|
|
9142
|
-
|
|
9785
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "..", "graph.html"),
|
|
9143
9786
|
// bundled (dist/../)
|
|
9144
|
-
|
|
9787
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "..", "dist", "graph.html")
|
|
9145
9788
|
];
|
|
9146
9789
|
for (const p of candidates) {
|
|
9147
9790
|
try {
|
|
9148
|
-
|
|
9791
|
+
readFileSync11(p);
|
|
9149
9792
|
return p;
|
|
9150
9793
|
} catch {
|
|
9151
9794
|
}
|
|
@@ -9181,7 +9824,7 @@ var HTTPServer = class {
|
|
|
9181
9824
|
}
|
|
9182
9825
|
const serveGraph = (c) => {
|
|
9183
9826
|
try {
|
|
9184
|
-
const html =
|
|
9827
|
+
const html = readFileSync11(GRAPH_HTML_PATH, "utf8");
|
|
9185
9828
|
return c.html(html);
|
|
9186
9829
|
} catch {
|
|
9187
9830
|
return c.html("<p>Graph UI not found. Run: pnpm build</p>");
|
|
@@ -9191,7 +9834,7 @@ var HTTPServer = class {
|
|
|
9191
9834
|
this.app.get("/graph", serveGraph);
|
|
9192
9835
|
}
|
|
9193
9836
|
start() {
|
|
9194
|
-
return new Promise((
|
|
9837
|
+
return new Promise((resolve19) => {
|
|
9195
9838
|
this.server = serve(
|
|
9196
9839
|
{
|
|
9197
9840
|
fetch: this.app.fetch,
|
|
@@ -9199,20 +9842,20 @@ var HTTPServer = class {
|
|
|
9199
9842
|
hostname: this.deps.host
|
|
9200
9843
|
},
|
|
9201
9844
|
() => {
|
|
9202
|
-
|
|
9845
|
+
resolve19();
|
|
9203
9846
|
}
|
|
9204
9847
|
);
|
|
9205
9848
|
});
|
|
9206
9849
|
}
|
|
9207
9850
|
stop() {
|
|
9208
|
-
return new Promise((
|
|
9851
|
+
return new Promise((resolve19, reject) => {
|
|
9209
9852
|
if (!this.server) {
|
|
9210
|
-
|
|
9853
|
+
resolve19();
|
|
9211
9854
|
return;
|
|
9212
9855
|
}
|
|
9213
9856
|
this.server.close((err) => {
|
|
9214
9857
|
if (err) reject(err);
|
|
9215
|
-
else
|
|
9858
|
+
else resolve19();
|
|
9216
9859
|
});
|
|
9217
9860
|
});
|
|
9218
9861
|
}
|
|
@@ -9224,13 +9867,13 @@ var HTTPServer = class {
|
|
|
9224
9867
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
9225
9868
|
init_LLMExecutor();
|
|
9226
9869
|
|
|
9227
|
-
// packages/daemon/src/IdentityManager.ts
|
|
9870
|
+
// packages/daemon/src/utils/IdentityManager.ts
|
|
9228
9871
|
init_src();
|
|
9229
|
-
import { readFileSync as
|
|
9230
|
-
import { resolve as
|
|
9872
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, existsSync as existsSync14, mkdirSync as mkdirSync5 } from "node:fs";
|
|
9873
|
+
import { resolve as resolve13, dirname as dirname5 } from "node:path";
|
|
9231
9874
|
import { homedir as homedir6, hostname } from "node:os";
|
|
9232
9875
|
import YAML5 from "yaml";
|
|
9233
|
-
var IDENTITY_PATH =
|
|
9876
|
+
var IDENTITY_PATH = resolve13(homedir6(), ".0agent", "identity.yaml");
|
|
9234
9877
|
var DEFAULT_IDENTITY = {
|
|
9235
9878
|
name: "User",
|
|
9236
9879
|
device_id: `unknown-device`,
|
|
@@ -9246,8 +9889,8 @@ var IdentityManager = class {
|
|
|
9246
9889
|
* Load or create identity. Call once at daemon startup.
|
|
9247
9890
|
*/
|
|
9248
9891
|
async init() {
|
|
9249
|
-
if (
|
|
9250
|
-
const raw =
|
|
9892
|
+
if (existsSync14(IDENTITY_PATH)) {
|
|
9893
|
+
const raw = readFileSync12(IDENTITY_PATH, "utf8");
|
|
9251
9894
|
this.identity = YAML5.parse(raw);
|
|
9252
9895
|
} else {
|
|
9253
9896
|
this.identity = {
|
|
@@ -9299,24 +9942,24 @@ var IdentityManager = class {
|
|
|
9299
9942
|
}
|
|
9300
9943
|
save() {
|
|
9301
9944
|
const dir = dirname5(IDENTITY_PATH);
|
|
9302
|
-
if (!
|
|
9945
|
+
if (!existsSync14(dir)) {
|
|
9303
9946
|
mkdirSync5(dir, { recursive: true });
|
|
9304
9947
|
}
|
|
9305
9948
|
writeFileSync7(IDENTITY_PATH, YAML5.stringify(this.identity), "utf8");
|
|
9306
9949
|
}
|
|
9307
9950
|
};
|
|
9308
9951
|
|
|
9309
|
-
// packages/daemon/src/TeamManager.ts
|
|
9310
|
-
import { readFileSync as
|
|
9311
|
-
import { resolve as
|
|
9952
|
+
// packages/daemon/src/services/TeamManager.ts
|
|
9953
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync6 } from "node:fs";
|
|
9954
|
+
import { resolve as resolve14 } from "node:path";
|
|
9312
9955
|
import { homedir as homedir7 } from "node:os";
|
|
9313
9956
|
import YAML6 from "yaml";
|
|
9314
|
-
var TEAMS_PATH =
|
|
9957
|
+
var TEAMS_PATH = resolve14(homedir7(), ".0agent", "teams.yaml");
|
|
9315
9958
|
var TeamManager = class {
|
|
9316
9959
|
config;
|
|
9317
9960
|
constructor() {
|
|
9318
|
-
if (
|
|
9319
|
-
this.config = YAML6.parse(
|
|
9961
|
+
if (existsSync15(TEAMS_PATH)) {
|
|
9962
|
+
this.config = YAML6.parse(readFileSync13(TEAMS_PATH, "utf8"));
|
|
9320
9963
|
} else {
|
|
9321
9964
|
this.config = { memberships: [] };
|
|
9322
9965
|
}
|
|
@@ -9371,12 +10014,12 @@ var TeamManager = class {
|
|
|
9371
10014
|
}
|
|
9372
10015
|
}
|
|
9373
10016
|
save() {
|
|
9374
|
-
mkdirSync6(
|
|
10017
|
+
mkdirSync6(resolve14(homedir7(), ".0agent"), { recursive: true });
|
|
9375
10018
|
writeFileSync8(TEAMS_PATH, YAML6.stringify(this.config), "utf8");
|
|
9376
10019
|
}
|
|
9377
10020
|
};
|
|
9378
10021
|
|
|
9379
|
-
// packages/daemon/src/TeamSync.ts
|
|
10022
|
+
// packages/daemon/src/services/TeamSync.ts
|
|
9380
10023
|
var TeamSync = class {
|
|
9381
10024
|
constructor(teamManager, adapter, entityNodeId) {
|
|
9382
10025
|
this.teamManager = teamManager;
|
|
@@ -9454,9 +10097,9 @@ var TeamSync = class {
|
|
|
9454
10097
|
}
|
|
9455
10098
|
};
|
|
9456
10099
|
|
|
9457
|
-
// packages/daemon/src/GitHubMemorySync.ts
|
|
9458
|
-
import { readFileSync as
|
|
9459
|
-
import { resolve as
|
|
10100
|
+
// packages/daemon/src/services/GitHubMemorySync.ts
|
|
10101
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync16, readdirSync as readdirSync4 } from "node:fs";
|
|
10102
|
+
import { resolve as resolve15 } from "node:path";
|
|
9460
10103
|
import { homedir as homedir8 } from "node:os";
|
|
9461
10104
|
var GITHUB_API = "https://api.github.com";
|
|
9462
10105
|
async function ghFetch(path, token, opts) {
|
|
@@ -9576,10 +10219,10 @@ var GitHubMemorySync = class {
|
|
|
9576
10219
|
)
|
|
9577
10220
|
);
|
|
9578
10221
|
}
|
|
9579
|
-
const customSkillsDir =
|
|
9580
|
-
if (
|
|
10222
|
+
const customSkillsDir = resolve15(homedir8(), ".0agent", "skills", "custom");
|
|
10223
|
+
if (existsSync16(customSkillsDir)) {
|
|
9581
10224
|
for (const file of readdirSync4(customSkillsDir).filter((f) => f.endsWith(".yaml"))) {
|
|
9582
|
-
const content =
|
|
10225
|
+
const content = readFileSync14(resolve15(customSkillsDir, file), "utf8");
|
|
9583
10226
|
pushes.push(putFile(token, owner, repo, `skills/custom/${file}`, content, commitMsg));
|
|
9584
10227
|
}
|
|
9585
10228
|
}
|
|
@@ -9765,7 +10408,7 @@ var GitHubMemorySync = class {
|
|
|
9765
10408
|
}
|
|
9766
10409
|
async pullCustomSkills() {
|
|
9767
10410
|
const { token, owner, repo } = this.config;
|
|
9768
|
-
const dir =
|
|
10411
|
+
const dir = resolve15(homedir8(), ".0agent", "skills", "custom");
|
|
9769
10412
|
try {
|
|
9770
10413
|
const res = await ghFetch(`/repos/${owner}/${repo}/contents/skills/custom`, token);
|
|
9771
10414
|
if (!res.ok) return;
|
|
@@ -9775,7 +10418,7 @@ var GitHubMemorySync = class {
|
|
|
9775
10418
|
if (content) {
|
|
9776
10419
|
const { mkdirSync: mkdirSync11 } = await import("node:fs");
|
|
9777
10420
|
mkdirSync11(dir, { recursive: true });
|
|
9778
|
-
writeFileSync9(
|
|
10421
|
+
writeFileSync9(resolve15(dir, file.name), content, "utf8");
|
|
9779
10422
|
}
|
|
9780
10423
|
}
|
|
9781
10424
|
} catch {
|
|
@@ -9851,8 +10494,8 @@ git checkout <commit> graph/ # restore graph files
|
|
|
9851
10494
|
}
|
|
9852
10495
|
};
|
|
9853
10496
|
|
|
9854
|
-
// packages/daemon/src/CodespaceManager.ts
|
|
9855
|
-
import { execSync as
|
|
10497
|
+
// packages/daemon/src/services/CodespaceManager.ts
|
|
10498
|
+
import { execSync as execSync8, spawn as spawn8 } from "node:child_process";
|
|
9856
10499
|
var BROWSER_PORT_REMOTE = 3e3;
|
|
9857
10500
|
var BROWSER_PORT_LOCAL = 3001;
|
|
9858
10501
|
var DISPLAY_NAME = "0agent-browser";
|
|
@@ -9894,7 +10537,7 @@ var CodespaceManager = class {
|
|
|
9894
10537
|
console.log(`[Codespace] Creating browser codespace from ${this.memoryRepo}...`);
|
|
9895
10538
|
console.log("[Codespace] First time: ~2-3 minutes. Subsequent starts: ~30 seconds.");
|
|
9896
10539
|
try {
|
|
9897
|
-
const result =
|
|
10540
|
+
const result = execSync8(
|
|
9898
10541
|
`gh codespace create --repo "${this.memoryRepo}" --machine basicLinux32gb --display-name "${DISPLAY_NAME}" --json name`,
|
|
9899
10542
|
{ encoding: "utf8", timeout: 3e5 }
|
|
9900
10543
|
);
|
|
@@ -9908,7 +10551,7 @@ var CodespaceManager = class {
|
|
|
9908
10551
|
/** Find the 0agent-browser codespace by display name. */
|
|
9909
10552
|
findExisting() {
|
|
9910
10553
|
try {
|
|
9911
|
-
const out =
|
|
10554
|
+
const out = execSync8("gh codespace list --json name,state,displayName,repository", {
|
|
9912
10555
|
encoding: "utf8",
|
|
9913
10556
|
timeout: 1e4
|
|
9914
10557
|
});
|
|
@@ -9924,7 +10567,7 @@ var CodespaceManager = class {
|
|
|
9924
10567
|
const info = this.findExisting();
|
|
9925
10568
|
if (info?.state === "Shutdown") {
|
|
9926
10569
|
console.log("[Codespace] Starting stopped codespace (~30s)...");
|
|
9927
|
-
|
|
10570
|
+
execSync8(`gh codespace start --codespace "${name}"`, { timeout: 12e4 });
|
|
9928
10571
|
await this.waitForState(name, "Available", 60);
|
|
9929
10572
|
console.log("[Codespace] Codespace is running");
|
|
9930
10573
|
} else if (info?.state === "Starting") {
|
|
@@ -9936,7 +10579,7 @@ var CodespaceManager = class {
|
|
|
9936
10579
|
/** Start the browser server inside the codespace (idempotent). */
|
|
9937
10580
|
async startBrowserServer(name) {
|
|
9938
10581
|
try {
|
|
9939
|
-
|
|
10582
|
+
execSync8(
|
|
9940
10583
|
`gh codespace exec --codespace "${name}" -- bash -c "pgrep -f 'node server.js' > /dev/null 2>&1 || (cd /workspaces && nohup node server.js > /tmp/browser-server.log 2>&1 &)"`,
|
|
9941
10584
|
{ timeout: 3e4 }
|
|
9942
10585
|
);
|
|
@@ -9947,7 +10590,7 @@ var CodespaceManager = class {
|
|
|
9947
10590
|
async openTunnel(name) {
|
|
9948
10591
|
this.closeTunnel();
|
|
9949
10592
|
console.log(`[Codespace] Opening tunnel port ${BROWSER_PORT_REMOTE} \u2192 localhost:${BROWSER_PORT_LOCAL}...`);
|
|
9950
|
-
this.forwardProcess =
|
|
10593
|
+
this.forwardProcess = spawn8(
|
|
9951
10594
|
"gh",
|
|
9952
10595
|
["codespace", "ports", "forward", `${BROWSER_PORT_REMOTE}:${BROWSER_PORT_LOCAL}`, "--codespace", name],
|
|
9953
10596
|
{ stdio: ["ignore", "ignore", "ignore"] }
|
|
@@ -9991,7 +10634,7 @@ var CodespaceManager = class {
|
|
|
9991
10634
|
this.closeTunnel();
|
|
9992
10635
|
const info = this.findExisting();
|
|
9993
10636
|
if (info?.state === "Available") {
|
|
9994
|
-
|
|
10637
|
+
execSync8(`gh codespace stop --codespace "${info.name}"`, { timeout: 3e4 });
|
|
9995
10638
|
console.log("[Codespace] Stopped (state preserved, restarts in 30s when needed)");
|
|
9996
10639
|
}
|
|
9997
10640
|
}
|
|
@@ -10000,7 +10643,7 @@ var CodespaceManager = class {
|
|
|
10000
10643
|
this.closeTunnel();
|
|
10001
10644
|
const info = this.findExisting();
|
|
10002
10645
|
if (info) {
|
|
10003
|
-
|
|
10646
|
+
execSync8(`gh codespace delete --codespace "${info.name}" --force`, { timeout: 3e4 });
|
|
10004
10647
|
console.log("[Codespace] Deleted");
|
|
10005
10648
|
}
|
|
10006
10649
|
}
|
|
@@ -10026,7 +10669,7 @@ var CodespaceManager = class {
|
|
|
10026
10669
|
/** Check if gh CLI is installed and authenticated. */
|
|
10027
10670
|
static isAvailable() {
|
|
10028
10671
|
try {
|
|
10029
|
-
|
|
10672
|
+
execSync8("gh auth status", { stdio: "ignore", timeout: 5e3 });
|
|
10030
10673
|
return true;
|
|
10031
10674
|
} catch {
|
|
10032
10675
|
return false;
|
|
@@ -10037,7 +10680,7 @@ var CodespaceManager = class {
|
|
|
10037
10680
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
10038
10681
|
init_RuntimeSelfHeal();
|
|
10039
10682
|
|
|
10040
|
-
// packages/daemon/src/TelegramBridge.ts
|
|
10683
|
+
// packages/daemon/src/services/TelegramBridge.ts
|
|
10041
10684
|
var TelegramBridge = class {
|
|
10042
10685
|
constructor(config, sessions, eventBus) {
|
|
10043
10686
|
this.config = config;
|
|
@@ -10336,52 +10979,52 @@ var SurfaceRouter = class {
|
|
|
10336
10979
|
}
|
|
10337
10980
|
_handleDaemonEvent(event) {
|
|
10338
10981
|
const sessionId = String(event.session_id ?? "");
|
|
10339
|
-
const
|
|
10340
|
-
if (!
|
|
10341
|
-
const adapter = this.adapters.get(
|
|
10982
|
+
const state2 = this.activeSessions.get(sessionId);
|
|
10983
|
+
if (!state2) return;
|
|
10984
|
+
const adapter = this.adapters.get(state2.surface);
|
|
10342
10985
|
if (!adapter) return;
|
|
10343
10986
|
if (event.type === "session.token") {
|
|
10344
|
-
|
|
10345
|
-
if (
|
|
10346
|
-
|
|
10347
|
-
if (!
|
|
10987
|
+
state2.tokenBuffer += String(event.token ?? "");
|
|
10988
|
+
if (state2.streamTimer) clearTimeout(state2.streamTimer);
|
|
10989
|
+
state2.streamTimer = setTimeout(() => {
|
|
10990
|
+
if (!state2.tokenBuffer) return;
|
|
10348
10991
|
adapter.send({
|
|
10349
|
-
surface_channel_id:
|
|
10350
|
-
text:
|
|
10992
|
+
surface_channel_id: state2.channelId,
|
|
10993
|
+
text: state2.tokenBuffer,
|
|
10351
10994
|
format: "markdown",
|
|
10352
10995
|
is_progress: true,
|
|
10353
|
-
thread_id:
|
|
10996
|
+
thread_id: state2.threadId
|
|
10354
10997
|
}).catch(() => {
|
|
10355
10998
|
});
|
|
10356
10999
|
}, 400);
|
|
10357
11000
|
} else if (event.type === "session.completed") {
|
|
10358
|
-
if (
|
|
10359
|
-
clearTimeout(
|
|
10360
|
-
|
|
11001
|
+
if (state2.streamTimer) {
|
|
11002
|
+
clearTimeout(state2.streamTimer);
|
|
11003
|
+
state2.streamTimer = null;
|
|
10361
11004
|
}
|
|
10362
11005
|
const result = event.result;
|
|
10363
11006
|
const output = String(result?.output ?? "").trim();
|
|
10364
11007
|
if (output && output !== "(no output)") {
|
|
10365
11008
|
adapter.send({
|
|
10366
|
-
surface_channel_id:
|
|
11009
|
+
surface_channel_id: state2.channelId,
|
|
10367
11010
|
text: output,
|
|
10368
11011
|
format: "markdown",
|
|
10369
11012
|
is_progress: false,
|
|
10370
|
-
thread_id:
|
|
11013
|
+
thread_id: state2.threadId
|
|
10371
11014
|
}).catch(() => {
|
|
10372
11015
|
});
|
|
10373
11016
|
}
|
|
10374
11017
|
this.activeSessions.delete(sessionId);
|
|
10375
11018
|
} else if (event.type === "session.failed") {
|
|
10376
|
-
if (
|
|
10377
|
-
clearTimeout(
|
|
10378
|
-
|
|
11019
|
+
if (state2.streamTimer) {
|
|
11020
|
+
clearTimeout(state2.streamTimer);
|
|
11021
|
+
state2.streamTimer = null;
|
|
10379
11022
|
}
|
|
10380
11023
|
adapter.send({
|
|
10381
|
-
surface_channel_id:
|
|
11024
|
+
surface_channel_id: state2.channelId,
|
|
10382
11025
|
text: `\u26A0\uFE0F ${String(event.error ?? "Task failed")}`,
|
|
10383
11026
|
format: "prose",
|
|
10384
|
-
thread_id:
|
|
11027
|
+
thread_id: state2.threadId
|
|
10385
11028
|
}).catch(() => {
|
|
10386
11029
|
});
|
|
10387
11030
|
this.activeSessions.delete(sessionId);
|
|
@@ -10396,7 +11039,7 @@ var SurfaceRouter = class {
|
|
|
10396
11039
|
};
|
|
10397
11040
|
|
|
10398
11041
|
// packages/daemon/src/surfaces/TelegramAdapter.ts
|
|
10399
|
-
import { existsSync as
|
|
11042
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7 } from "node:fs";
|
|
10400
11043
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
10401
11044
|
import { join as join4 } from "node:path";
|
|
10402
11045
|
var TelegramAdapter = class {
|
|
@@ -10446,13 +11089,13 @@ var TelegramAdapter = class {
|
|
|
10446
11089
|
async send(msg) {
|
|
10447
11090
|
const chatId = Number(msg.surface_channel_id);
|
|
10448
11091
|
if (!chatId) return;
|
|
10449
|
-
const
|
|
10450
|
-
if (msg.is_progress &&
|
|
10451
|
-
|
|
10452
|
-
await this._editMessage(chatId,
|
|
11092
|
+
const state2 = this.streamingState.get(chatId);
|
|
11093
|
+
if (msg.is_progress && state2) {
|
|
11094
|
+
state2.accumulatedText = msg.text;
|
|
11095
|
+
await this._editMessage(chatId, state2.workingMsgId, `\u23F3 ${this._truncate(msg.text, 3800)}`);
|
|
10453
11096
|
} else {
|
|
10454
|
-
if (
|
|
10455
|
-
await this._editMessage(chatId,
|
|
11097
|
+
if (state2) {
|
|
11098
|
+
await this._editMessage(chatId, state2.workingMsgId, msg.text);
|
|
10456
11099
|
this.streamingState.delete(chatId);
|
|
10457
11100
|
} else {
|
|
10458
11101
|
await this._sendMessage(chatId, msg.text);
|
|
@@ -10603,7 +11246,7 @@ Sessions: ${h.active_sessions} active`
|
|
|
10603
11246
|
const fileUrl = await this._getFileUrl(fileId);
|
|
10604
11247
|
if (!fileUrl) return null;
|
|
10605
11248
|
const tmpDir = join4(tmpdir3(), "0agent-voice");
|
|
10606
|
-
if (!
|
|
11249
|
+
if (!existsSync17(tmpDir)) mkdirSync7(tmpDir, { recursive: true });
|
|
10607
11250
|
const tmpPath = join4(tmpDir, `${fileId}.ogg`);
|
|
10608
11251
|
const wavPath = join4(tmpDir, `${fileId}.wav`);
|
|
10609
11252
|
const res = await fetch(fileUrl);
|
|
@@ -10611,20 +11254,20 @@ Sessions: ${h.active_sessions} active`
|
|
|
10611
11254
|
const buf = await res.arrayBuffer();
|
|
10612
11255
|
const { writeFileSync: writeFileSync13 } = await import("node:fs");
|
|
10613
11256
|
writeFileSync13(tmpPath, Buffer.from(buf));
|
|
10614
|
-
const { execSync:
|
|
11257
|
+
const { execSync: execSync11 } = await import("node:child_process");
|
|
10615
11258
|
try {
|
|
10616
|
-
|
|
11259
|
+
execSync11(`ffmpeg -y -i "${tmpPath}" -ar 16000 -ac 1 "${wavPath}" 2>/dev/null`, { timeout: 3e4 });
|
|
10617
11260
|
} catch {
|
|
10618
11261
|
}
|
|
10619
|
-
const inputFile =
|
|
10620
|
-
const whisperOut =
|
|
11262
|
+
const inputFile = existsSync17(wavPath) ? wavPath : tmpPath;
|
|
11263
|
+
const whisperOut = execSync11(
|
|
10621
11264
|
`whisper "${inputFile}" --model ${this.whisperModel} --output_format txt --output_dir "${tmpDir}" --fp16 False 2>/dev/null`,
|
|
10622
11265
|
{ timeout: 12e4, encoding: "utf8" }
|
|
10623
11266
|
);
|
|
10624
11267
|
const txtPath = inputFile.replace(/\.(ogg|wav)$/, ".txt");
|
|
10625
|
-
if (
|
|
10626
|
-
const { readFileSync:
|
|
10627
|
-
return
|
|
11268
|
+
if (existsSync17(txtPath)) {
|
|
11269
|
+
const { readFileSync: readFileSync18 } = await import("node:fs");
|
|
11270
|
+
return readFileSync18(txtPath, "utf8").trim();
|
|
10628
11271
|
}
|
|
10629
11272
|
return whisperOut?.trim() || null;
|
|
10630
11273
|
} catch {
|
|
@@ -10790,24 +11433,24 @@ var SlackAdapter = class {
|
|
|
10790
11433
|
if (!this.app) return;
|
|
10791
11434
|
const client = this.app["client"];
|
|
10792
11435
|
const stateKey = `${msg.surface_channel_id}:${msg.thread_id ?? ""}`;
|
|
10793
|
-
const
|
|
10794
|
-
if (msg.is_progress &&
|
|
11436
|
+
const state2 = this.streamingState.get(stateKey);
|
|
11437
|
+
if (msg.is_progress && state2) {
|
|
10795
11438
|
try {
|
|
10796
11439
|
await client["chat.update"]({
|
|
10797
|
-
channel:
|
|
10798
|
-
ts:
|
|
11440
|
+
channel: state2.channelId,
|
|
11441
|
+
ts: state2.ts,
|
|
10799
11442
|
text: `\u23F3 ${this._truncate(msg.text, 3e3)}`
|
|
10800
11443
|
});
|
|
10801
11444
|
} catch {
|
|
10802
11445
|
}
|
|
10803
11446
|
} else {
|
|
10804
|
-
if (
|
|
11447
|
+
if (state2) {
|
|
10805
11448
|
try {
|
|
10806
11449
|
await client["chat.update"]({
|
|
10807
|
-
channel:
|
|
10808
|
-
ts:
|
|
11450
|
+
channel: state2.channelId,
|
|
11451
|
+
ts: state2.ts,
|
|
10809
11452
|
text: msg.text,
|
|
10810
|
-
thread_ts:
|
|
11453
|
+
thread_ts: state2.threadTs || void 0
|
|
10811
11454
|
});
|
|
10812
11455
|
} catch {
|
|
10813
11456
|
await this._postMessage(client, msg.surface_channel_id, msg.text, msg.thread_id);
|
|
@@ -11066,10 +11709,10 @@ var WhatsAppAdapter = class {
|
|
|
11066
11709
|
import * as readline from "node:readline";
|
|
11067
11710
|
|
|
11068
11711
|
// packages/daemon/src/surfaces/WhisperSTT.ts
|
|
11069
|
-
import { execSync as
|
|
11070
|
-
import { existsSync as
|
|
11712
|
+
import { execSync as execSync9, spawnSync as spawnSync5 } from "node:child_process";
|
|
11713
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync15 } from "node:fs";
|
|
11071
11714
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
11072
|
-
import { join as join5, basename } from "node:path";
|
|
11715
|
+
import { join as join5, basename as basename2 } from "node:path";
|
|
11073
11716
|
var WhisperSTT = class _WhisperSTT {
|
|
11074
11717
|
model;
|
|
11075
11718
|
language;
|
|
@@ -11085,20 +11728,20 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11085
11728
|
console.warn("[WhisperSTT] No Whisper binary found. Install: pip install openai-whisper");
|
|
11086
11729
|
return null;
|
|
11087
11730
|
}
|
|
11088
|
-
if (!
|
|
11731
|
+
if (!existsSync18(audioPath)) {
|
|
11089
11732
|
console.warn(`[WhisperSTT] Audio file not found: ${audioPath}`);
|
|
11090
11733
|
return null;
|
|
11091
11734
|
}
|
|
11092
11735
|
const outDir = join5(tmpdir4(), "0agent-whisper");
|
|
11093
|
-
if (!
|
|
11736
|
+
if (!existsSync18(outDir)) mkdirSync8(outDir, { recursive: true });
|
|
11094
11737
|
try {
|
|
11095
11738
|
const langFlag = this.language ? `--language ${this.language}` : "";
|
|
11096
11739
|
const cmd = this.binary === "faster-whisper" ? `faster-whisper "${audioPath}" --model ${this.model} ${langFlag} --output_format txt --output_dir "${outDir}"` : `whisper "${audioPath}" --model ${this.model} ${langFlag} --output_format txt --output_dir "${outDir}" --fp16 False`;
|
|
11097
|
-
|
|
11098
|
-
const baseName =
|
|
11740
|
+
execSync9(cmd, { timeout: 18e4, stdio: "pipe" });
|
|
11741
|
+
const baseName = basename2(audioPath).replace(/\.[^.]+$/, "");
|
|
11099
11742
|
const txtPath = join5(outDir, `${baseName}.txt`);
|
|
11100
|
-
if (
|
|
11101
|
-
return
|
|
11743
|
+
if (existsSync18(txtPath)) {
|
|
11744
|
+
return readFileSync15(txtPath, "utf8").trim();
|
|
11102
11745
|
}
|
|
11103
11746
|
return null;
|
|
11104
11747
|
} catch (err) {
|
|
@@ -11123,14 +11766,14 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11123
11766
|
};
|
|
11124
11767
|
async function recordAudio(durationSeconds) {
|
|
11125
11768
|
const outDir = join5(tmpdir4(), "0agent-voice");
|
|
11126
|
-
if (!
|
|
11769
|
+
if (!existsSync18(outDir)) mkdirSync8(outDir, { recursive: true });
|
|
11127
11770
|
const outPath = join5(outDir, `recording-${Date.now()}.wav`);
|
|
11128
11771
|
const soxResult = spawnSync5(
|
|
11129
11772
|
"sox",
|
|
11130
11773
|
["-d", "-r", "16000", "-c", "1", "-b", "16", outPath, "trim", "0", String(durationSeconds)],
|
|
11131
11774
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11132
11775
|
);
|
|
11133
|
-
if (soxResult.status === 0 &&
|
|
11776
|
+
if (soxResult.status === 0 && existsSync18(outPath)) return outPath;
|
|
11134
11777
|
const platform3 = process.platform;
|
|
11135
11778
|
let ffmpegDevice;
|
|
11136
11779
|
if (platform3 === "darwin") {
|
|
@@ -11145,11 +11788,11 @@ async function recordAudio(durationSeconds) {
|
|
|
11145
11788
|
["-y", ...ffmpegDevice, "-ar", "16000", "-ac", "1", "-t", String(durationSeconds), outPath],
|
|
11146
11789
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11147
11790
|
);
|
|
11148
|
-
return ffmpegResult.status === 0 &&
|
|
11791
|
+
return ffmpegResult.status === 0 && existsSync18(outPath) ? outPath : null;
|
|
11149
11792
|
}
|
|
11150
11793
|
|
|
11151
11794
|
// packages/daemon/src/surfaces/NativeTTS.ts
|
|
11152
|
-
import { spawnSync as spawnSync6, spawn as
|
|
11795
|
+
import { spawnSync as spawnSync6, spawn as spawn9 } from "node:child_process";
|
|
11153
11796
|
var NativeTTS = class _NativeTTS {
|
|
11154
11797
|
engine;
|
|
11155
11798
|
voice;
|
|
@@ -11173,11 +11816,11 @@ var NativeTTS = class _NativeTTS {
|
|
|
11173
11816
|
if (!this.resolvedEngine) return;
|
|
11174
11817
|
const cleaned = this._clean(text);
|
|
11175
11818
|
if (!cleaned) return;
|
|
11176
|
-
return new Promise((
|
|
11819
|
+
return new Promise((resolve19) => {
|
|
11177
11820
|
const args = this._buildArgs(this.resolvedEngine, cleaned);
|
|
11178
|
-
const proc =
|
|
11179
|
-
proc.on("close", () =>
|
|
11180
|
-
proc.on("error", () =>
|
|
11821
|
+
const proc = spawn9(this.resolvedEngine, args, { stdio: "ignore" });
|
|
11822
|
+
proc.on("close", () => resolve19());
|
|
11823
|
+
proc.on("error", () => resolve19());
|
|
11181
11824
|
});
|
|
11182
11825
|
}
|
|
11183
11826
|
/** Check if any TTS engine is available */
|
|
@@ -11235,7 +11878,7 @@ var NativeTTS = class _NativeTTS {
|
|
|
11235
11878
|
}
|
|
11236
11879
|
_speakWith(engine, text) {
|
|
11237
11880
|
const args = this._buildArgs(engine, text);
|
|
11238
|
-
const proc =
|
|
11881
|
+
const proc = spawn9(engine, args, { stdio: "ignore", detached: true });
|
|
11239
11882
|
proc.unref();
|
|
11240
11883
|
}
|
|
11241
11884
|
/** Remove markdown/ANSI and control chars before speaking */
|
|
@@ -11360,10 +12003,10 @@ var VoiceAdapter = class {
|
|
|
11360
12003
|
};
|
|
11361
12004
|
|
|
11362
12005
|
// packages/daemon/src/surfaces/MeetingAdapter.ts
|
|
11363
|
-
import { existsSync as
|
|
12006
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
11364
12007
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
11365
12008
|
import { join as join6 } from "node:path";
|
|
11366
|
-
import { spawn as
|
|
12009
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
11367
12010
|
var MeetingAdapter = class {
|
|
11368
12011
|
name = "meeting";
|
|
11369
12012
|
messageHandler = null;
|
|
@@ -11388,7 +12031,7 @@ var MeetingAdapter = class {
|
|
|
11388
12031
|
this.triggerPhrases = config.trigger_phrases ?? ["agent,", "hey agent", "ok agent"];
|
|
11389
12032
|
this.contextWindowSeconds = config.context_window_seconds ?? 120;
|
|
11390
12033
|
this.tmpDir = join6(tmpdir5(), "0agent-meeting");
|
|
11391
|
-
if (!
|
|
12034
|
+
if (!existsSync19(this.tmpDir)) mkdirSync9(this.tmpDir, { recursive: true });
|
|
11392
12035
|
this.stt = new WhisperSTT({ model: config.whisper_model ?? "base" });
|
|
11393
12036
|
}
|
|
11394
12037
|
onMessage(handler) {
|
|
@@ -11473,7 +12116,7 @@ ${msg.text}
|
|
|
11473
12116
|
async _captureAndTranscribeChunk(channelId) {
|
|
11474
12117
|
const chunkPath = join6(this.tmpDir, `chunk-${Date.now()}.wav`);
|
|
11475
12118
|
const captured = await this._captureSystemAudio(chunkPath, this.chunkSeconds);
|
|
11476
|
-
if (!captured || !
|
|
12119
|
+
if (!captured || !existsSync19(chunkPath)) return;
|
|
11477
12120
|
const text = await this.stt.transcribe(chunkPath);
|
|
11478
12121
|
if (!text || text.trim().length < 3) return;
|
|
11479
12122
|
const segment = { text: text.trim(), timestamp: Date.now() };
|
|
@@ -11494,7 +12137,7 @@ ${msg.text}
|
|
|
11494
12137
|
}
|
|
11495
12138
|
}
|
|
11496
12139
|
async _captureSystemAudio(outPath, seconds) {
|
|
11497
|
-
return new Promise((
|
|
12140
|
+
return new Promise((resolve19) => {
|
|
11498
12141
|
const platform3 = process.platform;
|
|
11499
12142
|
let args;
|
|
11500
12143
|
if (platform3 === "darwin") {
|
|
@@ -11502,18 +12145,18 @@ ${msg.text}
|
|
|
11502
12145
|
} else if (platform3 === "linux") {
|
|
11503
12146
|
args = ["-y", "-f", "pulse", "-i", "default.monitor", "-ar", "16000", "-ac", "1", "-t", String(seconds), outPath];
|
|
11504
12147
|
} else {
|
|
11505
|
-
|
|
12148
|
+
resolve19(false);
|
|
11506
12149
|
return;
|
|
11507
12150
|
}
|
|
11508
|
-
const proc =
|
|
12151
|
+
const proc = spawn10("ffmpeg", args, { stdio: "pipe" });
|
|
11509
12152
|
this.ffmpegProcess = proc;
|
|
11510
12153
|
proc.on("close", (code) => {
|
|
11511
12154
|
this.ffmpegProcess = null;
|
|
11512
|
-
|
|
12155
|
+
resolve19(code === 0);
|
|
11513
12156
|
});
|
|
11514
12157
|
proc.on("error", () => {
|
|
11515
12158
|
this.ffmpegProcess = null;
|
|
11516
|
-
|
|
12159
|
+
resolve19(false);
|
|
11517
12160
|
});
|
|
11518
12161
|
});
|
|
11519
12162
|
}
|
|
@@ -11611,12 +12254,12 @@ var ZeroAgentDaemon = class {
|
|
|
11611
12254
|
startedAt = 0;
|
|
11612
12255
|
pidFilePath;
|
|
11613
12256
|
constructor() {
|
|
11614
|
-
this.pidFilePath =
|
|
12257
|
+
this.pidFilePath = resolve17(homedir9(), ".0agent", "daemon.pid");
|
|
11615
12258
|
}
|
|
11616
12259
|
async start(opts) {
|
|
11617
12260
|
this.config = await loadConfig(opts?.config_path);
|
|
11618
|
-
const dotDir =
|
|
11619
|
-
if (!
|
|
12261
|
+
const dotDir = resolve17(homedir9(), ".0agent");
|
|
12262
|
+
if (!existsSync21(dotDir)) {
|
|
11620
12263
|
mkdirSync10(dotDir, { recursive: true });
|
|
11621
12264
|
}
|
|
11622
12265
|
this.adapter = new SQLiteAdapter({ db_path: this.config.graph.db_path });
|
|
@@ -11690,10 +12333,10 @@ var ZeroAgentDaemon = class {
|
|
|
11690
12333
|
console.log(`[0agent] Teams: ${teams.map((t) => t.team_name).join(", ")}`);
|
|
11691
12334
|
}
|
|
11692
12335
|
const _daemonFile = fileURLToPath3(import.meta.url);
|
|
11693
|
-
const _agentRoot =
|
|
12336
|
+
const _agentRoot = resolve17(dirname7(_daemonFile), "..");
|
|
11694
12337
|
let agentRoot;
|
|
11695
12338
|
try {
|
|
11696
|
-
const _pkg = JSON.parse(
|
|
12339
|
+
const _pkg = JSON.parse(readFileSync17(resolve17(_agentRoot, "package.json"), "utf8"));
|
|
11697
12340
|
if (_pkg.name === "0agent") agentRoot = _agentRoot;
|
|
11698
12341
|
} catch {
|
|
11699
12342
|
}
|
|
@@ -11897,7 +12540,7 @@ var ZeroAgentDaemon = class {
|
|
|
11897
12540
|
this.graph = null;
|
|
11898
12541
|
}
|
|
11899
12542
|
this.adapter = null;
|
|
11900
|
-
if (
|
|
12543
|
+
if (existsSync21(this.pidFilePath)) {
|
|
11901
12544
|
try {
|
|
11902
12545
|
unlinkSync4(this.pidFilePath);
|
|
11903
12546
|
} catch {
|
|
@@ -11927,11 +12570,11 @@ var ZeroAgentDaemon = class {
|
|
|
11927
12570
|
};
|
|
11928
12571
|
|
|
11929
12572
|
// packages/daemon/src/start.ts
|
|
11930
|
-
import { resolve as
|
|
12573
|
+
import { resolve as resolve18 } from "node:path";
|
|
11931
12574
|
import { homedir as homedir10 } from "node:os";
|
|
11932
|
-
import { existsSync as
|
|
11933
|
-
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ??
|
|
11934
|
-
if (!
|
|
12575
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
12576
|
+
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ?? resolve18(homedir10(), ".0agent", "config.yaml");
|
|
12577
|
+
if (!existsSync22(CONFIG_PATH)) {
|
|
11935
12578
|
console.error(`
|
|
11936
12579
|
0agent is not initialised.
|
|
11937
12580
|
|