0agent 1.0.78 → 1.0.82
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 +935 -284
- 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/
|
|
2827
|
-
import { readFileSync as readFileSync2, writeFileSync, readdirSync, mkdirSync, existsSync as existsSync2 } from "node:fs";
|
|
2829
|
+
// packages/daemon/src/tools/FileCapability.ts
|
|
2830
|
+
import { readFileSync as readFileSync2, writeFileSync, readdirSync, mkdirSync, existsSync as existsSync2, statSync } 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";
|
|
@@ -2859,6 +2862,11 @@ var init_FileCapability = __esm({
|
|
|
2859
2862
|
try {
|
|
2860
2863
|
if (op === "read") {
|
|
2861
2864
|
if (!existsSync2(safe)) return { success: false, output: `Not found: ${rel}`, duration_ms: Date.now() - start };
|
|
2865
|
+
if (statSync(safe).isDirectory()) {
|
|
2866
|
+
const entries = readdirSync(safe, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && e.name !== "node_modules").map((e) => `${e.isDirectory() ? "d" : "f"} ${e.name}`).join("\n");
|
|
2867
|
+
return { success: true, output: `(directory listing for ${rel}):
|
|
2868
|
+
${entries || "(empty)"}`, duration_ms: Date.now() - start };
|
|
2869
|
+
}
|
|
2862
2870
|
const content = readFileSync2(safe, "utf8");
|
|
2863
2871
|
return {
|
|
2864
2872
|
success: true,
|
|
@@ -2913,10 +2921,10 @@ var init_FileCapability = __esm({
|
|
|
2913
2921
|
}
|
|
2914
2922
|
});
|
|
2915
2923
|
|
|
2916
|
-
// packages/daemon/src/
|
|
2924
|
+
// packages/daemon/src/tools/MemoryCapability.ts
|
|
2917
2925
|
var MemoryCapability;
|
|
2918
2926
|
var init_MemoryCapability = __esm({
|
|
2919
|
-
"packages/daemon/src/
|
|
2927
|
+
"packages/daemon/src/tools/MemoryCapability.ts"() {
|
|
2920
2928
|
"use strict";
|
|
2921
2929
|
init_src();
|
|
2922
2930
|
MemoryCapability = class {
|
|
@@ -3014,14 +3022,14 @@ var init_MemoryCapability = __esm({
|
|
|
3014
3022
|
}
|
|
3015
3023
|
});
|
|
3016
3024
|
|
|
3017
|
-
// packages/daemon/src/
|
|
3025
|
+
// packages/daemon/src/tools/GUICapability.ts
|
|
3018
3026
|
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
3019
3027
|
import { writeFileSync as writeFileSync2, unlinkSync } from "node:fs";
|
|
3020
3028
|
import { resolve as resolve3 } from "node:path";
|
|
3021
3029
|
import { tmpdir, platform as platform2 } from "node:os";
|
|
3022
3030
|
var GUICapability;
|
|
3023
3031
|
var init_GUICapability = __esm({
|
|
3024
|
-
"packages/daemon/src/
|
|
3032
|
+
"packages/daemon/src/tools/GUICapability.ts"() {
|
|
3025
3033
|
"use strict";
|
|
3026
3034
|
GUICapability = class {
|
|
3027
3035
|
name = "gui_automation";
|
|
@@ -4012,14 +4020,14 @@ else:
|
|
|
4012
4020
|
}
|
|
4013
4021
|
});
|
|
4014
4022
|
|
|
4015
|
-
// packages/daemon/src/
|
|
4023
|
+
// packages/daemon/src/tools/OpenInterpreterCapability.ts
|
|
4016
4024
|
import { spawn as spawn4 } from "node:child_process";
|
|
4017
4025
|
import { writeFileSync as writeFileSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
4018
4026
|
import { resolve as resolve4 } from "node:path";
|
|
4019
4027
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
4020
4028
|
var OI_SCRIPT, OpenInterpreterCapability;
|
|
4021
4029
|
var init_OpenInterpreterCapability = __esm({
|
|
4022
|
-
"packages/daemon/src/
|
|
4030
|
+
"packages/daemon/src/tools/OpenInterpreterCapability.ts"() {
|
|
4023
4031
|
"use strict";
|
|
4024
4032
|
OI_SCRIPT = `
|
|
4025
4033
|
import sys
|
|
@@ -4152,7 +4160,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4152
4160
|
}
|
|
4153
4161
|
/** Async pip install — never blocks the event loop (unlike spawnSync). */
|
|
4154
4162
|
_pipInstall(pkg, signal) {
|
|
4155
|
-
return new Promise((
|
|
4163
|
+
return new Promise((resolve19) => {
|
|
4156
4164
|
const proc = spawn4("pip3", ["install", pkg, "-q"], {
|
|
4157
4165
|
env: process.env,
|
|
4158
4166
|
stdio: "ignore"
|
|
@@ -4163,7 +4171,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4163
4171
|
settled = true;
|
|
4164
4172
|
signal?.removeEventListener("abort", onAbort);
|
|
4165
4173
|
clearTimeout(timer);
|
|
4166
|
-
|
|
4174
|
+
resolve19(ok);
|
|
4167
4175
|
};
|
|
4168
4176
|
const onAbort = () => {
|
|
4169
4177
|
try {
|
|
@@ -4185,7 +4193,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4185
4193
|
});
|
|
4186
4194
|
}
|
|
4187
4195
|
_runScript(scriptPath, stdinData, signal) {
|
|
4188
|
-
return new Promise((
|
|
4196
|
+
return new Promise((resolve19) => {
|
|
4189
4197
|
const proc = spawn4("python3", [scriptPath], {
|
|
4190
4198
|
env: process.env,
|
|
4191
4199
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4198,7 +4206,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4198
4206
|
settled = true;
|
|
4199
4207
|
signal?.removeEventListener("abort", onAbort);
|
|
4200
4208
|
clearTimeout(timer);
|
|
4201
|
-
|
|
4209
|
+
resolve19({ stdout: out.join(""), stderr: err.join(""), code });
|
|
4202
4210
|
};
|
|
4203
4211
|
const onAbort = () => {
|
|
4204
4212
|
try {
|
|
@@ -4227,13 +4235,13 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4227
4235
|
}
|
|
4228
4236
|
});
|
|
4229
4237
|
|
|
4230
|
-
// packages/daemon/src/
|
|
4238
|
+
// packages/daemon/src/tools/SurgeCapability.ts
|
|
4231
4239
|
import { execSync as execSync3 } from "node:child_process";
|
|
4232
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, copyFileSync, statSync } from "node:fs";
|
|
4240
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, copyFileSync, statSync as statSync2 } from "node:fs";
|
|
4233
4241
|
import { join } from "node:path";
|
|
4234
4242
|
var SurgeCapability;
|
|
4235
4243
|
var init_SurgeCapability = __esm({
|
|
4236
|
-
"packages/daemon/src/
|
|
4244
|
+
"packages/daemon/src/tools/SurgeCapability.ts"() {
|
|
4237
4245
|
"use strict";
|
|
4238
4246
|
SurgeCapability = class {
|
|
4239
4247
|
name = "surge_publish";
|
|
@@ -4265,7 +4273,7 @@ var init_SurgeCapability = __esm({
|
|
|
4265
4273
|
return { success: false, output: `Path does not exist: ${target}`, duration_ms: 0 };
|
|
4266
4274
|
}
|
|
4267
4275
|
let publishDir = target;
|
|
4268
|
-
if (
|
|
4276
|
+
if (statSync2(target).isFile()) {
|
|
4269
4277
|
publishDir = join("/tmp", `surge-${Date.now()}`);
|
|
4270
4278
|
mkdirSync2(publishDir, { recursive: true });
|
|
4271
4279
|
copyFileSync(target, join(publishDir, "index.html"));
|
|
@@ -4307,10 +4315,10 @@ ${out}`,
|
|
|
4307
4315
|
}
|
|
4308
4316
|
});
|
|
4309
4317
|
|
|
4310
|
-
// packages/daemon/src/
|
|
4318
|
+
// packages/daemon/src/tools/BrowserExecuteCapability.ts
|
|
4311
4319
|
var BrowserExecuteCapability;
|
|
4312
4320
|
var init_BrowserExecuteCapability = __esm({
|
|
4313
|
-
"packages/daemon/src/
|
|
4321
|
+
"packages/daemon/src/tools/BrowserExecuteCapability.ts"() {
|
|
4314
4322
|
"use strict";
|
|
4315
4323
|
BrowserExecuteCapability = class {
|
|
4316
4324
|
name = "browser_execute";
|
|
@@ -4584,11 +4592,11 @@ var init_BrowserExecuteCapability = __esm({
|
|
|
4584
4592
|
}
|
|
4585
4593
|
});
|
|
4586
4594
|
|
|
4587
|
-
// packages/daemon/src/
|
|
4595
|
+
// packages/daemon/src/tools/OCRExtractCapability.ts
|
|
4588
4596
|
import { readFileSync as readFileSync3, existsSync as existsSync4 } from "node:fs";
|
|
4589
4597
|
var OCRExtractCapability;
|
|
4590
4598
|
var init_OCRExtractCapability = __esm({
|
|
4591
|
-
"packages/daemon/src/
|
|
4599
|
+
"packages/daemon/src/tools/OCRExtractCapability.ts"() {
|
|
4592
4600
|
"use strict";
|
|
4593
4601
|
OCRExtractCapability = class {
|
|
4594
4602
|
name = "ocr_extract";
|
|
@@ -4747,11 +4755,11 @@ ${JSON.stringify(result.fields, null, 2)}`,
|
|
|
4747
4755
|
}
|
|
4748
4756
|
});
|
|
4749
4757
|
|
|
4750
|
-
// packages/daemon/src/
|
|
4758
|
+
// packages/daemon/src/tools/CredentialVaultCapability.ts
|
|
4751
4759
|
import { randomBytes, createCipheriv, createDecipheriv } from "node:crypto";
|
|
4752
4760
|
var sessionKeys, credStore, CredentialVaultCapability;
|
|
4753
4761
|
var init_CredentialVaultCapability = __esm({
|
|
4754
|
-
"packages/daemon/src/
|
|
4762
|
+
"packages/daemon/src/tools/CredentialVaultCapability.ts"() {
|
|
4755
4763
|
"use strict";
|
|
4756
4764
|
sessionKeys = /* @__PURE__ */ new Map();
|
|
4757
4765
|
credStore = /* @__PURE__ */ new Map();
|
|
@@ -4862,10 +4870,10 @@ var init_CredentialVaultCapability = __esm({
|
|
|
4862
4870
|
}
|
|
4863
4871
|
});
|
|
4864
4872
|
|
|
4865
|
-
// packages/daemon/src/
|
|
4873
|
+
// packages/daemon/src/tools/MonitorWatchCapability.ts
|
|
4866
4874
|
var DAEMON_URL, MonitorWatchCapability;
|
|
4867
4875
|
var init_MonitorWatchCapability = __esm({
|
|
4868
|
-
"packages/daemon/src/
|
|
4876
|
+
"packages/daemon/src/tools/MonitorWatchCapability.ts"() {
|
|
4869
4877
|
"use strict";
|
|
4870
4878
|
DAEMON_URL = "http://localhost:4200";
|
|
4871
4879
|
MonitorWatchCapability = class {
|
|
@@ -5050,10 +5058,10 @@ ${lines.join("\n")}`,
|
|
|
5050
5058
|
}
|
|
5051
5059
|
});
|
|
5052
5060
|
|
|
5053
|
-
// packages/daemon/src/
|
|
5061
|
+
// packages/daemon/src/tools/SessionSearchCapability.ts
|
|
5054
5062
|
var SessionSearchCapability;
|
|
5055
5063
|
var init_SessionSearchCapability = __esm({
|
|
5056
|
-
"packages/daemon/src/
|
|
5064
|
+
"packages/daemon/src/tools/SessionSearchCapability.ts"() {
|
|
5057
5065
|
"use strict";
|
|
5058
5066
|
SessionSearchCapability = class {
|
|
5059
5067
|
name = "session_search";
|
|
@@ -5132,14 +5140,343 @@ ${results.join("\n\n")}`,
|
|
|
5132
5140
|
}
|
|
5133
5141
|
});
|
|
5134
5142
|
|
|
5135
|
-
// packages/daemon/src/
|
|
5143
|
+
// packages/daemon/src/tools/WorktreeCapability.ts
|
|
5144
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
5145
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
5146
|
+
import { resolve as resolve5, basename } from "node:path";
|
|
5147
|
+
var activeWorktrees, WorktreeCapability;
|
|
5148
|
+
var init_WorktreeCapability = __esm({
|
|
5149
|
+
"packages/daemon/src/tools/WorktreeCapability.ts"() {
|
|
5150
|
+
"use strict";
|
|
5151
|
+
activeWorktrees = /* @__PURE__ */ new Map();
|
|
5152
|
+
WorktreeCapability = class {
|
|
5153
|
+
name = "worktree";
|
|
5154
|
+
description = "Create isolated git worktrees for safe parallel branch work.";
|
|
5155
|
+
toolDefinition = {
|
|
5156
|
+
name: "worktree",
|
|
5157
|
+
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.',
|
|
5158
|
+
input_schema: {
|
|
5159
|
+
type: "object",
|
|
5160
|
+
properties: {
|
|
5161
|
+
op: { type: "string", description: "Operation: enter, exit, list" },
|
|
5162
|
+
branch: { type: "string", description: "Branch name for new worktree (enter only). Auto-generated if omitted." },
|
|
5163
|
+
keep: { type: "string", description: 'Set to "true" to keep worktree on exit (default: remove)' },
|
|
5164
|
+
id: { type: "string", description: 'Worktree ID for exit (if multiple active). Use "list" to see IDs.' }
|
|
5165
|
+
},
|
|
5166
|
+
required: ["op"]
|
|
5167
|
+
}
|
|
5168
|
+
};
|
|
5169
|
+
async execute(input, cwd) {
|
|
5170
|
+
const start = Date.now();
|
|
5171
|
+
const op = String(input.op ?? "");
|
|
5172
|
+
switch (op) {
|
|
5173
|
+
case "enter":
|
|
5174
|
+
return this._enter(input, cwd, start);
|
|
5175
|
+
case "exit":
|
|
5176
|
+
return this._exit(input, cwd, start);
|
|
5177
|
+
case "list":
|
|
5178
|
+
return this._list(start);
|
|
5179
|
+
default:
|
|
5180
|
+
return { success: false, output: `Unknown op: ${op}. Use enter, exit, or list.`, duration_ms: 0 };
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
_enter(input, cwd, start) {
|
|
5184
|
+
try {
|
|
5185
|
+
execSync4("git rev-parse --git-dir", { cwd, stdio: "pipe" });
|
|
5186
|
+
} catch {
|
|
5187
|
+
return { success: false, output: "Not in a git repository.", duration_ms: 0 };
|
|
5188
|
+
}
|
|
5189
|
+
const branch = input.branch ? String(input.branch).replace(/[^a-zA-Z0-9\-_\/]/g, "-") : `0agent-wt-${Date.now().toString(36)}`;
|
|
5190
|
+
const repoRoot = execSync4("git rev-parse --show-toplevel", { cwd, encoding: "utf8" }).trim();
|
|
5191
|
+
const worktreePath = resolve5(repoRoot, "..", `${basename(repoRoot)}-${branch}`);
|
|
5192
|
+
if (existsSync5(worktreePath)) {
|
|
5193
|
+
return { success: false, output: `Worktree path already exists: ${worktreePath}`, duration_ms: 0 };
|
|
5194
|
+
}
|
|
5195
|
+
try {
|
|
5196
|
+
execSync4(`git worktree add -b "${branch}" "${worktreePath}"`, { cwd, stdio: "pipe" });
|
|
5197
|
+
const id = `wt-${Date.now().toString(36)}`;
|
|
5198
|
+
activeWorktrees.set(id, { originalCwd: cwd, worktreePath, branch });
|
|
5199
|
+
return {
|
|
5200
|
+
success: true,
|
|
5201
|
+
output: [
|
|
5202
|
+
`Worktree created:`,
|
|
5203
|
+
` ID: ${id}`,
|
|
5204
|
+
` Branch: ${branch}`,
|
|
5205
|
+
` Path: ${worktreePath}`,
|
|
5206
|
+
` Original cwd: ${cwd}`,
|
|
5207
|
+
``,
|
|
5208
|
+
`Switch to the worktree by running commands in: ${worktreePath}`,
|
|
5209
|
+
`When done, call worktree(op:"exit", id:"${id}") to clean up.`
|
|
5210
|
+
].join("\n"),
|
|
5211
|
+
structured: { id, branch, worktreePath, originalCwd: cwd },
|
|
5212
|
+
duration_ms: Date.now() - start
|
|
5213
|
+
};
|
|
5214
|
+
} catch (err) {
|
|
5215
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5216
|
+
return { success: false, output: `Failed to create worktree: ${msg}`, duration_ms: Date.now() - start };
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
_exit(input, _cwd, start) {
|
|
5220
|
+
const id = String(input.id ?? "");
|
|
5221
|
+
const keep = String(input.keep ?? "") === "true";
|
|
5222
|
+
let entry;
|
|
5223
|
+
let entryId = id;
|
|
5224
|
+
if (id) {
|
|
5225
|
+
entry = activeWorktrees.get(id);
|
|
5226
|
+
} else {
|
|
5227
|
+
const keys = [...activeWorktrees.keys()];
|
|
5228
|
+
if (keys.length > 0) {
|
|
5229
|
+
entryId = keys[keys.length - 1];
|
|
5230
|
+
entry = activeWorktrees.get(entryId);
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
if (!entry) {
|
|
5234
|
+
return { success: false, output: id ? `No worktree with ID: ${id}` : "No active worktrees.", duration_ms: 0 };
|
|
5235
|
+
}
|
|
5236
|
+
if (keep) {
|
|
5237
|
+
activeWorktrees.delete(entryId);
|
|
5238
|
+
return {
|
|
5239
|
+
success: true,
|
|
5240
|
+
output: `Worktree kept at: ${entry.worktreePath} (branch: ${entry.branch}). Original cwd: ${entry.originalCwd}`,
|
|
5241
|
+
duration_ms: Date.now() - start
|
|
5242
|
+
};
|
|
5243
|
+
}
|
|
5244
|
+
try {
|
|
5245
|
+
execSync4(`git worktree remove "${entry.worktreePath}" --force`, {
|
|
5246
|
+
cwd: entry.originalCwd,
|
|
5247
|
+
stdio: "pipe"
|
|
5248
|
+
});
|
|
5249
|
+
try {
|
|
5250
|
+
execSync4(`git branch -D "${entry.branch}"`, { cwd: entry.originalCwd, stdio: "pipe" });
|
|
5251
|
+
} catch {
|
|
5252
|
+
}
|
|
5253
|
+
activeWorktrees.delete(entryId);
|
|
5254
|
+
return {
|
|
5255
|
+
success: true,
|
|
5256
|
+
output: `Worktree removed. Branch "${entry.branch}" deleted. Restored to: ${entry.originalCwd}`,
|
|
5257
|
+
duration_ms: Date.now() - start
|
|
5258
|
+
};
|
|
5259
|
+
} catch (err) {
|
|
5260
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5261
|
+
return { success: false, output: `Failed to remove worktree: ${msg}`, duration_ms: Date.now() - start };
|
|
5262
|
+
}
|
|
5263
|
+
}
|
|
5264
|
+
_list(start) {
|
|
5265
|
+
if (activeWorktrees.size === 0) {
|
|
5266
|
+
return { success: true, output: "No active worktrees.", duration_ms: Date.now() - start };
|
|
5267
|
+
}
|
|
5268
|
+
const lines = [...activeWorktrees.entries()].map(
|
|
5269
|
+
([id, wt]) => ` ${id}: ${wt.branch} \u2192 ${wt.worktreePath}`
|
|
5270
|
+
);
|
|
5271
|
+
return {
|
|
5272
|
+
success: true,
|
|
5273
|
+
output: `Active worktrees:
|
|
5274
|
+
${lines.join("\n")}`,
|
|
5275
|
+
structured: [...activeWorktrees.entries()].map(([id, wt]) => ({ id, ...wt })),
|
|
5276
|
+
duration_ms: Date.now() - start
|
|
5277
|
+
};
|
|
5278
|
+
}
|
|
5279
|
+
};
|
|
5280
|
+
}
|
|
5281
|
+
});
|
|
5282
|
+
|
|
5283
|
+
// packages/daemon/src/tools/LSPCapability.ts
|
|
5284
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
5285
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
5286
|
+
import { resolve as resolve6, extname } from "node:path";
|
|
5287
|
+
var LSPCapability;
|
|
5288
|
+
var init_LSPCapability = __esm({
|
|
5289
|
+
"packages/daemon/src/tools/LSPCapability.ts"() {
|
|
5290
|
+
"use strict";
|
|
5291
|
+
LSPCapability = class {
|
|
5292
|
+
name = "lsp";
|
|
5293
|
+
description = "Code intelligence: go-to-definition, find-references, hover, symbols via LSP.";
|
|
5294
|
+
toolDefinition = {
|
|
5295
|
+
name: "lsp",
|
|
5296
|
+
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).',
|
|
5297
|
+
input_schema: {
|
|
5298
|
+
type: "object",
|
|
5299
|
+
properties: {
|
|
5300
|
+
op: { type: "string", description: "Operation: definition, references, hover, symbols" },
|
|
5301
|
+
file: { type: "string", description: "Absolute or relative file path" },
|
|
5302
|
+
line: { type: "string", description: "Line number (1-based) for definition/references/hover" },
|
|
5303
|
+
column: { type: "string", description: "Column number (1-based) for definition/references/hover" },
|
|
5304
|
+
symbol: { type: "string", description: "Symbol name to search for (alternative to line+column \u2014 uses grep to find position)" }
|
|
5305
|
+
},
|
|
5306
|
+
required: ["op", "file"]
|
|
5307
|
+
}
|
|
5308
|
+
};
|
|
5309
|
+
async execute(input, cwd) {
|
|
5310
|
+
const start = Date.now();
|
|
5311
|
+
const op = String(input.op ?? "");
|
|
5312
|
+
let file = String(input.file ?? "");
|
|
5313
|
+
const line = Number(input.line ?? 1) - 1;
|
|
5314
|
+
const column = Number(input.column ?? 1) - 1;
|
|
5315
|
+
const symbol = input.symbol ? String(input.symbol) : void 0;
|
|
5316
|
+
if (!file) return { success: false, output: "file is required", duration_ms: 0 };
|
|
5317
|
+
if (!file.startsWith("/")) file = resolve6(cwd, file);
|
|
5318
|
+
if (!existsSync6(file)) return { success: false, output: `File not found: ${file}`, duration_ms: 0 };
|
|
5319
|
+
let actualLine = line;
|
|
5320
|
+
let actualCol = column;
|
|
5321
|
+
if (symbol) {
|
|
5322
|
+
const pos = this._findSymbolPosition(file, symbol);
|
|
5323
|
+
if (pos) {
|
|
5324
|
+
actualLine = pos.line;
|
|
5325
|
+
actualCol = pos.column;
|
|
5326
|
+
} else {
|
|
5327
|
+
return { success: false, output: `Symbol "${symbol}" not found in ${file}`, duration_ms: Date.now() - start };
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
const ext = extname(file).toLowerCase();
|
|
5331
|
+
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
5332
|
+
return this._tsOperation(op, file, actualLine, actualCol, cwd, start);
|
|
5333
|
+
}
|
|
5334
|
+
return this._grepFallback(op, file, actualLine, actualCol, symbol, cwd, start);
|
|
5335
|
+
}
|
|
5336
|
+
/**
|
|
5337
|
+
* TypeScript/JavaScript operations using tsserver protocol.
|
|
5338
|
+
*/
|
|
5339
|
+
_tsOperation(op, file, line, column, cwd, start) {
|
|
5340
|
+
try {
|
|
5341
|
+
switch (op) {
|
|
5342
|
+
case "definition": {
|
|
5343
|
+
const content = readFileSync4(file, "utf8");
|
|
5344
|
+
const lines = content.split("\n");
|
|
5345
|
+
const targetLine = lines[line] ?? "";
|
|
5346
|
+
const word = this._getWordAt(targetLine, column);
|
|
5347
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5348
|
+
const defPatterns = [
|
|
5349
|
+
`(function|const|let|var|class|interface|type|enum)\\s+${word}\\b`,
|
|
5350
|
+
`${word}\\s*[:=]\\s*(function|\\()`,
|
|
5351
|
+
`export\\s+(default\\s+)?(function|class|const|let|var|type|interface)\\s+${word}`
|
|
5352
|
+
];
|
|
5353
|
+
const results = [];
|
|
5354
|
+
for (const pattern of defPatterns) {
|
|
5355
|
+
try {
|
|
5356
|
+
const grep = execSync5(
|
|
5357
|
+
`rg -n "${pattern}" --type ts --type js "${cwd}" 2>/dev/null | head -10`,
|
|
5358
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5359
|
+
).trim();
|
|
5360
|
+
if (grep) results.push(grep);
|
|
5361
|
+
} catch {
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
5364
|
+
if (!results.length) {
|
|
5365
|
+
return { success: true, output: `No definition found for "${word}"`, duration_ms: Date.now() - start };
|
|
5366
|
+
}
|
|
5367
|
+
return {
|
|
5368
|
+
success: true,
|
|
5369
|
+
output: `Definition of "${word}":
|
|
5370
|
+
${results.join("\n")}`,
|
|
5371
|
+
duration_ms: Date.now() - start
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
case "references": {
|
|
5375
|
+
const content = readFileSync4(file, "utf8");
|
|
5376
|
+
const lines = content.split("\n");
|
|
5377
|
+
const word = this._getWordAt(lines[line] ?? "", column);
|
|
5378
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5379
|
+
try {
|
|
5380
|
+
const grep = execSync5(
|
|
5381
|
+
`rg -n "\\b${word}\\b" --type ts --type js "${cwd}" 2>/dev/null | head -20`,
|
|
5382
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5383
|
+
).trim();
|
|
5384
|
+
const refCount = grep.split("\n").filter(Boolean).length;
|
|
5385
|
+
return {
|
|
5386
|
+
success: true,
|
|
5387
|
+
output: `References to "${word}" (${refCount} found):
|
|
5388
|
+
${grep}`,
|
|
5389
|
+
duration_ms: Date.now() - start
|
|
5390
|
+
};
|
|
5391
|
+
} catch {
|
|
5392
|
+
return { success: true, output: `No references found for "${word}"`, duration_ms: Date.now() - start };
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
case "hover": {
|
|
5396
|
+
const content = readFileSync4(file, "utf8");
|
|
5397
|
+
const lines = content.split("\n");
|
|
5398
|
+
const word = this._getWordAt(lines[line] ?? "", column);
|
|
5399
|
+
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5400
|
+
const surroundingLines = lines.slice(Math.max(0, line - 3), line + 4);
|
|
5401
|
+
return {
|
|
5402
|
+
success: true,
|
|
5403
|
+
output: `Symbol: ${word}
|
|
5404
|
+
Context (${file}:${line + 1}:${column + 1}):
|
|
5405
|
+
${surroundingLines.join("\n")}`,
|
|
5406
|
+
duration_ms: Date.now() - start
|
|
5407
|
+
};
|
|
5408
|
+
}
|
|
5409
|
+
case "symbols": {
|
|
5410
|
+
try {
|
|
5411
|
+
const grep = execSync5(
|
|
5412
|
+
`rg -n "^\\s*(export\\s+)?(function|class|interface|type|enum|const|let|var)\\s+\\w+" "${file}" 2>/dev/null`,
|
|
5413
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5414
|
+
).trim();
|
|
5415
|
+
return {
|
|
5416
|
+
success: true,
|
|
5417
|
+
output: `Symbols in ${file}:
|
|
5418
|
+
${grep || "(no symbols found)"}`,
|
|
5419
|
+
duration_ms: Date.now() - start
|
|
5420
|
+
};
|
|
5421
|
+
} catch {
|
|
5422
|
+
return { success: true, output: `No symbols found in ${file}`, duration_ms: Date.now() - start };
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
default:
|
|
5426
|
+
return { success: false, output: `Unknown op: ${op}`, duration_ms: 0 };
|
|
5427
|
+
}
|
|
5428
|
+
} catch (err) {
|
|
5429
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5430
|
+
return { success: false, output: `LSP operation failed: ${msg}`, duration_ms: Date.now() - start };
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
_grepFallback(op, file, line, column, symbol, cwd, start) {
|
|
5434
|
+
const content = readFileSync4(file, "utf8");
|
|
5435
|
+
const lines = content.split("\n");
|
|
5436
|
+
const word = symbol || this._getWordAt(lines[line] ?? "", column);
|
|
5437
|
+
if (!word) return { success: false, output: "No symbol to search for", duration_ms: 0 };
|
|
5438
|
+
try {
|
|
5439
|
+
const grep = execSync5(
|
|
5440
|
+
`rg -n "\\b${word}\\b" "${cwd}" 2>/dev/null | head -20`,
|
|
5441
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
5442
|
+
).trim();
|
|
5443
|
+
return {
|
|
5444
|
+
success: true,
|
|
5445
|
+
output: `${op} for "${word}" (grep fallback):
|
|
5446
|
+
${grep || "(no results)"}`,
|
|
5447
|
+
duration_ms: Date.now() - start
|
|
5448
|
+
};
|
|
5449
|
+
} catch {
|
|
5450
|
+
return { success: true, output: `No results for "${word}"`, duration_ms: Date.now() - start };
|
|
5451
|
+
}
|
|
5452
|
+
}
|
|
5453
|
+
_findSymbolPosition(file, symbol) {
|
|
5454
|
+
const content = readFileSync4(file, "utf8");
|
|
5455
|
+
const lines = content.split("\n");
|
|
5456
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5457
|
+
const col = lines[i].indexOf(symbol);
|
|
5458
|
+
if (col !== -1) return { line: i, column: col };
|
|
5459
|
+
}
|
|
5460
|
+
return null;
|
|
5461
|
+
}
|
|
5462
|
+
_getWordAt(line, col) {
|
|
5463
|
+
const before = line.slice(0, col + 1).match(/[\w$]+$/)?.[0] ?? "";
|
|
5464
|
+
const after = line.slice(col + 1).match(/^[\w$]*/)?.[0] ?? "";
|
|
5465
|
+
const word = before + after;
|
|
5466
|
+
return word.length > 0 ? word : null;
|
|
5467
|
+
}
|
|
5468
|
+
};
|
|
5469
|
+
}
|
|
5470
|
+
});
|
|
5471
|
+
|
|
5472
|
+
// packages/daemon/src/tools/CodespaceBrowserCapability.ts
|
|
5136
5473
|
var CodespaceBrowserCapability_exports = {};
|
|
5137
5474
|
__export(CodespaceBrowserCapability_exports, {
|
|
5138
5475
|
CodespaceBrowserCapability: () => CodespaceBrowserCapability
|
|
5139
5476
|
});
|
|
5140
5477
|
var CodespaceBrowserCapability;
|
|
5141
5478
|
var init_CodespaceBrowserCapability = __esm({
|
|
5142
|
-
"packages/daemon/src/
|
|
5479
|
+
"packages/daemon/src/tools/CodespaceBrowserCapability.ts"() {
|
|
5143
5480
|
"use strict";
|
|
5144
5481
|
init_BrowserCapability();
|
|
5145
5482
|
CodespaceBrowserCapability = class {
|
|
@@ -5206,10 +5543,10 @@ var init_CodespaceBrowserCapability = __esm({
|
|
|
5206
5543
|
}
|
|
5207
5544
|
});
|
|
5208
5545
|
|
|
5209
|
-
// packages/daemon/src/
|
|
5546
|
+
// packages/daemon/src/tools/CapabilityRegistry.ts
|
|
5210
5547
|
var CapabilityRegistry;
|
|
5211
5548
|
var init_CapabilityRegistry = __esm({
|
|
5212
|
-
"packages/daemon/src/
|
|
5549
|
+
"packages/daemon/src/tools/CapabilityRegistry.ts"() {
|
|
5213
5550
|
"use strict";
|
|
5214
5551
|
init_WebSearchCapability();
|
|
5215
5552
|
init_BrowserCapability();
|
|
@@ -5225,6 +5562,8 @@ var init_CapabilityRegistry = __esm({
|
|
|
5225
5562
|
init_CredentialVaultCapability();
|
|
5226
5563
|
init_MonitorWatchCapability();
|
|
5227
5564
|
init_SessionSearchCapability();
|
|
5565
|
+
init_WorktreeCapability();
|
|
5566
|
+
init_LSPCapability();
|
|
5228
5567
|
CapabilityRegistry = class {
|
|
5229
5568
|
capabilities = /* @__PURE__ */ new Map();
|
|
5230
5569
|
/**
|
|
@@ -5262,6 +5601,8 @@ var init_CapabilityRegistry = __esm({
|
|
|
5262
5601
|
if (dbPath) {
|
|
5263
5602
|
this.register(new SessionSearchCapability(() => dbPath));
|
|
5264
5603
|
}
|
|
5604
|
+
this.register(new WorktreeCapability());
|
|
5605
|
+
this.register(new LSPCapability());
|
|
5265
5606
|
if (graph) {
|
|
5266
5607
|
this.register(new MemoryCapability(graph, onMemoryWrite));
|
|
5267
5608
|
}
|
|
@@ -5302,6 +5643,10 @@ var init_CapabilityRegistry = __esm({
|
|
|
5302
5643
|
active.add("computer_use");
|
|
5303
5644
|
active.add("gui_automation");
|
|
5304
5645
|
}
|
|
5646
|
+
if (/implement|build|write|fix|refactor|debug|test|definition|reference|hover|symbol|branch|worktree|isolat|parallel.*work/i.test(lower)) {
|
|
5647
|
+
active.add("lsp");
|
|
5648
|
+
active.add("worktree");
|
|
5649
|
+
}
|
|
5305
5650
|
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
5651
|
active.add("browser_execute");
|
|
5307
5652
|
active.add("ocr_extract");
|
|
@@ -5332,9 +5677,9 @@ var init_CapabilityRegistry = __esm({
|
|
|
5332
5677
|
}
|
|
5333
5678
|
});
|
|
5334
5679
|
|
|
5335
|
-
// packages/daemon/src/
|
|
5336
|
-
var
|
|
5337
|
-
"packages/daemon/src/
|
|
5680
|
+
// packages/daemon/src/tools/index.ts
|
|
5681
|
+
var init_tools = __esm({
|
|
5682
|
+
"packages/daemon/src/tools/index.ts"() {
|
|
5338
5683
|
"use strict";
|
|
5339
5684
|
init_CapabilityRegistry();
|
|
5340
5685
|
init_WebSearchCapability();
|
|
@@ -5349,13 +5694,15 @@ var init_capabilities = __esm({
|
|
|
5349
5694
|
init_CredentialVaultCapability();
|
|
5350
5695
|
init_MonitorWatchCapability();
|
|
5351
5696
|
init_SessionSearchCapability();
|
|
5697
|
+
init_WorktreeCapability();
|
|
5698
|
+
init_LSPCapability();
|
|
5352
5699
|
}
|
|
5353
5700
|
});
|
|
5354
5701
|
|
|
5355
|
-
// packages/daemon/src/IterationBudget.ts
|
|
5702
|
+
// packages/daemon/src/utils/IterationBudget.ts
|
|
5356
5703
|
var IterationBudget;
|
|
5357
5704
|
var init_IterationBudget = __esm({
|
|
5358
|
-
"packages/daemon/src/IterationBudget.ts"() {
|
|
5705
|
+
"packages/daemon/src/utils/IterationBudget.ts"() {
|
|
5359
5706
|
"use strict";
|
|
5360
5707
|
IterationBudget = class _IterationBudget {
|
|
5361
5708
|
constructor(maxIterations, parent, childAllocation) {
|
|
@@ -5432,7 +5779,7 @@ var init_IterationBudget = __esm({
|
|
|
5432
5779
|
}
|
|
5433
5780
|
});
|
|
5434
5781
|
|
|
5435
|
-
// packages/daemon/src/PromptInjectionScanner.ts
|
|
5782
|
+
// packages/daemon/src/utils/PromptInjectionScanner.ts
|
|
5436
5783
|
function scanForInjection(content, source) {
|
|
5437
5784
|
const warnings = [];
|
|
5438
5785
|
let sanitized = content;
|
|
@@ -5469,7 +5816,7 @@ function sanitizeContextFile(content, filePath, log) {
|
|
|
5469
5816
|
}
|
|
5470
5817
|
var INJECTION_PATTERNS, INVISIBLE_CHARS;
|
|
5471
5818
|
var init_PromptInjectionScanner = __esm({
|
|
5472
|
-
"packages/daemon/src/PromptInjectionScanner.ts"() {
|
|
5819
|
+
"packages/daemon/src/utils/PromptInjectionScanner.ts"() {
|
|
5473
5820
|
"use strict";
|
|
5474
5821
|
INJECTION_PATTERNS = [
|
|
5475
5822
|
// Direct instruction override
|
|
@@ -5495,19 +5842,160 @@ var init_PromptInjectionScanner = __esm({
|
|
|
5495
5842
|
}
|
|
5496
5843
|
});
|
|
5497
5844
|
|
|
5845
|
+
// packages/daemon/src/utils/ContextCollapse.ts
|
|
5846
|
+
function collapseContext(messages, tailKeep = 10) {
|
|
5847
|
+
if (messages.length <= tailKeep) return messages;
|
|
5848
|
+
const cutIndex = messages.length - tailKeep;
|
|
5849
|
+
const prefix = messages.slice(0, cutIndex);
|
|
5850
|
+
const tail = messages.slice(cutIndex);
|
|
5851
|
+
const collapsed = [];
|
|
5852
|
+
for (const msg of prefix) {
|
|
5853
|
+
if (msg.role === "tool") {
|
|
5854
|
+
collapsed.push({
|
|
5855
|
+
...msg,
|
|
5856
|
+
content: collapseToolResult(msg.content, msg.tool_call_id)
|
|
5857
|
+
});
|
|
5858
|
+
} else if (msg.role === "assistant" && msg.tool_calls) {
|
|
5859
|
+
collapsed.push({
|
|
5860
|
+
...msg,
|
|
5861
|
+
content: msg.content.length > 200 ? msg.content.slice(0, 200) + "\u2026" : msg.content
|
|
5862
|
+
});
|
|
5863
|
+
} else {
|
|
5864
|
+
collapsed.push(msg);
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
return [...collapsed, ...tail];
|
|
5868
|
+
}
|
|
5869
|
+
function collapseToolResult(content, toolCallId) {
|
|
5870
|
+
const lineCount = content.split("\n").length;
|
|
5871
|
+
const charCount = content.length;
|
|
5872
|
+
if (charCount <= 200) return content;
|
|
5873
|
+
if (/^(1\t| 1\t|\d+\|)/.test(content)) {
|
|
5874
|
+
const lastLine = content.trim().split("\n").pop() ?? "";
|
|
5875
|
+
const lineNum = lastLine.match(/^(\d+)/)?.[1] ?? String(lineCount);
|
|
5876
|
+
return `[file content: ${lineNum} lines, ${charCount} chars \u2014 collapsed]`;
|
|
5877
|
+
}
|
|
5878
|
+
if (content.startsWith("(no output)") || content.startsWith("exit ")) {
|
|
5879
|
+
return content.slice(0, 100);
|
|
5880
|
+
}
|
|
5881
|
+
if (/^(Error|FAIL|Traceback|SyntaxError|TypeError|ReferenceError)/i.test(content)) {
|
|
5882
|
+
const lines = content.split("\n");
|
|
5883
|
+
return lines.slice(0, 2).join("\n") + (lines.length > 2 ? `
|
|
5884
|
+
[...${lines.length - 2} more lines]` : "");
|
|
5885
|
+
}
|
|
5886
|
+
const fileMatches = content.match(/^[^\n]+:\d+:/gm);
|
|
5887
|
+
if (fileMatches) {
|
|
5888
|
+
const uniqueFiles = new Set(fileMatches.map((m) => m.split(":")[0]));
|
|
5889
|
+
return `[search: ${fileMatches.length} matches in ${uniqueFiles.size} files \u2014 collapsed]`;
|
|
5890
|
+
}
|
|
5891
|
+
if (content.startsWith("{") || content.startsWith("[")) {
|
|
5892
|
+
return `[JSON output: ${charCount} chars \u2014 collapsed]`;
|
|
5893
|
+
}
|
|
5894
|
+
const urlMatch = content.match(/https?:\/\/[^\s]+\.surge\.sh/);
|
|
5895
|
+
if (urlMatch) {
|
|
5896
|
+
return `[published: ${urlMatch[0]}]`;
|
|
5897
|
+
}
|
|
5898
|
+
const firstLine = content.split("\n")[0].slice(0, 100);
|
|
5899
|
+
return `${firstLine}\u2026 [${lineCount} lines, ${charCount} chars \u2014 collapsed]`;
|
|
5900
|
+
}
|
|
5901
|
+
var init_ContextCollapse = __esm({
|
|
5902
|
+
"packages/daemon/src/utils/ContextCollapse.ts"() {
|
|
5903
|
+
"use strict";
|
|
5904
|
+
}
|
|
5905
|
+
});
|
|
5906
|
+
|
|
5907
|
+
// packages/daemon/src/services/StreamingToolExecutor.ts
|
|
5908
|
+
function isPreExecSafe(tc) {
|
|
5909
|
+
if (PRE_EXEC_SAFE.has(tc.name)) return true;
|
|
5910
|
+
if (tc.name === "file_op" && tc.input.op === "read") return true;
|
|
5911
|
+
if (tc.name === "file_op" && tc.input.op === "list") return true;
|
|
5912
|
+
if (tc.name === "ocr_extract") return true;
|
|
5913
|
+
return false;
|
|
5914
|
+
}
|
|
5915
|
+
var PRE_EXEC_SAFE, StreamingToolExecutor;
|
|
5916
|
+
var init_StreamingToolExecutor = __esm({
|
|
5917
|
+
"packages/daemon/src/services/StreamingToolExecutor.ts"() {
|
|
5918
|
+
"use strict";
|
|
5919
|
+
PRE_EXEC_SAFE = /* @__PURE__ */ new Set([
|
|
5920
|
+
"web_search",
|
|
5921
|
+
"scrape_url",
|
|
5922
|
+
"session_search",
|
|
5923
|
+
"lsp"
|
|
5924
|
+
]);
|
|
5925
|
+
StreamingToolExecutor = class {
|
|
5926
|
+
pending = /* @__PURE__ */ new Map();
|
|
5927
|
+
registry;
|
|
5928
|
+
cwd;
|
|
5929
|
+
signal;
|
|
5930
|
+
constructor(registry, cwd, signal) {
|
|
5931
|
+
this.registry = registry;
|
|
5932
|
+
this.cwd = cwd;
|
|
5933
|
+
this.signal = signal;
|
|
5934
|
+
}
|
|
5935
|
+
/**
|
|
5936
|
+
* Called by LLMExecutor's onToolUseBlock callback during streaming.
|
|
5937
|
+
* Starts executing the tool immediately if it's safe to pre-execute.
|
|
5938
|
+
*/
|
|
5939
|
+
onToolBlock(tc) {
|
|
5940
|
+
if (!isPreExecSafe(tc)) return;
|
|
5941
|
+
const promise = this.registry.execute(tc.name, tc.input, this.cwd, this.signal);
|
|
5942
|
+
this.pending.set(tc.id, { promise, toolCall: tc, started: Date.now() });
|
|
5943
|
+
}
|
|
5944
|
+
/**
|
|
5945
|
+
* Get a pre-executed result if available, or execute now.
|
|
5946
|
+
* Returns the result string (same contract as _executeSingleTool).
|
|
5947
|
+
*/
|
|
5948
|
+
async getOrExecute(tc, fallbackExecute) {
|
|
5949
|
+
const pending = this.pending.get(tc.id);
|
|
5950
|
+
if (pending) {
|
|
5951
|
+
try {
|
|
5952
|
+
const capResult = await pending.promise;
|
|
5953
|
+
const MAX_TOOL_OUTPUT = 4e3;
|
|
5954
|
+
let result = capResult.output;
|
|
5955
|
+
if (result.length > MAX_TOOL_OUTPUT) {
|
|
5956
|
+
result = result.slice(0, MAX_TOOL_OUTPUT) + `
|
|
5957
|
+
[...${result.length - MAX_TOOL_OUTPUT} chars truncated]`;
|
|
5958
|
+
}
|
|
5959
|
+
return { result, preExecuted: true };
|
|
5960
|
+
} catch (err) {
|
|
5961
|
+
return { result: `Error: ${err instanceof Error ? err.message : String(err)}`, preExecuted: true };
|
|
5962
|
+
} finally {
|
|
5963
|
+
this.pending.delete(tc.id);
|
|
5964
|
+
}
|
|
5965
|
+
}
|
|
5966
|
+
return { result: await fallbackExecute(), preExecuted: false };
|
|
5967
|
+
}
|
|
5968
|
+
/**
|
|
5969
|
+
* Number of tools currently pre-executing.
|
|
5970
|
+
*/
|
|
5971
|
+
get activeCount() {
|
|
5972
|
+
return this.pending.size;
|
|
5973
|
+
}
|
|
5974
|
+
/**
|
|
5975
|
+
* Cancel all pending pre-executions.
|
|
5976
|
+
*/
|
|
5977
|
+
clear() {
|
|
5978
|
+
this.pending.clear();
|
|
5979
|
+
}
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5982
|
+
});
|
|
5983
|
+
|
|
5498
5984
|
// packages/daemon/src/AgentExecutor.ts
|
|
5499
|
-
import { spawn as
|
|
5500
|
-
import { writeFileSync as writeFileSync4, readFileSync as
|
|
5501
|
-
import { resolve as
|
|
5985
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
5986
|
+
import { writeFileSync as writeFileSync4, readFileSync as readFileSync5, readdirSync as readdirSync2, mkdirSync as mkdirSync3, existsSync as existsSync7 } from "node:fs";
|
|
5987
|
+
import { resolve as resolve7, dirname as dirname2, relative } from "node:path";
|
|
5502
5988
|
import { homedir as homedir2 } from "node:os";
|
|
5503
5989
|
var SELF_MOD_PATTERN, AgentExecutor;
|
|
5504
5990
|
var init_AgentExecutor = __esm({
|
|
5505
5991
|
"packages/daemon/src/AgentExecutor.ts"() {
|
|
5506
5992
|
"use strict";
|
|
5507
5993
|
init_LLMExecutor();
|
|
5508
|
-
|
|
5994
|
+
init_tools();
|
|
5509
5995
|
init_IterationBudget();
|
|
5510
5996
|
init_PromptInjectionScanner();
|
|
5997
|
+
init_ContextCollapse();
|
|
5998
|
+
init_StreamingToolExecutor();
|
|
5511
5999
|
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
6000
|
AgentExecutor = class {
|
|
5513
6001
|
constructor(llm, config, onStep, onToken) {
|
|
@@ -5519,7 +6007,7 @@ var init_AgentExecutor = __esm({
|
|
|
5519
6007
|
this.maxIterations = config.max_iterations ?? 50;
|
|
5520
6008
|
this.maxCommandMs = config.max_command_ms ?? 3e4;
|
|
5521
6009
|
this.agentRoot = config.agent_root;
|
|
5522
|
-
this.registry = new CapabilityRegistry(void 0, config.graph, config.onMemoryWrite);
|
|
6010
|
+
this.registry = new CapabilityRegistry(void 0, config.graph, config.onMemoryWrite, config.dbPath);
|
|
5523
6011
|
if (config.entityNodeId) {
|
|
5524
6012
|
this.registry.setEntityNodeId(config.entityNodeId);
|
|
5525
6013
|
}
|
|
@@ -5572,12 +6060,26 @@ var init_AgentExecutor = __esm({
|
|
|
5572
6060
|
}
|
|
5573
6061
|
this.onStep(i === 0 ? "Thinking\u2026" : "Continuing\u2026");
|
|
5574
6062
|
const estimatedTokens = this._estimateTokens(messages);
|
|
5575
|
-
if (estimatedTokens > contextLimit
|
|
5576
|
-
|
|
6063
|
+
if (estimatedTokens > contextLimit * 0.6) {
|
|
6064
|
+
const before = messages.length;
|
|
6065
|
+
const collapsed = collapseContext(messages, 12);
|
|
6066
|
+
if (collapsed !== messages) {
|
|
6067
|
+
messages.length = 0;
|
|
6068
|
+
messages.push(...collapsed);
|
|
6069
|
+
const afterTokens = this._estimateTokens(messages);
|
|
6070
|
+
if (afterTokens < estimatedTokens * 0.8) {
|
|
6071
|
+
this.onStep(`Context collapsed (${Math.round(estimatedTokens / 1e3)}k \u2192 ${Math.round(afterTokens / 1e3)}k tokens)`);
|
|
6072
|
+
}
|
|
6073
|
+
}
|
|
6074
|
+
}
|
|
6075
|
+
const tokensAfterCollapse = this._estimateTokens(messages);
|
|
6076
|
+
if (tokensAfterCollapse > contextLimit - 16384) {
|
|
6077
|
+
this.onStep(`Compacting context (${Math.round(tokensAfterCollapse / 1e3)}k tokens)\u2026`);
|
|
5577
6078
|
this._compactHistory(messages);
|
|
5578
6079
|
}
|
|
5579
6080
|
let response;
|
|
5580
6081
|
let llmFailed = false;
|
|
6082
|
+
const streamExec = new StreamingToolExecutor(this.registry, this.cwd, signal);
|
|
5581
6083
|
{
|
|
5582
6084
|
let llmRetry = 0;
|
|
5583
6085
|
while (true) {
|
|
@@ -5591,7 +6093,9 @@ var init_AgentExecutor = __esm({
|
|
|
5591
6093
|
this.onToken(token);
|
|
5592
6094
|
finalOutput += token;
|
|
5593
6095
|
},
|
|
5594
|
-
signal
|
|
6096
|
+
signal,
|
|
6097
|
+
// Streaming tool execution: start safe tools as their blocks complete
|
|
6098
|
+
(tc) => streamExec.onToolBlock(tc)
|
|
5595
6099
|
);
|
|
5596
6100
|
break;
|
|
5597
6101
|
} catch (err) {
|
|
@@ -5627,6 +6131,12 @@ var init_AgentExecutor = __esm({
|
|
|
5627
6131
|
totalTokens += response.tokens_used;
|
|
5628
6132
|
totalCost += response.cost_usd;
|
|
5629
6133
|
modelName = response.model;
|
|
6134
|
+
const maxBudget = this.config.max_budget_usd ?? Infinity;
|
|
6135
|
+
if (totalCost >= maxBudget) {
|
|
6136
|
+
this.onStep(`Budget limit reached: $${totalCost.toFixed(4)} \u2265 $${maxBudget} \u2014 stopping session.`);
|
|
6137
|
+
finalOutput = `Session stopped: cost budget of $${maxBudget} exceeded ($${totalCost.toFixed(4)} used).`;
|
|
6138
|
+
break;
|
|
6139
|
+
}
|
|
5630
6140
|
if (response.tool_calls?.some((tc) => !toolSet.find((t) => t.name === tc.name))) {
|
|
5631
6141
|
toolSet = this.registry.getToolDefinitions();
|
|
5632
6142
|
}
|
|
@@ -5644,8 +6154,13 @@ var init_AgentExecutor = __esm({
|
|
|
5644
6154
|
const { parallel, serial } = this._partitionToolCalls(toolCalls);
|
|
5645
6155
|
if (parallel.length > 0) {
|
|
5646
6156
|
const results = await Promise.all(parallel.map(async (tc) => {
|
|
5647
|
-
|
|
5648
|
-
|
|
6157
|
+
const { result, preExecuted } = await streamExec.getOrExecute(
|
|
6158
|
+
tc,
|
|
6159
|
+
() => this._executeSingleTool(tc, signal, filesWritten, commandsRun)
|
|
6160
|
+
);
|
|
6161
|
+
const tag = preExecuted ? " [pre-exec]" : " [parallel]";
|
|
6162
|
+
this.onStep(`\u25B6 ${tc.name}(${this.summariseInput(tc.name, tc.input)})${tag}`);
|
|
6163
|
+
return { tc, result };
|
|
5649
6164
|
}));
|
|
5650
6165
|
for (const { tc, result } of results) {
|
|
5651
6166
|
this.onStep(` \u21B3 ${result.slice(0, 120)}${result.length > 120 ? "\u2026" : ""}`);
|
|
@@ -5653,8 +6168,11 @@ var init_AgentExecutor = __esm({
|
|
|
5653
6168
|
}
|
|
5654
6169
|
}
|
|
5655
6170
|
for (const tc of serial) {
|
|
5656
|
-
|
|
5657
|
-
|
|
6171
|
+
const { result, preExecuted } = await streamExec.getOrExecute(
|
|
6172
|
+
tc,
|
|
6173
|
+
() => this._executeSingleTool(tc, signal, filesWritten, commandsRun)
|
|
6174
|
+
);
|
|
6175
|
+
this.onStep(`\u25B6 ${tc.name}(${this.summariseInput(tc.name, tc.input)})${preExecuted ? " [pre-exec]" : ""}`);
|
|
5658
6176
|
this.onStep(` \u21B3 ${result.slice(0, 120)}${result.length > 120 ? "\u2026" : ""}`);
|
|
5659
6177
|
messages.push({ role: "tool", content: result, tool_call_id: tc.id });
|
|
5660
6178
|
}
|
|
@@ -5700,9 +6218,9 @@ var init_AgentExecutor = __esm({
|
|
|
5700
6218
|
}
|
|
5701
6219
|
}
|
|
5702
6220
|
shellExec(command, timeoutMs) {
|
|
5703
|
-
return new Promise((
|
|
6221
|
+
return new Promise((resolve19) => {
|
|
5704
6222
|
const chunks = [];
|
|
5705
|
-
const proc =
|
|
6223
|
+
const proc = spawn6("bash", ["-c", command], {
|
|
5706
6224
|
cwd: this.cwd,
|
|
5707
6225
|
env: { ...process.env, TERM: "dumb" },
|
|
5708
6226
|
timeout: timeoutMs
|
|
@@ -5711,10 +6229,10 @@ var init_AgentExecutor = __esm({
|
|
|
5711
6229
|
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
5712
6230
|
proc.on("close", (code) => {
|
|
5713
6231
|
const output = chunks.join("").trim();
|
|
5714
|
-
|
|
6232
|
+
resolve19(output || (code === 0 ? "(command completed, no output)" : `exit code ${code}`));
|
|
5715
6233
|
});
|
|
5716
6234
|
proc.on("error", (err) => {
|
|
5717
|
-
|
|
6235
|
+
resolve19(`Error: ${err.message}`);
|
|
5718
6236
|
});
|
|
5719
6237
|
});
|
|
5720
6238
|
}
|
|
@@ -5729,8 +6247,8 @@ var init_AgentExecutor = __esm({
|
|
|
5729
6247
|
readFile(filePath) {
|
|
5730
6248
|
const safe = this.safePath(filePath);
|
|
5731
6249
|
if (!safe) return "Error: path outside working directory";
|
|
5732
|
-
if (!
|
|
5733
|
-
const content =
|
|
6250
|
+
if (!existsSync7(safe)) return `File not found: ${filePath}`;
|
|
6251
|
+
const content = readFileSync5(safe, "utf8");
|
|
5734
6252
|
return content.length > 8e3 ? content.slice(0, 8e3) + `
|
|
5735
6253
|
\u2026[truncated, ${content.length} total bytes]` : content;
|
|
5736
6254
|
}
|
|
@@ -5821,7 +6339,7 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5821
6339
|
listDir(dirPath) {
|
|
5822
6340
|
const safe = this.safePath(dirPath ?? ".");
|
|
5823
6341
|
if (!safe) return "Error: path outside working directory";
|
|
5824
|
-
if (!
|
|
6342
|
+
if (!existsSync7(safe)) return `Directory not found: ${dirPath}`;
|
|
5825
6343
|
try {
|
|
5826
6344
|
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
6345
|
return entries || "(empty directory)";
|
|
@@ -5831,7 +6349,7 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5831
6349
|
}
|
|
5832
6350
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
5833
6351
|
safePath(p) {
|
|
5834
|
-
const resolved =
|
|
6352
|
+
const resolved = resolve7(this.cwd, p);
|
|
5835
6353
|
return resolved.startsWith(this.cwd) ? resolved : null;
|
|
5836
6354
|
}
|
|
5837
6355
|
buildSystemPrompt(extra, task) {
|
|
@@ -5962,15 +6480,15 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
5962
6480
|
);
|
|
5963
6481
|
}
|
|
5964
6482
|
const agentsFiles = [
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
6483
|
+
resolve7(this.cwd, "AGENTS.md"),
|
|
6484
|
+
resolve7(this.cwd, ".0agent", "AGENTS.md"),
|
|
6485
|
+
resolve7(this.cwd, "CLAUDE.md"),
|
|
6486
|
+
resolve7(homedir2(), ".0agent", "AGENTS.md")
|
|
5969
6487
|
];
|
|
5970
6488
|
for (const f of agentsFiles) {
|
|
5971
6489
|
try {
|
|
5972
|
-
if (
|
|
5973
|
-
const content =
|
|
6490
|
+
if (existsSync7(f)) {
|
|
6491
|
+
const content = readFileSync5(f, "utf8").trim();
|
|
5974
6492
|
if (content && content.length < 4e3) {
|
|
5975
6493
|
const sanitized = sanitizeContextFile(content, f);
|
|
5976
6494
|
lines.push(``, `Project instructions:`, sanitized);
|
|
@@ -6084,6 +6602,9 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
6084
6602
|
async _executeSingleTool(tc, signal, filesWritten, commandsRun) {
|
|
6085
6603
|
let result;
|
|
6086
6604
|
try {
|
|
6605
|
+
if (!tc.input || Object.keys(tc.input).length === 0) {
|
|
6606
|
+
return `Error: empty tool input for ${tc.name}. Provide required parameters.`;
|
|
6607
|
+
}
|
|
6087
6608
|
const capResult = await this.registry.execute(tc.name, tc.input, this.cwd, signal);
|
|
6088
6609
|
result = capResult.output;
|
|
6089
6610
|
const MAX_TOOL_OUTPUT = 4e3;
|
|
@@ -6152,8 +6673,8 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
6152
6673
|
});
|
|
6153
6674
|
|
|
6154
6675
|
// packages/daemon/src/ExecutionVerifier.ts
|
|
6155
|
-
import { existsSync as
|
|
6156
|
-
import { resolve as
|
|
6676
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
6677
|
+
import { resolve as resolve8 } from "node:path";
|
|
6157
6678
|
var ExecutionVerifier;
|
|
6158
6679
|
var init_ExecutionVerifier = __esm({
|
|
6159
6680
|
"packages/daemon/src/ExecutionVerifier.ts"() {
|
|
@@ -6190,8 +6711,8 @@ var init_ExecutionVerifier = __esm({
|
|
|
6190
6711
|
};
|
|
6191
6712
|
}
|
|
6192
6713
|
if (files.length > 0) {
|
|
6193
|
-
const lastFile =
|
|
6194
|
-
const exists =
|
|
6714
|
+
const lastFile = resolve8(this.cwd, files[files.length - 1]);
|
|
6715
|
+
const exists = existsSync9(lastFile);
|
|
6195
6716
|
return {
|
|
6196
6717
|
success: exists,
|
|
6197
6718
|
method: "file_exists",
|
|
@@ -6230,10 +6751,10 @@ var init_ExecutionVerifier = __esm({
|
|
|
6230
6751
|
});
|
|
6231
6752
|
|
|
6232
6753
|
// packages/daemon/src/RuntimeSelfHeal.ts
|
|
6233
|
-
import { readFileSync as
|
|
6234
|
-
import { resolve as
|
|
6754
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "node:fs";
|
|
6755
|
+
import { resolve as resolve9, dirname as dirname3 } from "node:path";
|
|
6235
6756
|
import { fileURLToPath } from "node:url";
|
|
6236
|
-
import { execSync as
|
|
6757
|
+
import { execSync as execSync7, spawn as spawn7 } from "node:child_process";
|
|
6237
6758
|
function isRuntimeBug(error) {
|
|
6238
6759
|
if (TASK_FAILURE_PATTERNS.some((p) => p.test(error))) return false;
|
|
6239
6760
|
return RUNTIME_BUG_PATTERNS.some((p) => p.test(error));
|
|
@@ -6257,8 +6778,8 @@ function parseStackTrace(stack) {
|
|
|
6257
6778
|
}
|
|
6258
6779
|
function extractContext(filePath, errorLine, contextLines = 30) {
|
|
6259
6780
|
try {
|
|
6260
|
-
if (!
|
|
6261
|
-
const content =
|
|
6781
|
+
if (!existsSync10(filePath)) return null;
|
|
6782
|
+
const content = readFileSync7(filePath, "utf8");
|
|
6262
6783
|
const lines = content.split("\n");
|
|
6263
6784
|
const start = Math.max(0, errorLine - contextLines);
|
|
6264
6785
|
const end = Math.min(lines.length, errorLine + contextLines);
|
|
@@ -6303,8 +6824,8 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6303
6824
|
this.llm = llm;
|
|
6304
6825
|
this.eventBus = eventBus;
|
|
6305
6826
|
let dir = dirname3(fileURLToPath(import.meta.url));
|
|
6306
|
-
while (dir !== "/" && !
|
|
6307
|
-
dir =
|
|
6827
|
+
while (dir !== "/" && !existsSync10(resolve9(dir, "package.json"))) {
|
|
6828
|
+
dir = resolve9(dir, "..");
|
|
6308
6829
|
}
|
|
6309
6830
|
this.projectRoot = dir;
|
|
6310
6831
|
}
|
|
@@ -6340,7 +6861,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6340
6861
|
*/
|
|
6341
6862
|
async applyPatch(proposal) {
|
|
6342
6863
|
const tsPath = this.findSourceFile(proposal.location);
|
|
6343
|
-
if (!tsPath || !
|
|
6864
|
+
if (!tsPath || !existsSync10(tsPath)) {
|
|
6344
6865
|
return {
|
|
6345
6866
|
applied: false,
|
|
6346
6867
|
restarted: false,
|
|
@@ -6348,7 +6869,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6348
6869
|
};
|
|
6349
6870
|
}
|
|
6350
6871
|
try {
|
|
6351
|
-
const original =
|
|
6872
|
+
const original = readFileSync7(tsPath, "utf8");
|
|
6352
6873
|
const backup = tsPath + ".bak";
|
|
6353
6874
|
writeFileSync5(backup, original, "utf8");
|
|
6354
6875
|
if (!original.includes(proposal.original_code.trim())) {
|
|
@@ -6360,10 +6881,10 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6360
6881
|
}
|
|
6361
6882
|
const patched = original.replace(proposal.original_code, proposal.proposed_code);
|
|
6362
6883
|
writeFileSync5(tsPath, patched, "utf8");
|
|
6363
|
-
const bundleScript =
|
|
6364
|
-
if (
|
|
6884
|
+
const bundleScript = resolve9(this.projectRoot, "scripts", "bundle.mjs");
|
|
6885
|
+
if (existsSync10(bundleScript)) {
|
|
6365
6886
|
try {
|
|
6366
|
-
|
|
6887
|
+
execSync7(`node "${bundleScript}"`, {
|
|
6367
6888
|
cwd: this.projectRoot,
|
|
6368
6889
|
timeout: 6e4,
|
|
6369
6890
|
stdio: "ignore"
|
|
@@ -6394,14 +6915,14 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6394
6915
|
// ─── Private helpers ───────────────────────────────────────────────────────
|
|
6395
6916
|
findSourceFile(location) {
|
|
6396
6917
|
const candidates = [
|
|
6397
|
-
|
|
6918
|
+
resolve9(this.projectRoot, location.relPath),
|
|
6398
6919
|
// If relPath starts with dist/, look in src/
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6920
|
+
resolve9(this.projectRoot, location.relPath.replace(/^dist\//, "src/").replace(/\.js$/, ".ts")),
|
|
6921
|
+
resolve9(this.projectRoot, "packages", "daemon", "src", location.relPath.replace(/.*src\//, "")),
|
|
6922
|
+
resolve9(this.projectRoot, "packages", "core", "src", location.relPath.replace(/.*src\//, ""))
|
|
6402
6923
|
];
|
|
6403
6924
|
for (const p of candidates) {
|
|
6404
|
-
if (
|
|
6925
|
+
if (existsSync10(p)) return p;
|
|
6405
6926
|
}
|
|
6406
6927
|
return null;
|
|
6407
6928
|
}
|
|
@@ -6466,9 +6987,9 @@ Rules:
|
|
|
6466
6987
|
}
|
|
6467
6988
|
}
|
|
6468
6989
|
restartDaemon() {
|
|
6469
|
-
const bundlePath =
|
|
6470
|
-
if (
|
|
6471
|
-
const child =
|
|
6990
|
+
const bundlePath = resolve9(this.projectRoot, "dist", "daemon.mjs");
|
|
6991
|
+
if (existsSync10(bundlePath)) {
|
|
6992
|
+
const child = spawn7(process.execPath, [bundlePath], {
|
|
6472
6993
|
detached: true,
|
|
6473
6994
|
stdio: "ignore",
|
|
6474
6995
|
env: process.env
|
|
@@ -6566,14 +7087,14 @@ var init_SelfHealLoop = __esm({
|
|
|
6566
7087
|
}
|
|
6567
7088
|
});
|
|
6568
7089
|
|
|
6569
|
-
// packages/daemon/src/ProactiveSurface.ts
|
|
7090
|
+
// packages/daemon/src/tasks/ProactiveSurface.ts
|
|
6570
7091
|
var ProactiveSurface_exports = {};
|
|
6571
7092
|
__export(ProactiveSurface_exports, {
|
|
6572
7093
|
ProactiveSurface: () => ProactiveSurface
|
|
6573
7094
|
});
|
|
6574
|
-
import { execSync as
|
|
6575
|
-
import { existsSync as
|
|
6576
|
-
import { resolve as
|
|
7095
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
7096
|
+
import { existsSync as existsSync20, readFileSync as readFileSync16, statSync as statSync3, readdirSync as readdirSync5 } from "node:fs";
|
|
7097
|
+
import { resolve as resolve16, join as join7 } from "node:path";
|
|
6577
7098
|
function readdirSafe(dir) {
|
|
6578
7099
|
try {
|
|
6579
7100
|
return readdirSync5(dir);
|
|
@@ -6583,7 +7104,7 @@ function readdirSafe(dir) {
|
|
|
6583
7104
|
}
|
|
6584
7105
|
var ProactiveSurface;
|
|
6585
7106
|
var init_ProactiveSurface = __esm({
|
|
6586
|
-
"packages/daemon/src/ProactiveSurface.ts"() {
|
|
7107
|
+
"packages/daemon/src/tasks/ProactiveSurface.ts"() {
|
|
6587
7108
|
"use strict";
|
|
6588
7109
|
init_src();
|
|
6589
7110
|
ProactiveSurface = class {
|
|
@@ -6622,7 +7143,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6622
7143
|
return [...this.insights];
|
|
6623
7144
|
}
|
|
6624
7145
|
async poll() {
|
|
6625
|
-
if (!
|
|
7146
|
+
if (!existsSync20(resolve16(this.cwd, ".git"))) return;
|
|
6626
7147
|
const newInsights = [];
|
|
6627
7148
|
const gitInsight = this.checkGitActivity();
|
|
6628
7149
|
if (gitInsight) newInsights.push(gitInsight);
|
|
@@ -6640,7 +7161,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6640
7161
|
try {
|
|
6641
7162
|
const currentHead = this.getGitHead();
|
|
6642
7163
|
if (!currentHead || currentHead === this.lastKnownHead) return null;
|
|
6643
|
-
const log =
|
|
7164
|
+
const log = execSync10(
|
|
6644
7165
|
`git log ${this.lastKnownHead}..${currentHead} --oneline --stat`,
|
|
6645
7166
|
{ cwd: this.cwd, timeout: 3e3, encoding: "utf8" }
|
|
6646
7167
|
).trim();
|
|
@@ -6666,13 +7187,13 @@ var init_ProactiveSurface = __esm({
|
|
|
6666
7187
|
];
|
|
6667
7188
|
for (const dir of outputPaths) {
|
|
6668
7189
|
try {
|
|
6669
|
-
if (!
|
|
7190
|
+
if (!existsSync20(dir)) continue;
|
|
6670
7191
|
const xmlFiles = readdirSafe(dir).filter((f) => f.endsWith(".xml"));
|
|
6671
7192
|
for (const xml of xmlFiles) {
|
|
6672
7193
|
const path = join7(dir, xml);
|
|
6673
|
-
const stat =
|
|
7194
|
+
const stat = statSync3(path);
|
|
6674
7195
|
if (stat.mtimeMs < this.lastPollAt) continue;
|
|
6675
|
-
const content =
|
|
7196
|
+
const content = readFileSync16(path, "utf8");
|
|
6676
7197
|
const failures = [...content.matchAll(/<failure[^>]*message="([^"]+)"/g)].length;
|
|
6677
7198
|
if (failures > 0) {
|
|
6678
7199
|
return this.makeInsight(
|
|
@@ -6716,7 +7237,7 @@ var init_ProactiveSurface = __esm({
|
|
|
6716
7237
|
}
|
|
6717
7238
|
getGitHead() {
|
|
6718
7239
|
try {
|
|
6719
|
-
return
|
|
7240
|
+
return execSync10("git rev-parse HEAD", { cwd: this.cwd, timeout: 1e3, encoding: "utf8" }).trim();
|
|
6720
7241
|
} catch {
|
|
6721
7242
|
return "";
|
|
6722
7243
|
}
|
|
@@ -6727,8 +7248,8 @@ var init_ProactiveSurface = __esm({
|
|
|
6727
7248
|
|
|
6728
7249
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
6729
7250
|
init_src();
|
|
6730
|
-
import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, existsSync as
|
|
6731
|
-
import { resolve as
|
|
7251
|
+
import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync17 } from "node:fs";
|
|
7252
|
+
import { resolve as resolve17 } from "node:path";
|
|
6732
7253
|
import { homedir as homedir9 } from "node:os";
|
|
6733
7254
|
|
|
6734
7255
|
// packages/daemon/src/config/DaemonConfig.ts
|
|
@@ -6926,7 +7447,7 @@ ${issues}`);
|
|
|
6926
7447
|
// packages/daemon/src/SessionManager.ts
|
|
6927
7448
|
init_src();
|
|
6928
7449
|
|
|
6929
|
-
// packages/daemon/src/EntityScopedContext.ts
|
|
7450
|
+
// packages/daemon/src/utils/EntityScopedContext.ts
|
|
6930
7451
|
init_src();
|
|
6931
7452
|
var EntityScopedContextLoader = class {
|
|
6932
7453
|
constructor(graph) {
|
|
@@ -7003,7 +7524,7 @@ var EntityScopedContextLoader = class {
|
|
|
7003
7524
|
init_LLMExecutor();
|
|
7004
7525
|
init_AgentExecutor();
|
|
7005
7526
|
|
|
7006
|
-
// packages/daemon/src/AnthropicSkillFetcher.ts
|
|
7527
|
+
// packages/daemon/src/services/AnthropicSkillFetcher.ts
|
|
7007
7528
|
var BASE_URL = "https://raw.githubusercontent.com/anthropics/skills/main";
|
|
7008
7529
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
7009
7530
|
var ANTHROPIC_SKILLS = [
|
|
@@ -7122,9 +7643,9 @@ var AnthropicSkillFetcher = class {
|
|
|
7122
7643
|
}
|
|
7123
7644
|
};
|
|
7124
7645
|
|
|
7125
|
-
// packages/daemon/src/ProjectScanner.ts
|
|
7126
|
-
import { execSync as
|
|
7127
|
-
import { readFileSync as
|
|
7646
|
+
// packages/daemon/src/utils/ProjectScanner.ts
|
|
7647
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
7648
|
+
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "node:fs";
|
|
7128
7649
|
import { join as join2 } from "node:path";
|
|
7129
7650
|
import { createServer } from "node:net";
|
|
7130
7651
|
var PORTS_TO_CHECK = [3e3, 3001, 4e3, 4200, 5e3, 5173, 8e3, 8080, 8888];
|
|
@@ -7173,13 +7694,13 @@ var ProjectScanner = class {
|
|
|
7173
7694
|
const stack = [];
|
|
7174
7695
|
let name = "";
|
|
7175
7696
|
const pkgPath = join2(this.cwd, "package.json");
|
|
7176
|
-
if (
|
|
7697
|
+
if (existsSync8(pkgPath)) {
|
|
7177
7698
|
try {
|
|
7178
|
-
const pkg = JSON.parse(
|
|
7699
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
7179
7700
|
name = pkg.name ?? "";
|
|
7180
7701
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
7181
7702
|
stack.push("node");
|
|
7182
|
-
if (deps.typescript ||
|
|
7703
|
+
if (deps.typescript || existsSync8(join2(this.cwd, "tsconfig.json"))) stack.push("typescript");
|
|
7183
7704
|
if (deps.react) stack.push("react");
|
|
7184
7705
|
if (deps.vue) stack.push("vue");
|
|
7185
7706
|
if (deps.svelte) stack.push("svelte");
|
|
@@ -7188,24 +7709,24 @@ var ProjectScanner = class {
|
|
|
7188
7709
|
} catch {
|
|
7189
7710
|
}
|
|
7190
7711
|
}
|
|
7191
|
-
if (
|
|
7712
|
+
if (existsSync8(join2(this.cwd, "Cargo.toml"))) {
|
|
7192
7713
|
stack.push("rust");
|
|
7193
7714
|
try {
|
|
7194
|
-
const cargo =
|
|
7715
|
+
const cargo = readFileSync6(join2(this.cwd, "Cargo.toml"), "utf8");
|
|
7195
7716
|
const nameMatch = cargo.match(/^name\s*=\s*"([^"]+)"/m);
|
|
7196
7717
|
if (nameMatch && !name) name = nameMatch[1];
|
|
7197
7718
|
} catch {
|
|
7198
7719
|
}
|
|
7199
7720
|
}
|
|
7200
|
-
if (
|
|
7721
|
+
if (existsSync8(join2(this.cwd, "pyproject.toml")) || existsSync8(join2(this.cwd, "requirements.txt"))) {
|
|
7201
7722
|
stack.push("python");
|
|
7202
7723
|
}
|
|
7203
|
-
if (
|
|
7724
|
+
if (existsSync8(join2(this.cwd, "go.mod"))) stack.push("go");
|
|
7204
7725
|
return [stack, name];
|
|
7205
7726
|
}
|
|
7206
7727
|
getRecentCommits() {
|
|
7207
7728
|
try {
|
|
7208
|
-
const out =
|
|
7729
|
+
const out = execSync6("git log --oneline -5 2>/dev/null", {
|
|
7209
7730
|
cwd: this.cwd,
|
|
7210
7731
|
timeout: 3e3,
|
|
7211
7732
|
encoding: "utf8"
|
|
@@ -7217,7 +7738,7 @@ var ProjectScanner = class {
|
|
|
7217
7738
|
}
|
|
7218
7739
|
getDirtyFiles() {
|
|
7219
7740
|
try {
|
|
7220
|
-
const out =
|
|
7741
|
+
const out = execSync6("git status --short 2>/dev/null", {
|
|
7221
7742
|
cwd: this.cwd,
|
|
7222
7743
|
timeout: 3e3,
|
|
7223
7744
|
encoding: "utf8"
|
|
@@ -7230,19 +7751,19 @@ var ProjectScanner = class {
|
|
|
7230
7751
|
async getRunningPorts() {
|
|
7231
7752
|
const open = [];
|
|
7232
7753
|
await Promise.all(PORTS_TO_CHECK.map(
|
|
7233
|
-
(port) => new Promise((
|
|
7754
|
+
(port) => new Promise((resolve19) => {
|
|
7234
7755
|
const s = createServer();
|
|
7235
7756
|
s.listen(port, "127.0.0.1", () => {
|
|
7236
7757
|
s.close();
|
|
7237
|
-
|
|
7758
|
+
resolve19();
|
|
7238
7759
|
});
|
|
7239
7760
|
s.on("error", () => {
|
|
7240
7761
|
open.push(port);
|
|
7241
|
-
|
|
7762
|
+
resolve19();
|
|
7242
7763
|
});
|
|
7243
7764
|
setTimeout(() => {
|
|
7244
7765
|
s.close();
|
|
7245
|
-
|
|
7766
|
+
resolve19();
|
|
7246
7767
|
}, 200);
|
|
7247
7768
|
})
|
|
7248
7769
|
));
|
|
@@ -7251,9 +7772,9 @@ var ProjectScanner = class {
|
|
|
7251
7772
|
getReadmeSummary() {
|
|
7252
7773
|
for (const name of ["README.md", "readme.md", "README.txt", "README"]) {
|
|
7253
7774
|
const p = join2(this.cwd, name);
|
|
7254
|
-
if (
|
|
7775
|
+
if (existsSync8(p)) {
|
|
7255
7776
|
try {
|
|
7256
|
-
return
|
|
7777
|
+
return readFileSync6(p, "utf8").slice(0, 300).replace(/\n+/g, " ").trim();
|
|
7257
7778
|
} catch {
|
|
7258
7779
|
}
|
|
7259
7780
|
}
|
|
@@ -7262,7 +7783,7 @@ var ProjectScanner = class {
|
|
|
7262
7783
|
}
|
|
7263
7784
|
};
|
|
7264
7785
|
|
|
7265
|
-
// packages/daemon/src/ConversationStore.ts
|
|
7786
|
+
// packages/daemon/src/services/ConversationStore.ts
|
|
7266
7787
|
var CREATE_TABLE = `
|
|
7267
7788
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
7268
7789
|
id TEXT PRIMARY KEY,
|
|
@@ -7317,7 +7838,7 @@ var ConversationStore = class {
|
|
|
7317
7838
|
}
|
|
7318
7839
|
};
|
|
7319
7840
|
|
|
7320
|
-
// packages/daemon/src/SmartModelRouter.ts
|
|
7841
|
+
// packages/daemon/src/services/SmartModelRouter.ts
|
|
7321
7842
|
var COMPLEX_PATTERNS = [
|
|
7322
7843
|
// Code-related
|
|
7323
7844
|
/\b(implement|build|write|fix|refactor|debug|test|deploy|compile|lint|bundle|migrate)\b/i,
|
|
@@ -7387,9 +7908,130 @@ function getFastModelId(provider, _currentModel) {
|
|
|
7387
7908
|
}
|
|
7388
7909
|
}
|
|
7389
7910
|
|
|
7911
|
+
// packages/daemon/src/services/AutoMemoryExtractor.ts
|
|
7912
|
+
init_src();
|
|
7913
|
+
var state = {
|
|
7914
|
+
lastMessageIndex: 0,
|
|
7915
|
+
inProgress: false,
|
|
7916
|
+
pendingRun: false,
|
|
7917
|
+
turnsSinceExtraction: 0
|
|
7918
|
+
};
|
|
7919
|
+
var MIN_TURNS_BETWEEN = 3;
|
|
7920
|
+
var MAX_MESSAGES_PER_RUN = 20;
|
|
7921
|
+
var AutoMemoryExtractor = class {
|
|
7922
|
+
constructor(llm, graph, entityNodeId) {
|
|
7923
|
+
this.llm = llm;
|
|
7924
|
+
this.graph = graph;
|
|
7925
|
+
this.entityNodeId = entityNodeId;
|
|
7926
|
+
}
|
|
7927
|
+
/**
|
|
7928
|
+
* Called after each session turn. Decides whether to extract memories
|
|
7929
|
+
* and runs extraction in the background if needed.
|
|
7930
|
+
*
|
|
7931
|
+
* Fire-and-forget — never blocks the main session.
|
|
7932
|
+
*/
|
|
7933
|
+
async maybeExtract(messages, memoryWritesSinceLast) {
|
|
7934
|
+
state.turnsSinceExtraction++;
|
|
7935
|
+
if (memoryWritesSinceLast) {
|
|
7936
|
+
state.turnsSinceExtraction = 0;
|
|
7937
|
+
return;
|
|
7938
|
+
}
|
|
7939
|
+
if (state.turnsSinceExtraction < MIN_TURNS_BETWEEN) return;
|
|
7940
|
+
if (messages.length <= state.lastMessageIndex) return;
|
|
7941
|
+
if (state.inProgress) {
|
|
7942
|
+
state.pendingRun = true;
|
|
7943
|
+
return;
|
|
7944
|
+
}
|
|
7945
|
+
await this._runExtraction(messages);
|
|
7946
|
+
if (state.pendingRun) {
|
|
7947
|
+
state.pendingRun = false;
|
|
7948
|
+
await this._runExtraction(messages);
|
|
7949
|
+
}
|
|
7950
|
+
}
|
|
7951
|
+
async _runExtraction(messages) {
|
|
7952
|
+
if (!this.llm?.isConfigured) return;
|
|
7953
|
+
state.inProgress = true;
|
|
7954
|
+
try {
|
|
7955
|
+
const newMessages = messages.slice(
|
|
7956
|
+
state.lastMessageIndex,
|
|
7957
|
+
state.lastMessageIndex + MAX_MESSAGES_PER_RUN
|
|
7958
|
+
);
|
|
7959
|
+
if (newMessages.length === 0) return;
|
|
7960
|
+
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");
|
|
7961
|
+
if (conversationText.length < 50) return;
|
|
7962
|
+
const prompt = [
|
|
7963
|
+
"Extract any durable facts from this conversation that are worth remembering across sessions.",
|
|
7964
|
+
"Focus on: user preferences, project decisions, tool configurations, recurring patterns, names, roles.",
|
|
7965
|
+
"Do NOT extract: greetings, transient task details, things already obvious from the code.",
|
|
7966
|
+
"",
|
|
7967
|
+
'Return a JSON array of facts. Each fact: {"label":"snake_case_key","content":"value","type":"identity|tech|preference|project|outcome"}',
|
|
7968
|
+
"Return [] if nothing worth extracting.",
|
|
7969
|
+
"",
|
|
7970
|
+
"Conversation:",
|
|
7971
|
+
conversationText
|
|
7972
|
+
].join("\n");
|
|
7973
|
+
const resp = await this.llm.complete(
|
|
7974
|
+
[{ role: "user", content: prompt }],
|
|
7975
|
+
"You extract durable facts from conversations. Return ONLY a JSON array. No explanation."
|
|
7976
|
+
);
|
|
7977
|
+
const text = resp.content.trim();
|
|
7978
|
+
const jsonMatch = text.match(/\[[\s\S]*\]/);
|
|
7979
|
+
if (!jsonMatch) return;
|
|
7980
|
+
let facts;
|
|
7981
|
+
try {
|
|
7982
|
+
facts = JSON.parse(jsonMatch[0]);
|
|
7983
|
+
} catch {
|
|
7984
|
+
return;
|
|
7985
|
+
}
|
|
7986
|
+
if (!Array.isArray(facts) || facts.length === 0) return;
|
|
7987
|
+
for (const fact of facts.slice(0, 5)) {
|
|
7988
|
+
if (!fact.label || !fact.content) continue;
|
|
7989
|
+
const nodeId = `memory:${fact.label}`;
|
|
7990
|
+
const existing = this.graph.getNode(nodeId);
|
|
7991
|
+
if (existing) {
|
|
7992
|
+
this.graph.updateNode(nodeId, {
|
|
7993
|
+
metadata: {
|
|
7994
|
+
...existing.metadata,
|
|
7995
|
+
content: fact.content,
|
|
7996
|
+
type: fact.type || "note",
|
|
7997
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7998
|
+
}
|
|
7999
|
+
});
|
|
8000
|
+
} else {
|
|
8001
|
+
const node = createNode({
|
|
8002
|
+
id: nodeId,
|
|
8003
|
+
graph_id: "root",
|
|
8004
|
+
label: fact.label,
|
|
8005
|
+
type: "context" /* CONTEXT */,
|
|
8006
|
+
metadata: {
|
|
8007
|
+
content: fact.content,
|
|
8008
|
+
type: fact.type || "note",
|
|
8009
|
+
saved_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8010
|
+
source: "auto_extract"
|
|
8011
|
+
}
|
|
8012
|
+
});
|
|
8013
|
+
this.graph.addNode(node);
|
|
8014
|
+
}
|
|
8015
|
+
}
|
|
8016
|
+
state.lastMessageIndex = messages.length;
|
|
8017
|
+
state.turnsSinceExtraction = 0;
|
|
8018
|
+
} catch {
|
|
8019
|
+
} finally {
|
|
8020
|
+
state.inProgress = false;
|
|
8021
|
+
}
|
|
8022
|
+
}
|
|
8023
|
+
/** Reset state (e.g., on new session). */
|
|
8024
|
+
reset() {
|
|
8025
|
+
state.lastMessageIndex = 0;
|
|
8026
|
+
state.inProgress = false;
|
|
8027
|
+
state.pendingRun = false;
|
|
8028
|
+
state.turnsSinceExtraction = 0;
|
|
8029
|
+
}
|
|
8030
|
+
};
|
|
8031
|
+
|
|
7390
8032
|
// packages/daemon/src/SessionManager.ts
|
|
7391
|
-
import { readFileSync as
|
|
7392
|
-
import { resolve as
|
|
8033
|
+
import { readFileSync as readFileSync8, existsSync as existsSync11 } from "node:fs";
|
|
8034
|
+
import { resolve as resolve10 } from "node:path";
|
|
7393
8035
|
import { homedir as homedir3 } from "node:os";
|
|
7394
8036
|
import YAML2 from "yaml";
|
|
7395
8037
|
var SessionManager = class {
|
|
@@ -7782,6 +8424,15 @@ Current task:`;
|
|
|
7782
8424
|
this._extractAndPersistFacts(enrichedReq.task, agentResult.output, activeLLM, userEntityId).catch((err) => {
|
|
7783
8425
|
console.warn("[0agent] Memory extraction outer error:", err instanceof Error ? err.message : err);
|
|
7784
8426
|
});
|
|
8427
|
+
if (this.graph && activeLLM) {
|
|
8428
|
+
const extractor = new AutoMemoryExtractor(activeLLM, this.graph, userEntityId);
|
|
8429
|
+
extractor.maybeExtract(
|
|
8430
|
+
[{ role: "user", content: enrichedReq.task }, { role: "assistant", content: agentResult.output }],
|
|
8431
|
+
false
|
|
8432
|
+
// memoryWritesSinceLast — checked inside extractor
|
|
8433
|
+
).catch(() => {
|
|
8434
|
+
});
|
|
8435
|
+
}
|
|
7785
8436
|
this.completeSession(sessionId, {
|
|
7786
8437
|
output: agentResult.output,
|
|
7787
8438
|
files_written: agentResult.files_written,
|
|
@@ -7790,7 +8441,7 @@ Current task:`;
|
|
|
7790
8441
|
model: agentResult.model
|
|
7791
8442
|
});
|
|
7792
8443
|
} else {
|
|
7793
|
-
const cfgPath =
|
|
8444
|
+
const cfgPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
7794
8445
|
const output = `No LLM API key found. Add one to ${cfgPath} or run: 0agent init`;
|
|
7795
8446
|
this.addStep(sessionId, "\u26A0 No LLM API key configured \u2014 run: 0agent init");
|
|
7796
8447
|
this.completeSession(sessionId, { output });
|
|
@@ -7833,9 +8484,9 @@ Current task:`;
|
|
|
7833
8484
|
*/
|
|
7834
8485
|
getFreshLLM() {
|
|
7835
8486
|
try {
|
|
7836
|
-
const configPath =
|
|
7837
|
-
if (!
|
|
7838
|
-
const raw =
|
|
8487
|
+
const configPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
8488
|
+
if (!existsSync11(configPath)) return this.llm;
|
|
8489
|
+
const raw = readFileSync8(configPath, "utf8");
|
|
7839
8490
|
const cfg = YAML2.parse(raw);
|
|
7840
8491
|
const providers = cfg.llm_providers;
|
|
7841
8492
|
if (!providers?.length) return this.llm;
|
|
@@ -7861,9 +8512,9 @@ Current task:`;
|
|
|
7861
8512
|
if (!this.graph) return;
|
|
7862
8513
|
let extractLLM;
|
|
7863
8514
|
try {
|
|
7864
|
-
const cfgPath =
|
|
7865
|
-
if (
|
|
7866
|
-
const raw =
|
|
8515
|
+
const cfgPath = resolve10(homedir3(), ".0agent", "config.yaml");
|
|
8516
|
+
if (existsSync11(cfgPath)) {
|
|
8517
|
+
const raw = readFileSync8(cfgPath, "utf8");
|
|
7867
8518
|
const cfg = YAML2.parse(raw);
|
|
7868
8519
|
const prov = cfg.llm_providers?.find((p) => p.is_default) ?? cfg.llm_providers?.[0];
|
|
7869
8520
|
if (prov?.api_key && prov.provider === "anthropic") {
|
|
@@ -8101,7 +8752,7 @@ var WebSocketEventBus = class {
|
|
|
8101
8752
|
}
|
|
8102
8753
|
};
|
|
8103
8754
|
|
|
8104
|
-
// packages/daemon/src/BackgroundWorkers.ts
|
|
8755
|
+
// packages/daemon/src/tasks/BackgroundWorkers.ts
|
|
8105
8756
|
var DEFAULT_CONFIG2 = {
|
|
8106
8757
|
decay_interval_ms: 6 * 60 * 60 * 1e3,
|
|
8107
8758
|
// 6 hours
|
|
@@ -8225,8 +8876,8 @@ var BackgroundWorkers = class {
|
|
|
8225
8876
|
}
|
|
8226
8877
|
};
|
|
8227
8878
|
|
|
8228
|
-
// packages/daemon/src/SkillRegistry.ts
|
|
8229
|
-
import { readFileSync as
|
|
8879
|
+
// packages/daemon/src/skills/SkillRegistry.ts
|
|
8880
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync3, existsSync as existsSync12, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, mkdirSync as mkdirSync4 } from "node:fs";
|
|
8230
8881
|
import { join as join3 } from "node:path";
|
|
8231
8882
|
import { homedir as homedir4 } from "node:os";
|
|
8232
8883
|
import YAML3 from "yaml";
|
|
@@ -8249,11 +8900,11 @@ var SkillRegistry = class {
|
|
|
8249
8900
|
this.loadFromDir(this.customDir, false);
|
|
8250
8901
|
}
|
|
8251
8902
|
loadFromDir(dir, isBuiltin) {
|
|
8252
|
-
if (!
|
|
8903
|
+
if (!existsSync12(dir)) return;
|
|
8253
8904
|
const files = readdirSync3(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
8254
8905
|
for (const file of files) {
|
|
8255
8906
|
try {
|
|
8256
|
-
const raw =
|
|
8907
|
+
const raw = readFileSync9(join3(dir, file), "utf8");
|
|
8257
8908
|
const skill = YAML3.parse(raw);
|
|
8258
8909
|
if (skill.name) {
|
|
8259
8910
|
this.skills.set(skill.name, skill);
|
|
@@ -8303,7 +8954,7 @@ var SkillRegistry = class {
|
|
|
8303
8954
|
throw new Error(`Cannot delete built-in skill: ${name}`);
|
|
8304
8955
|
}
|
|
8305
8956
|
const filePath = join3(this.customDir, `${name}.yaml`);
|
|
8306
|
-
if (
|
|
8957
|
+
if (existsSync12(filePath)) {
|
|
8307
8958
|
unlinkSync3(filePath);
|
|
8308
8959
|
}
|
|
8309
8960
|
this.skills.delete(name);
|
|
@@ -8316,8 +8967,8 @@ var SkillRegistry = class {
|
|
|
8316
8967
|
// packages/daemon/src/HTTPServer.ts
|
|
8317
8968
|
import { Hono as Hono14 } from "hono";
|
|
8318
8969
|
import { serve } from "@hono/node-server";
|
|
8319
|
-
import { readFileSync as
|
|
8320
|
-
import { resolve as
|
|
8970
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
8971
|
+
import { resolve as resolve12, dirname as dirname4 } from "node:path";
|
|
8321
8972
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
8322
8973
|
|
|
8323
8974
|
// packages/daemon/src/routes/health.ts
|
|
@@ -8609,8 +9260,8 @@ function memoryRoutes(deps) {
|
|
|
8609
9260
|
// packages/daemon/src/routes/llm.ts
|
|
8610
9261
|
init_LLMExecutor();
|
|
8611
9262
|
import { Hono as Hono10 } from "hono";
|
|
8612
|
-
import { readFileSync as
|
|
8613
|
-
import { resolve as
|
|
9263
|
+
import { readFileSync as readFileSync10, existsSync as existsSync13 } from "node:fs";
|
|
9264
|
+
import { resolve as resolve11 } from "node:path";
|
|
8614
9265
|
import { homedir as homedir5 } from "node:os";
|
|
8615
9266
|
import YAML4 from "yaml";
|
|
8616
9267
|
function llmRoutes() {
|
|
@@ -8618,11 +9269,11 @@ function llmRoutes() {
|
|
|
8618
9269
|
app.post("/ping", async (c) => {
|
|
8619
9270
|
const start = Date.now();
|
|
8620
9271
|
try {
|
|
8621
|
-
const configPath =
|
|
8622
|
-
if (!
|
|
9272
|
+
const configPath = resolve11(homedir5(), ".0agent", "config.yaml");
|
|
9273
|
+
if (!existsSync13(configPath)) {
|
|
8623
9274
|
return c.json({ ok: false, error: "Config not found. Run: 0agent init" });
|
|
8624
9275
|
}
|
|
8625
|
-
const cfg = YAML4.parse(
|
|
9276
|
+
const cfg = YAML4.parse(readFileSync10(configPath, "utf8"));
|
|
8626
9277
|
const providers = cfg.llm_providers;
|
|
8627
9278
|
const def = providers?.find((p) => p.is_default) ?? providers?.[0];
|
|
8628
9279
|
if (!def) {
|
|
@@ -8707,7 +9358,7 @@ function codespaceRoutes(deps) {
|
|
|
8707
9358
|
// packages/daemon/src/routes/schedule.ts
|
|
8708
9359
|
import { Hono as Hono12 } from "hono";
|
|
8709
9360
|
|
|
8710
|
-
// packages/daemon/src/SchedulerManager.ts
|
|
9361
|
+
// packages/daemon/src/tasks/SchedulerManager.ts
|
|
8711
9362
|
var DAYS = {
|
|
8712
9363
|
sunday: 0,
|
|
8713
9364
|
sun: 0,
|
|
@@ -9137,15 +9788,15 @@ function runtimeRoutes(deps) {
|
|
|
9137
9788
|
// packages/daemon/src/HTTPServer.ts
|
|
9138
9789
|
function findGraphHtml() {
|
|
9139
9790
|
const candidates = [
|
|
9140
|
-
|
|
9791
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "graph.html"),
|
|
9141
9792
|
// dev (src/)
|
|
9142
|
-
|
|
9793
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "..", "graph.html"),
|
|
9143
9794
|
// bundled (dist/../)
|
|
9144
|
-
|
|
9795
|
+
resolve12(dirname4(fileURLToPath2(import.meta.url)), "..", "dist", "graph.html")
|
|
9145
9796
|
];
|
|
9146
9797
|
for (const p of candidates) {
|
|
9147
9798
|
try {
|
|
9148
|
-
|
|
9799
|
+
readFileSync11(p);
|
|
9149
9800
|
return p;
|
|
9150
9801
|
} catch {
|
|
9151
9802
|
}
|
|
@@ -9181,7 +9832,7 @@ var HTTPServer = class {
|
|
|
9181
9832
|
}
|
|
9182
9833
|
const serveGraph = (c) => {
|
|
9183
9834
|
try {
|
|
9184
|
-
const html =
|
|
9835
|
+
const html = readFileSync11(GRAPH_HTML_PATH, "utf8");
|
|
9185
9836
|
return c.html(html);
|
|
9186
9837
|
} catch {
|
|
9187
9838
|
return c.html("<p>Graph UI not found. Run: pnpm build</p>");
|
|
@@ -9191,7 +9842,7 @@ var HTTPServer = class {
|
|
|
9191
9842
|
this.app.get("/graph", serveGraph);
|
|
9192
9843
|
}
|
|
9193
9844
|
start() {
|
|
9194
|
-
return new Promise((
|
|
9845
|
+
return new Promise((resolve19) => {
|
|
9195
9846
|
this.server = serve(
|
|
9196
9847
|
{
|
|
9197
9848
|
fetch: this.app.fetch,
|
|
@@ -9199,20 +9850,20 @@ var HTTPServer = class {
|
|
|
9199
9850
|
hostname: this.deps.host
|
|
9200
9851
|
},
|
|
9201
9852
|
() => {
|
|
9202
|
-
|
|
9853
|
+
resolve19();
|
|
9203
9854
|
}
|
|
9204
9855
|
);
|
|
9205
9856
|
});
|
|
9206
9857
|
}
|
|
9207
9858
|
stop() {
|
|
9208
|
-
return new Promise((
|
|
9859
|
+
return new Promise((resolve19, reject) => {
|
|
9209
9860
|
if (!this.server) {
|
|
9210
|
-
|
|
9861
|
+
resolve19();
|
|
9211
9862
|
return;
|
|
9212
9863
|
}
|
|
9213
9864
|
this.server.close((err) => {
|
|
9214
9865
|
if (err) reject(err);
|
|
9215
|
-
else
|
|
9866
|
+
else resolve19();
|
|
9216
9867
|
});
|
|
9217
9868
|
});
|
|
9218
9869
|
}
|
|
@@ -9224,13 +9875,13 @@ var HTTPServer = class {
|
|
|
9224
9875
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
9225
9876
|
init_LLMExecutor();
|
|
9226
9877
|
|
|
9227
|
-
// packages/daemon/src/IdentityManager.ts
|
|
9878
|
+
// packages/daemon/src/utils/IdentityManager.ts
|
|
9228
9879
|
init_src();
|
|
9229
|
-
import { readFileSync as
|
|
9230
|
-
import { resolve as
|
|
9880
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, existsSync as existsSync14, mkdirSync as mkdirSync5 } from "node:fs";
|
|
9881
|
+
import { resolve as resolve13, dirname as dirname5 } from "node:path";
|
|
9231
9882
|
import { homedir as homedir6, hostname } from "node:os";
|
|
9232
9883
|
import YAML5 from "yaml";
|
|
9233
|
-
var IDENTITY_PATH =
|
|
9884
|
+
var IDENTITY_PATH = resolve13(homedir6(), ".0agent", "identity.yaml");
|
|
9234
9885
|
var DEFAULT_IDENTITY = {
|
|
9235
9886
|
name: "User",
|
|
9236
9887
|
device_id: `unknown-device`,
|
|
@@ -9246,8 +9897,8 @@ var IdentityManager = class {
|
|
|
9246
9897
|
* Load or create identity. Call once at daemon startup.
|
|
9247
9898
|
*/
|
|
9248
9899
|
async init() {
|
|
9249
|
-
if (
|
|
9250
|
-
const raw =
|
|
9900
|
+
if (existsSync14(IDENTITY_PATH)) {
|
|
9901
|
+
const raw = readFileSync12(IDENTITY_PATH, "utf8");
|
|
9251
9902
|
this.identity = YAML5.parse(raw);
|
|
9252
9903
|
} else {
|
|
9253
9904
|
this.identity = {
|
|
@@ -9299,24 +9950,24 @@ var IdentityManager = class {
|
|
|
9299
9950
|
}
|
|
9300
9951
|
save() {
|
|
9301
9952
|
const dir = dirname5(IDENTITY_PATH);
|
|
9302
|
-
if (!
|
|
9953
|
+
if (!existsSync14(dir)) {
|
|
9303
9954
|
mkdirSync5(dir, { recursive: true });
|
|
9304
9955
|
}
|
|
9305
9956
|
writeFileSync7(IDENTITY_PATH, YAML5.stringify(this.identity), "utf8");
|
|
9306
9957
|
}
|
|
9307
9958
|
};
|
|
9308
9959
|
|
|
9309
|
-
// packages/daemon/src/TeamManager.ts
|
|
9310
|
-
import { readFileSync as
|
|
9311
|
-
import { resolve as
|
|
9960
|
+
// packages/daemon/src/services/TeamManager.ts
|
|
9961
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync6 } from "node:fs";
|
|
9962
|
+
import { resolve as resolve14 } from "node:path";
|
|
9312
9963
|
import { homedir as homedir7 } from "node:os";
|
|
9313
9964
|
import YAML6 from "yaml";
|
|
9314
|
-
var TEAMS_PATH =
|
|
9965
|
+
var TEAMS_PATH = resolve14(homedir7(), ".0agent", "teams.yaml");
|
|
9315
9966
|
var TeamManager = class {
|
|
9316
9967
|
config;
|
|
9317
9968
|
constructor() {
|
|
9318
|
-
if (
|
|
9319
|
-
this.config = YAML6.parse(
|
|
9969
|
+
if (existsSync15(TEAMS_PATH)) {
|
|
9970
|
+
this.config = YAML6.parse(readFileSync13(TEAMS_PATH, "utf8"));
|
|
9320
9971
|
} else {
|
|
9321
9972
|
this.config = { memberships: [] };
|
|
9322
9973
|
}
|
|
@@ -9371,12 +10022,12 @@ var TeamManager = class {
|
|
|
9371
10022
|
}
|
|
9372
10023
|
}
|
|
9373
10024
|
save() {
|
|
9374
|
-
mkdirSync6(
|
|
10025
|
+
mkdirSync6(resolve14(homedir7(), ".0agent"), { recursive: true });
|
|
9375
10026
|
writeFileSync8(TEAMS_PATH, YAML6.stringify(this.config), "utf8");
|
|
9376
10027
|
}
|
|
9377
10028
|
};
|
|
9378
10029
|
|
|
9379
|
-
// packages/daemon/src/TeamSync.ts
|
|
10030
|
+
// packages/daemon/src/services/TeamSync.ts
|
|
9380
10031
|
var TeamSync = class {
|
|
9381
10032
|
constructor(teamManager, adapter, entityNodeId) {
|
|
9382
10033
|
this.teamManager = teamManager;
|
|
@@ -9454,9 +10105,9 @@ var TeamSync = class {
|
|
|
9454
10105
|
}
|
|
9455
10106
|
};
|
|
9456
10107
|
|
|
9457
|
-
// packages/daemon/src/GitHubMemorySync.ts
|
|
9458
|
-
import { readFileSync as
|
|
9459
|
-
import { resolve as
|
|
10108
|
+
// packages/daemon/src/services/GitHubMemorySync.ts
|
|
10109
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync16, readdirSync as readdirSync4 } from "node:fs";
|
|
10110
|
+
import { resolve as resolve15 } from "node:path";
|
|
9460
10111
|
import { homedir as homedir8 } from "node:os";
|
|
9461
10112
|
var GITHUB_API = "https://api.github.com";
|
|
9462
10113
|
async function ghFetch(path, token, opts) {
|
|
@@ -9576,10 +10227,10 @@ var GitHubMemorySync = class {
|
|
|
9576
10227
|
)
|
|
9577
10228
|
);
|
|
9578
10229
|
}
|
|
9579
|
-
const customSkillsDir =
|
|
9580
|
-
if (
|
|
10230
|
+
const customSkillsDir = resolve15(homedir8(), ".0agent", "skills", "custom");
|
|
10231
|
+
if (existsSync16(customSkillsDir)) {
|
|
9581
10232
|
for (const file of readdirSync4(customSkillsDir).filter((f) => f.endsWith(".yaml"))) {
|
|
9582
|
-
const content =
|
|
10233
|
+
const content = readFileSync14(resolve15(customSkillsDir, file), "utf8");
|
|
9583
10234
|
pushes.push(putFile(token, owner, repo, `skills/custom/${file}`, content, commitMsg));
|
|
9584
10235
|
}
|
|
9585
10236
|
}
|
|
@@ -9765,7 +10416,7 @@ var GitHubMemorySync = class {
|
|
|
9765
10416
|
}
|
|
9766
10417
|
async pullCustomSkills() {
|
|
9767
10418
|
const { token, owner, repo } = this.config;
|
|
9768
|
-
const dir =
|
|
10419
|
+
const dir = resolve15(homedir8(), ".0agent", "skills", "custom");
|
|
9769
10420
|
try {
|
|
9770
10421
|
const res = await ghFetch(`/repos/${owner}/${repo}/contents/skills/custom`, token);
|
|
9771
10422
|
if (!res.ok) return;
|
|
@@ -9775,7 +10426,7 @@ var GitHubMemorySync = class {
|
|
|
9775
10426
|
if (content) {
|
|
9776
10427
|
const { mkdirSync: mkdirSync11 } = await import("node:fs");
|
|
9777
10428
|
mkdirSync11(dir, { recursive: true });
|
|
9778
|
-
writeFileSync9(
|
|
10429
|
+
writeFileSync9(resolve15(dir, file.name), content, "utf8");
|
|
9779
10430
|
}
|
|
9780
10431
|
}
|
|
9781
10432
|
} catch {
|
|
@@ -9851,8 +10502,8 @@ git checkout <commit> graph/ # restore graph files
|
|
|
9851
10502
|
}
|
|
9852
10503
|
};
|
|
9853
10504
|
|
|
9854
|
-
// packages/daemon/src/CodespaceManager.ts
|
|
9855
|
-
import { execSync as
|
|
10505
|
+
// packages/daemon/src/services/CodespaceManager.ts
|
|
10506
|
+
import { execSync as execSync8, spawn as spawn8 } from "node:child_process";
|
|
9856
10507
|
var BROWSER_PORT_REMOTE = 3e3;
|
|
9857
10508
|
var BROWSER_PORT_LOCAL = 3001;
|
|
9858
10509
|
var DISPLAY_NAME = "0agent-browser";
|
|
@@ -9894,7 +10545,7 @@ var CodespaceManager = class {
|
|
|
9894
10545
|
console.log(`[Codespace] Creating browser codespace from ${this.memoryRepo}...`);
|
|
9895
10546
|
console.log("[Codespace] First time: ~2-3 minutes. Subsequent starts: ~30 seconds.");
|
|
9896
10547
|
try {
|
|
9897
|
-
const result =
|
|
10548
|
+
const result = execSync8(
|
|
9898
10549
|
`gh codespace create --repo "${this.memoryRepo}" --machine basicLinux32gb --display-name "${DISPLAY_NAME}" --json name`,
|
|
9899
10550
|
{ encoding: "utf8", timeout: 3e5 }
|
|
9900
10551
|
);
|
|
@@ -9908,7 +10559,7 @@ var CodespaceManager = class {
|
|
|
9908
10559
|
/** Find the 0agent-browser codespace by display name. */
|
|
9909
10560
|
findExisting() {
|
|
9910
10561
|
try {
|
|
9911
|
-
const out =
|
|
10562
|
+
const out = execSync8("gh codespace list --json name,state,displayName,repository", {
|
|
9912
10563
|
encoding: "utf8",
|
|
9913
10564
|
timeout: 1e4
|
|
9914
10565
|
});
|
|
@@ -9924,7 +10575,7 @@ var CodespaceManager = class {
|
|
|
9924
10575
|
const info = this.findExisting();
|
|
9925
10576
|
if (info?.state === "Shutdown") {
|
|
9926
10577
|
console.log("[Codespace] Starting stopped codespace (~30s)...");
|
|
9927
|
-
|
|
10578
|
+
execSync8(`gh codespace start --codespace "${name}"`, { timeout: 12e4 });
|
|
9928
10579
|
await this.waitForState(name, "Available", 60);
|
|
9929
10580
|
console.log("[Codespace] Codespace is running");
|
|
9930
10581
|
} else if (info?.state === "Starting") {
|
|
@@ -9936,7 +10587,7 @@ var CodespaceManager = class {
|
|
|
9936
10587
|
/** Start the browser server inside the codespace (idempotent). */
|
|
9937
10588
|
async startBrowserServer(name) {
|
|
9938
10589
|
try {
|
|
9939
|
-
|
|
10590
|
+
execSync8(
|
|
9940
10591
|
`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
10592
|
{ timeout: 3e4 }
|
|
9942
10593
|
);
|
|
@@ -9947,7 +10598,7 @@ var CodespaceManager = class {
|
|
|
9947
10598
|
async openTunnel(name) {
|
|
9948
10599
|
this.closeTunnel();
|
|
9949
10600
|
console.log(`[Codespace] Opening tunnel port ${BROWSER_PORT_REMOTE} \u2192 localhost:${BROWSER_PORT_LOCAL}...`);
|
|
9950
|
-
this.forwardProcess =
|
|
10601
|
+
this.forwardProcess = spawn8(
|
|
9951
10602
|
"gh",
|
|
9952
10603
|
["codespace", "ports", "forward", `${BROWSER_PORT_REMOTE}:${BROWSER_PORT_LOCAL}`, "--codespace", name],
|
|
9953
10604
|
{ stdio: ["ignore", "ignore", "ignore"] }
|
|
@@ -9991,7 +10642,7 @@ var CodespaceManager = class {
|
|
|
9991
10642
|
this.closeTunnel();
|
|
9992
10643
|
const info = this.findExisting();
|
|
9993
10644
|
if (info?.state === "Available") {
|
|
9994
|
-
|
|
10645
|
+
execSync8(`gh codespace stop --codespace "${info.name}"`, { timeout: 3e4 });
|
|
9995
10646
|
console.log("[Codespace] Stopped (state preserved, restarts in 30s when needed)");
|
|
9996
10647
|
}
|
|
9997
10648
|
}
|
|
@@ -10000,7 +10651,7 @@ var CodespaceManager = class {
|
|
|
10000
10651
|
this.closeTunnel();
|
|
10001
10652
|
const info = this.findExisting();
|
|
10002
10653
|
if (info) {
|
|
10003
|
-
|
|
10654
|
+
execSync8(`gh codespace delete --codespace "${info.name}" --force`, { timeout: 3e4 });
|
|
10004
10655
|
console.log("[Codespace] Deleted");
|
|
10005
10656
|
}
|
|
10006
10657
|
}
|
|
@@ -10026,7 +10677,7 @@ var CodespaceManager = class {
|
|
|
10026
10677
|
/** Check if gh CLI is installed and authenticated. */
|
|
10027
10678
|
static isAvailable() {
|
|
10028
10679
|
try {
|
|
10029
|
-
|
|
10680
|
+
execSync8("gh auth status", { stdio: "ignore", timeout: 5e3 });
|
|
10030
10681
|
return true;
|
|
10031
10682
|
} catch {
|
|
10032
10683
|
return false;
|
|
@@ -10037,7 +10688,7 @@ var CodespaceManager = class {
|
|
|
10037
10688
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
10038
10689
|
init_RuntimeSelfHeal();
|
|
10039
10690
|
|
|
10040
|
-
// packages/daemon/src/TelegramBridge.ts
|
|
10691
|
+
// packages/daemon/src/services/TelegramBridge.ts
|
|
10041
10692
|
var TelegramBridge = class {
|
|
10042
10693
|
constructor(config, sessions, eventBus) {
|
|
10043
10694
|
this.config = config;
|
|
@@ -10336,52 +10987,52 @@ var SurfaceRouter = class {
|
|
|
10336
10987
|
}
|
|
10337
10988
|
_handleDaemonEvent(event) {
|
|
10338
10989
|
const sessionId = String(event.session_id ?? "");
|
|
10339
|
-
const
|
|
10340
|
-
if (!
|
|
10341
|
-
const adapter = this.adapters.get(
|
|
10990
|
+
const state2 = this.activeSessions.get(sessionId);
|
|
10991
|
+
if (!state2) return;
|
|
10992
|
+
const adapter = this.adapters.get(state2.surface);
|
|
10342
10993
|
if (!adapter) return;
|
|
10343
10994
|
if (event.type === "session.token") {
|
|
10344
|
-
|
|
10345
|
-
if (
|
|
10346
|
-
|
|
10347
|
-
if (!
|
|
10995
|
+
state2.tokenBuffer += String(event.token ?? "");
|
|
10996
|
+
if (state2.streamTimer) clearTimeout(state2.streamTimer);
|
|
10997
|
+
state2.streamTimer = setTimeout(() => {
|
|
10998
|
+
if (!state2.tokenBuffer) return;
|
|
10348
10999
|
adapter.send({
|
|
10349
|
-
surface_channel_id:
|
|
10350
|
-
text:
|
|
11000
|
+
surface_channel_id: state2.channelId,
|
|
11001
|
+
text: state2.tokenBuffer,
|
|
10351
11002
|
format: "markdown",
|
|
10352
11003
|
is_progress: true,
|
|
10353
|
-
thread_id:
|
|
11004
|
+
thread_id: state2.threadId
|
|
10354
11005
|
}).catch(() => {
|
|
10355
11006
|
});
|
|
10356
11007
|
}, 400);
|
|
10357
11008
|
} else if (event.type === "session.completed") {
|
|
10358
|
-
if (
|
|
10359
|
-
clearTimeout(
|
|
10360
|
-
|
|
11009
|
+
if (state2.streamTimer) {
|
|
11010
|
+
clearTimeout(state2.streamTimer);
|
|
11011
|
+
state2.streamTimer = null;
|
|
10361
11012
|
}
|
|
10362
11013
|
const result = event.result;
|
|
10363
11014
|
const output = String(result?.output ?? "").trim();
|
|
10364
11015
|
if (output && output !== "(no output)") {
|
|
10365
11016
|
adapter.send({
|
|
10366
|
-
surface_channel_id:
|
|
11017
|
+
surface_channel_id: state2.channelId,
|
|
10367
11018
|
text: output,
|
|
10368
11019
|
format: "markdown",
|
|
10369
11020
|
is_progress: false,
|
|
10370
|
-
thread_id:
|
|
11021
|
+
thread_id: state2.threadId
|
|
10371
11022
|
}).catch(() => {
|
|
10372
11023
|
});
|
|
10373
11024
|
}
|
|
10374
11025
|
this.activeSessions.delete(sessionId);
|
|
10375
11026
|
} else if (event.type === "session.failed") {
|
|
10376
|
-
if (
|
|
10377
|
-
clearTimeout(
|
|
10378
|
-
|
|
11027
|
+
if (state2.streamTimer) {
|
|
11028
|
+
clearTimeout(state2.streamTimer);
|
|
11029
|
+
state2.streamTimer = null;
|
|
10379
11030
|
}
|
|
10380
11031
|
adapter.send({
|
|
10381
|
-
surface_channel_id:
|
|
11032
|
+
surface_channel_id: state2.channelId,
|
|
10382
11033
|
text: `\u26A0\uFE0F ${String(event.error ?? "Task failed")}`,
|
|
10383
11034
|
format: "prose",
|
|
10384
|
-
thread_id:
|
|
11035
|
+
thread_id: state2.threadId
|
|
10385
11036
|
}).catch(() => {
|
|
10386
11037
|
});
|
|
10387
11038
|
this.activeSessions.delete(sessionId);
|
|
@@ -10396,7 +11047,7 @@ var SurfaceRouter = class {
|
|
|
10396
11047
|
};
|
|
10397
11048
|
|
|
10398
11049
|
// packages/daemon/src/surfaces/TelegramAdapter.ts
|
|
10399
|
-
import { existsSync as
|
|
11050
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7 } from "node:fs";
|
|
10400
11051
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
10401
11052
|
import { join as join4 } from "node:path";
|
|
10402
11053
|
var TelegramAdapter = class {
|
|
@@ -10446,13 +11097,13 @@ var TelegramAdapter = class {
|
|
|
10446
11097
|
async send(msg) {
|
|
10447
11098
|
const chatId = Number(msg.surface_channel_id);
|
|
10448
11099
|
if (!chatId) return;
|
|
10449
|
-
const
|
|
10450
|
-
if (msg.is_progress &&
|
|
10451
|
-
|
|
10452
|
-
await this._editMessage(chatId,
|
|
11100
|
+
const state2 = this.streamingState.get(chatId);
|
|
11101
|
+
if (msg.is_progress && state2) {
|
|
11102
|
+
state2.accumulatedText = msg.text;
|
|
11103
|
+
await this._editMessage(chatId, state2.workingMsgId, `\u23F3 ${this._truncate(msg.text, 3800)}`);
|
|
10453
11104
|
} else {
|
|
10454
|
-
if (
|
|
10455
|
-
await this._editMessage(chatId,
|
|
11105
|
+
if (state2) {
|
|
11106
|
+
await this._editMessage(chatId, state2.workingMsgId, msg.text);
|
|
10456
11107
|
this.streamingState.delete(chatId);
|
|
10457
11108
|
} else {
|
|
10458
11109
|
await this._sendMessage(chatId, msg.text);
|
|
@@ -10603,7 +11254,7 @@ Sessions: ${h.active_sessions} active`
|
|
|
10603
11254
|
const fileUrl = await this._getFileUrl(fileId);
|
|
10604
11255
|
if (!fileUrl) return null;
|
|
10605
11256
|
const tmpDir = join4(tmpdir3(), "0agent-voice");
|
|
10606
|
-
if (!
|
|
11257
|
+
if (!existsSync17(tmpDir)) mkdirSync7(tmpDir, { recursive: true });
|
|
10607
11258
|
const tmpPath = join4(tmpDir, `${fileId}.ogg`);
|
|
10608
11259
|
const wavPath = join4(tmpDir, `${fileId}.wav`);
|
|
10609
11260
|
const res = await fetch(fileUrl);
|
|
@@ -10611,20 +11262,20 @@ Sessions: ${h.active_sessions} active`
|
|
|
10611
11262
|
const buf = await res.arrayBuffer();
|
|
10612
11263
|
const { writeFileSync: writeFileSync13 } = await import("node:fs");
|
|
10613
11264
|
writeFileSync13(tmpPath, Buffer.from(buf));
|
|
10614
|
-
const { execSync:
|
|
11265
|
+
const { execSync: execSync11 } = await import("node:child_process");
|
|
10615
11266
|
try {
|
|
10616
|
-
|
|
11267
|
+
execSync11(`ffmpeg -y -i "${tmpPath}" -ar 16000 -ac 1 "${wavPath}" 2>/dev/null`, { timeout: 3e4 });
|
|
10617
11268
|
} catch {
|
|
10618
11269
|
}
|
|
10619
|
-
const inputFile =
|
|
10620
|
-
const whisperOut =
|
|
11270
|
+
const inputFile = existsSync17(wavPath) ? wavPath : tmpPath;
|
|
11271
|
+
const whisperOut = execSync11(
|
|
10621
11272
|
`whisper "${inputFile}" --model ${this.whisperModel} --output_format txt --output_dir "${tmpDir}" --fp16 False 2>/dev/null`,
|
|
10622
11273
|
{ timeout: 12e4, encoding: "utf8" }
|
|
10623
11274
|
);
|
|
10624
11275
|
const txtPath = inputFile.replace(/\.(ogg|wav)$/, ".txt");
|
|
10625
|
-
if (
|
|
10626
|
-
const { readFileSync:
|
|
10627
|
-
return
|
|
11276
|
+
if (existsSync17(txtPath)) {
|
|
11277
|
+
const { readFileSync: readFileSync18 } = await import("node:fs");
|
|
11278
|
+
return readFileSync18(txtPath, "utf8").trim();
|
|
10628
11279
|
}
|
|
10629
11280
|
return whisperOut?.trim() || null;
|
|
10630
11281
|
} catch {
|
|
@@ -10790,24 +11441,24 @@ var SlackAdapter = class {
|
|
|
10790
11441
|
if (!this.app) return;
|
|
10791
11442
|
const client = this.app["client"];
|
|
10792
11443
|
const stateKey = `${msg.surface_channel_id}:${msg.thread_id ?? ""}`;
|
|
10793
|
-
const
|
|
10794
|
-
if (msg.is_progress &&
|
|
11444
|
+
const state2 = this.streamingState.get(stateKey);
|
|
11445
|
+
if (msg.is_progress && state2) {
|
|
10795
11446
|
try {
|
|
10796
11447
|
await client["chat.update"]({
|
|
10797
|
-
channel:
|
|
10798
|
-
ts:
|
|
11448
|
+
channel: state2.channelId,
|
|
11449
|
+
ts: state2.ts,
|
|
10799
11450
|
text: `\u23F3 ${this._truncate(msg.text, 3e3)}`
|
|
10800
11451
|
});
|
|
10801
11452
|
} catch {
|
|
10802
11453
|
}
|
|
10803
11454
|
} else {
|
|
10804
|
-
if (
|
|
11455
|
+
if (state2) {
|
|
10805
11456
|
try {
|
|
10806
11457
|
await client["chat.update"]({
|
|
10807
|
-
channel:
|
|
10808
|
-
ts:
|
|
11458
|
+
channel: state2.channelId,
|
|
11459
|
+
ts: state2.ts,
|
|
10809
11460
|
text: msg.text,
|
|
10810
|
-
thread_ts:
|
|
11461
|
+
thread_ts: state2.threadTs || void 0
|
|
10811
11462
|
});
|
|
10812
11463
|
} catch {
|
|
10813
11464
|
await this._postMessage(client, msg.surface_channel_id, msg.text, msg.thread_id);
|
|
@@ -11066,10 +11717,10 @@ var WhatsAppAdapter = class {
|
|
|
11066
11717
|
import * as readline from "node:readline";
|
|
11067
11718
|
|
|
11068
11719
|
// packages/daemon/src/surfaces/WhisperSTT.ts
|
|
11069
|
-
import { execSync as
|
|
11070
|
-
import { existsSync as
|
|
11720
|
+
import { execSync as execSync9, spawnSync as spawnSync5 } from "node:child_process";
|
|
11721
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, readFileSync as readFileSync15 } from "node:fs";
|
|
11071
11722
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
11072
|
-
import { join as join5, basename } from "node:path";
|
|
11723
|
+
import { join as join5, basename as basename2 } from "node:path";
|
|
11073
11724
|
var WhisperSTT = class _WhisperSTT {
|
|
11074
11725
|
model;
|
|
11075
11726
|
language;
|
|
@@ -11085,20 +11736,20 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11085
11736
|
console.warn("[WhisperSTT] No Whisper binary found. Install: pip install openai-whisper");
|
|
11086
11737
|
return null;
|
|
11087
11738
|
}
|
|
11088
|
-
if (!
|
|
11739
|
+
if (!existsSync18(audioPath)) {
|
|
11089
11740
|
console.warn(`[WhisperSTT] Audio file not found: ${audioPath}`);
|
|
11090
11741
|
return null;
|
|
11091
11742
|
}
|
|
11092
11743
|
const outDir = join5(tmpdir4(), "0agent-whisper");
|
|
11093
|
-
if (!
|
|
11744
|
+
if (!existsSync18(outDir)) mkdirSync8(outDir, { recursive: true });
|
|
11094
11745
|
try {
|
|
11095
11746
|
const langFlag = this.language ? `--language ${this.language}` : "";
|
|
11096
11747
|
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 =
|
|
11748
|
+
execSync9(cmd, { timeout: 18e4, stdio: "pipe" });
|
|
11749
|
+
const baseName = basename2(audioPath).replace(/\.[^.]+$/, "");
|
|
11099
11750
|
const txtPath = join5(outDir, `${baseName}.txt`);
|
|
11100
|
-
if (
|
|
11101
|
-
return
|
|
11751
|
+
if (existsSync18(txtPath)) {
|
|
11752
|
+
return readFileSync15(txtPath, "utf8").trim();
|
|
11102
11753
|
}
|
|
11103
11754
|
return null;
|
|
11104
11755
|
} catch (err) {
|
|
@@ -11123,14 +11774,14 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11123
11774
|
};
|
|
11124
11775
|
async function recordAudio(durationSeconds) {
|
|
11125
11776
|
const outDir = join5(tmpdir4(), "0agent-voice");
|
|
11126
|
-
if (!
|
|
11777
|
+
if (!existsSync18(outDir)) mkdirSync8(outDir, { recursive: true });
|
|
11127
11778
|
const outPath = join5(outDir, `recording-${Date.now()}.wav`);
|
|
11128
11779
|
const soxResult = spawnSync5(
|
|
11129
11780
|
"sox",
|
|
11130
11781
|
["-d", "-r", "16000", "-c", "1", "-b", "16", outPath, "trim", "0", String(durationSeconds)],
|
|
11131
11782
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11132
11783
|
);
|
|
11133
|
-
if (soxResult.status === 0 &&
|
|
11784
|
+
if (soxResult.status === 0 && existsSync18(outPath)) return outPath;
|
|
11134
11785
|
const platform3 = process.platform;
|
|
11135
11786
|
let ffmpegDevice;
|
|
11136
11787
|
if (platform3 === "darwin") {
|
|
@@ -11145,11 +11796,11 @@ async function recordAudio(durationSeconds) {
|
|
|
11145
11796
|
["-y", ...ffmpegDevice, "-ar", "16000", "-ac", "1", "-t", String(durationSeconds), outPath],
|
|
11146
11797
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11147
11798
|
);
|
|
11148
|
-
return ffmpegResult.status === 0 &&
|
|
11799
|
+
return ffmpegResult.status === 0 && existsSync18(outPath) ? outPath : null;
|
|
11149
11800
|
}
|
|
11150
11801
|
|
|
11151
11802
|
// packages/daemon/src/surfaces/NativeTTS.ts
|
|
11152
|
-
import { spawnSync as spawnSync6, spawn as
|
|
11803
|
+
import { spawnSync as spawnSync6, spawn as spawn9 } from "node:child_process";
|
|
11153
11804
|
var NativeTTS = class _NativeTTS {
|
|
11154
11805
|
engine;
|
|
11155
11806
|
voice;
|
|
@@ -11173,11 +11824,11 @@ var NativeTTS = class _NativeTTS {
|
|
|
11173
11824
|
if (!this.resolvedEngine) return;
|
|
11174
11825
|
const cleaned = this._clean(text);
|
|
11175
11826
|
if (!cleaned) return;
|
|
11176
|
-
return new Promise((
|
|
11827
|
+
return new Promise((resolve19) => {
|
|
11177
11828
|
const args = this._buildArgs(this.resolvedEngine, cleaned);
|
|
11178
|
-
const proc =
|
|
11179
|
-
proc.on("close", () =>
|
|
11180
|
-
proc.on("error", () =>
|
|
11829
|
+
const proc = spawn9(this.resolvedEngine, args, { stdio: "ignore" });
|
|
11830
|
+
proc.on("close", () => resolve19());
|
|
11831
|
+
proc.on("error", () => resolve19());
|
|
11181
11832
|
});
|
|
11182
11833
|
}
|
|
11183
11834
|
/** Check if any TTS engine is available */
|
|
@@ -11235,7 +11886,7 @@ var NativeTTS = class _NativeTTS {
|
|
|
11235
11886
|
}
|
|
11236
11887
|
_speakWith(engine, text) {
|
|
11237
11888
|
const args = this._buildArgs(engine, text);
|
|
11238
|
-
const proc =
|
|
11889
|
+
const proc = spawn9(engine, args, { stdio: "ignore", detached: true });
|
|
11239
11890
|
proc.unref();
|
|
11240
11891
|
}
|
|
11241
11892
|
/** Remove markdown/ANSI and control chars before speaking */
|
|
@@ -11360,10 +12011,10 @@ var VoiceAdapter = class {
|
|
|
11360
12011
|
};
|
|
11361
12012
|
|
|
11362
12013
|
// packages/daemon/src/surfaces/MeetingAdapter.ts
|
|
11363
|
-
import { existsSync as
|
|
12014
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
11364
12015
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
11365
12016
|
import { join as join6 } from "node:path";
|
|
11366
|
-
import { spawn as
|
|
12017
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
11367
12018
|
var MeetingAdapter = class {
|
|
11368
12019
|
name = "meeting";
|
|
11369
12020
|
messageHandler = null;
|
|
@@ -11388,7 +12039,7 @@ var MeetingAdapter = class {
|
|
|
11388
12039
|
this.triggerPhrases = config.trigger_phrases ?? ["agent,", "hey agent", "ok agent"];
|
|
11389
12040
|
this.contextWindowSeconds = config.context_window_seconds ?? 120;
|
|
11390
12041
|
this.tmpDir = join6(tmpdir5(), "0agent-meeting");
|
|
11391
|
-
if (!
|
|
12042
|
+
if (!existsSync19(this.tmpDir)) mkdirSync9(this.tmpDir, { recursive: true });
|
|
11392
12043
|
this.stt = new WhisperSTT({ model: config.whisper_model ?? "base" });
|
|
11393
12044
|
}
|
|
11394
12045
|
onMessage(handler) {
|
|
@@ -11473,7 +12124,7 @@ ${msg.text}
|
|
|
11473
12124
|
async _captureAndTranscribeChunk(channelId) {
|
|
11474
12125
|
const chunkPath = join6(this.tmpDir, `chunk-${Date.now()}.wav`);
|
|
11475
12126
|
const captured = await this._captureSystemAudio(chunkPath, this.chunkSeconds);
|
|
11476
|
-
if (!captured || !
|
|
12127
|
+
if (!captured || !existsSync19(chunkPath)) return;
|
|
11477
12128
|
const text = await this.stt.transcribe(chunkPath);
|
|
11478
12129
|
if (!text || text.trim().length < 3) return;
|
|
11479
12130
|
const segment = { text: text.trim(), timestamp: Date.now() };
|
|
@@ -11494,7 +12145,7 @@ ${msg.text}
|
|
|
11494
12145
|
}
|
|
11495
12146
|
}
|
|
11496
12147
|
async _captureSystemAudio(outPath, seconds) {
|
|
11497
|
-
return new Promise((
|
|
12148
|
+
return new Promise((resolve19) => {
|
|
11498
12149
|
const platform3 = process.platform;
|
|
11499
12150
|
let args;
|
|
11500
12151
|
if (platform3 === "darwin") {
|
|
@@ -11502,18 +12153,18 @@ ${msg.text}
|
|
|
11502
12153
|
} else if (platform3 === "linux") {
|
|
11503
12154
|
args = ["-y", "-f", "pulse", "-i", "default.monitor", "-ar", "16000", "-ac", "1", "-t", String(seconds), outPath];
|
|
11504
12155
|
} else {
|
|
11505
|
-
|
|
12156
|
+
resolve19(false);
|
|
11506
12157
|
return;
|
|
11507
12158
|
}
|
|
11508
|
-
const proc =
|
|
12159
|
+
const proc = spawn10("ffmpeg", args, { stdio: "pipe" });
|
|
11509
12160
|
this.ffmpegProcess = proc;
|
|
11510
12161
|
proc.on("close", (code) => {
|
|
11511
12162
|
this.ffmpegProcess = null;
|
|
11512
|
-
|
|
12163
|
+
resolve19(code === 0);
|
|
11513
12164
|
});
|
|
11514
12165
|
proc.on("error", () => {
|
|
11515
12166
|
this.ffmpegProcess = null;
|
|
11516
|
-
|
|
12167
|
+
resolve19(false);
|
|
11517
12168
|
});
|
|
11518
12169
|
});
|
|
11519
12170
|
}
|
|
@@ -11611,12 +12262,12 @@ var ZeroAgentDaemon = class {
|
|
|
11611
12262
|
startedAt = 0;
|
|
11612
12263
|
pidFilePath;
|
|
11613
12264
|
constructor() {
|
|
11614
|
-
this.pidFilePath =
|
|
12265
|
+
this.pidFilePath = resolve17(homedir9(), ".0agent", "daemon.pid");
|
|
11615
12266
|
}
|
|
11616
12267
|
async start(opts) {
|
|
11617
12268
|
this.config = await loadConfig(opts?.config_path);
|
|
11618
|
-
const dotDir =
|
|
11619
|
-
if (!
|
|
12269
|
+
const dotDir = resolve17(homedir9(), ".0agent");
|
|
12270
|
+
if (!existsSync21(dotDir)) {
|
|
11620
12271
|
mkdirSync10(dotDir, { recursive: true });
|
|
11621
12272
|
}
|
|
11622
12273
|
this.adapter = new SQLiteAdapter({ db_path: this.config.graph.db_path });
|
|
@@ -11690,10 +12341,10 @@ var ZeroAgentDaemon = class {
|
|
|
11690
12341
|
console.log(`[0agent] Teams: ${teams.map((t) => t.team_name).join(", ")}`);
|
|
11691
12342
|
}
|
|
11692
12343
|
const _daemonFile = fileURLToPath3(import.meta.url);
|
|
11693
|
-
const _agentRoot =
|
|
12344
|
+
const _agentRoot = resolve17(dirname7(_daemonFile), "..");
|
|
11694
12345
|
let agentRoot;
|
|
11695
12346
|
try {
|
|
11696
|
-
const _pkg = JSON.parse(
|
|
12347
|
+
const _pkg = JSON.parse(readFileSync17(resolve17(_agentRoot, "package.json"), "utf8"));
|
|
11697
12348
|
if (_pkg.name === "0agent") agentRoot = _agentRoot;
|
|
11698
12349
|
} catch {
|
|
11699
12350
|
}
|
|
@@ -11897,7 +12548,7 @@ var ZeroAgentDaemon = class {
|
|
|
11897
12548
|
this.graph = null;
|
|
11898
12549
|
}
|
|
11899
12550
|
this.adapter = null;
|
|
11900
|
-
if (
|
|
12551
|
+
if (existsSync21(this.pidFilePath)) {
|
|
11901
12552
|
try {
|
|
11902
12553
|
unlinkSync4(this.pidFilePath);
|
|
11903
12554
|
} catch {
|
|
@@ -11927,11 +12578,11 @@ var ZeroAgentDaemon = class {
|
|
|
11927
12578
|
};
|
|
11928
12579
|
|
|
11929
12580
|
// packages/daemon/src/start.ts
|
|
11930
|
-
import { resolve as
|
|
12581
|
+
import { resolve as resolve18 } from "node:path";
|
|
11931
12582
|
import { homedir as homedir10 } from "node:os";
|
|
11932
|
-
import { existsSync as
|
|
11933
|
-
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ??
|
|
11934
|
-
if (!
|
|
12583
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
12584
|
+
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ?? resolve18(homedir10(), ".0agent", "config.yaml");
|
|
12585
|
+
if (!existsSync22(CONFIG_PATH)) {
|
|
11935
12586
|
console.error(`
|
|
11936
12587
|
0agent is not initialised.
|
|
11937
12588
|
|