@adhdev/daemon-core 0.5.3 → 0.5.5
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/index.d.ts +79 -2
- package/dist/index.js +1131 -433
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/providers/_builtin/extension/cline/scripts/read_chat.js +14 -1
- package/providers/_builtin/ide/antigravity/scripts/1.106/read_chat.js +24 -1
- package/providers/_builtin/ide/antigravity/scripts/1.107/read_chat.js +24 -1
- package/providers/_builtin/ide/cursor/scripts/0.49/focus_editor.js +3 -3
- package/providers/_builtin/ide/cursor/scripts/0.49/list_models.js +1 -1
- package/providers/_builtin/ide/cursor/scripts/0.49/list_modes.js +1 -1
- package/providers/_builtin/ide/cursor/scripts/0.49/open_panel.js +4 -4
- package/providers/_builtin/ide/cursor/scripts/0.49/read_chat.js +5 -1
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/dismiss_notification.js +30 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/focus_editor.js +13 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/list_models.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/list_modes.js +40 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/list_notifications.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/list_sessions.js +42 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/new_session.js +20 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/open_panel.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/read_chat.js +79 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/resolve_action.js +19 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/scripts.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/send_message.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/set_mode.js +38 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/set_model.js +81 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/switch_session.js +28 -0
- package/providers/_builtin/ide/windsurf/scripts/read_chat.js +18 -1
- package/src/cli-adapters/provider-cli-adapter.ts +167 -7
- package/src/commands/cli-manager.ts +128 -30
- package/src/commands/handler.ts +47 -3
- package/src/commands/router.ts +32 -2
- package/src/commands/workspace-commands.ts +108 -0
- package/src/config/config.ts +29 -1
- package/src/config/workspace-activity.ts +65 -0
- package/src/config/workspaces.ts +250 -0
- package/src/daemon/dev-server.ts +1 -1
- package/src/index.ts +5 -0
- package/src/launch.ts +1 -1
- package/src/providers/ide-provider-instance.ts +11 -0
- package/src/status/reporter.ts +23 -4
- package/src/system/host-memory.ts +65 -0
- package/src/types.ts +8 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,188 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
));
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
|
+
// src/config/workspaces.ts
|
|
34
|
+
function expandPath(p) {
|
|
35
|
+
const t = (p || "").trim();
|
|
36
|
+
if (!t) return "";
|
|
37
|
+
if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
38
|
+
return path.resolve(t);
|
|
39
|
+
}
|
|
40
|
+
function validateWorkspacePath(absPath) {
|
|
41
|
+
try {
|
|
42
|
+
if (!absPath) return { ok: false, error: "Path required" };
|
|
43
|
+
if (!fs.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
|
|
44
|
+
const st = fs.statSync(absPath);
|
|
45
|
+
if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
|
|
46
|
+
return { ok: true };
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return { ok: false, error: e?.message || "Invalid path" };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function defaultWorkspaceLabel(absPath) {
|
|
52
|
+
const base = path.basename(absPath) || absPath;
|
|
53
|
+
return base;
|
|
54
|
+
}
|
|
55
|
+
function migrateWorkspacesFromRecent(config) {
|
|
56
|
+
if (!config.workspaces) config.workspaces = [];
|
|
57
|
+
if (config.workspaces.length > 0) return config;
|
|
58
|
+
const recent = config.recentCliWorkspaces || [];
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
for (const raw of recent) {
|
|
61
|
+
const abs = expandPath(raw);
|
|
62
|
+
if (!abs || validateWorkspacePath(abs).ok !== true) continue;
|
|
63
|
+
if (config.workspaces.some((w) => path.resolve(w.path) === abs)) continue;
|
|
64
|
+
config.workspaces.push({
|
|
65
|
+
id: (0, import_crypto.randomUUID)(),
|
|
66
|
+
path: abs,
|
|
67
|
+
label: defaultWorkspaceLabel(abs),
|
|
68
|
+
addedAt: now
|
|
69
|
+
});
|
|
70
|
+
if (config.workspaces.length >= MAX_WORKSPACES) break;
|
|
71
|
+
}
|
|
72
|
+
return config;
|
|
73
|
+
}
|
|
74
|
+
function getDefaultWorkspacePath(config) {
|
|
75
|
+
const id = config.defaultWorkspaceId;
|
|
76
|
+
if (!id) return null;
|
|
77
|
+
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
78
|
+
if (!w) return null;
|
|
79
|
+
const abs = expandPath(w.path);
|
|
80
|
+
if (validateWorkspacePath(abs).ok !== true) return null;
|
|
81
|
+
return abs;
|
|
82
|
+
}
|
|
83
|
+
function getWorkspaceState(config) {
|
|
84
|
+
const workspaces = [...config.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
|
|
85
|
+
const defaultWorkspacePath = getDefaultWorkspacePath(config);
|
|
86
|
+
return {
|
|
87
|
+
workspaces,
|
|
88
|
+
defaultWorkspaceId: config.defaultWorkspaceId ?? null,
|
|
89
|
+
defaultWorkspacePath
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function resolveLaunchDirectory(args, config) {
|
|
93
|
+
const a = args || {};
|
|
94
|
+
if (a.dir != null && String(a.dir).trim()) {
|
|
95
|
+
const abs = expandPath(String(a.dir).trim());
|
|
96
|
+
if (abs && validateWorkspacePath(abs).ok === true) {
|
|
97
|
+
return { ok: true, path: abs, source: "dir" };
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
102
|
+
message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (a.workspaceId) {
|
|
106
|
+
const w = (config.workspaces || []).find((x) => x.id === a.workspaceId);
|
|
107
|
+
if (w) {
|
|
108
|
+
const abs = expandPath(w.path);
|
|
109
|
+
if (validateWorkspacePath(abs).ok === true) {
|
|
110
|
+
return { ok: true, path: abs, source: "workspaceId" };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
116
|
+
message: "Saved workspace not found or path is no longer valid"
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (a.useDefaultWorkspace === true) {
|
|
120
|
+
const d = getDefaultWorkspacePath(config);
|
|
121
|
+
if (d) return { ok: true, path: d, source: "defaultWorkspace" };
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
125
|
+
message: "No default workspace is set"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (a.useHome === true) {
|
|
129
|
+
return { ok: true, path: os.homedir(), source: "home" };
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
134
|
+
message: "Choose a directory, saved workspace, default workspace, or home before launching."
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function resolveIdeWorkspaceFromArgs(args, config) {
|
|
138
|
+
const ar = args || {};
|
|
139
|
+
if (ar.workspace) {
|
|
140
|
+
const abs = expandPath(ar.workspace);
|
|
141
|
+
if (abs && validateWorkspacePath(abs).ok === true) return abs;
|
|
142
|
+
}
|
|
143
|
+
if (ar.workspaceId) {
|
|
144
|
+
const w = (config.workspaces || []).find((x) => x.id === ar.workspaceId);
|
|
145
|
+
if (w) {
|
|
146
|
+
const abs = expandPath(w.path);
|
|
147
|
+
if (validateWorkspacePath(abs).ok === true) return abs;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (ar.useDefaultWorkspace === true) {
|
|
151
|
+
return getDefaultWorkspacePath(config) || void 0;
|
|
152
|
+
}
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
function resolveIdeLaunchWorkspace(args, config) {
|
|
156
|
+
const direct = resolveIdeWorkspaceFromArgs(args, config);
|
|
157
|
+
if (direct) return direct;
|
|
158
|
+
if (args?.useDefaultWorkspace === false) return void 0;
|
|
159
|
+
return getDefaultWorkspacePath(config) || void 0;
|
|
160
|
+
}
|
|
161
|
+
function findWorkspaceByPath(config, rawPath) {
|
|
162
|
+
const abs = path.resolve(expandPath(rawPath));
|
|
163
|
+
if (!abs) return void 0;
|
|
164
|
+
return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
|
|
165
|
+
}
|
|
166
|
+
function addWorkspaceEntry(config, rawPath, label) {
|
|
167
|
+
const abs = expandPath(rawPath);
|
|
168
|
+
const v = validateWorkspacePath(abs);
|
|
169
|
+
if (!v.ok) return { error: v.error };
|
|
170
|
+
const list = [...config.workspaces || []];
|
|
171
|
+
if (list.some((w) => path.resolve(w.path) === abs)) {
|
|
172
|
+
return { error: "Workspace already in list" };
|
|
173
|
+
}
|
|
174
|
+
if (list.length >= MAX_WORKSPACES) {
|
|
175
|
+
return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
|
|
176
|
+
}
|
|
177
|
+
const entry = {
|
|
178
|
+
id: (0, import_crypto.randomUUID)(),
|
|
179
|
+
path: abs,
|
|
180
|
+
label: (label || "").trim() || defaultWorkspaceLabel(abs),
|
|
181
|
+
addedAt: Date.now()
|
|
182
|
+
};
|
|
183
|
+
list.push(entry);
|
|
184
|
+
return { config: { ...config, workspaces: list }, entry };
|
|
185
|
+
}
|
|
186
|
+
function removeWorkspaceEntry(config, id) {
|
|
187
|
+
const list = (config.workspaces || []).filter((w) => w.id !== id);
|
|
188
|
+
if (list.length === (config.workspaces || []).length) return { error: "Workspace not found" };
|
|
189
|
+
let defaultWorkspaceId = config.defaultWorkspaceId;
|
|
190
|
+
if (defaultWorkspaceId === id) defaultWorkspaceId = null;
|
|
191
|
+
return { config: { ...config, workspaces: list, defaultWorkspaceId } };
|
|
192
|
+
}
|
|
193
|
+
function setDefaultWorkspaceId(config, id) {
|
|
194
|
+
if (id === null) {
|
|
195
|
+
return { config: { ...config, defaultWorkspaceId: null } };
|
|
196
|
+
}
|
|
197
|
+
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
198
|
+
if (!w) return { error: "Workspace not found" };
|
|
199
|
+
const abs = expandPath(w.path);
|
|
200
|
+
if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
|
|
201
|
+
return { config: { ...config, defaultWorkspaceId: id } };
|
|
202
|
+
}
|
|
203
|
+
var fs, os, path, import_crypto, MAX_WORKSPACES;
|
|
204
|
+
var init_workspaces = __esm({
|
|
205
|
+
"src/config/workspaces.ts"() {
|
|
206
|
+
"use strict";
|
|
207
|
+
fs = __toESM(require("fs"));
|
|
208
|
+
os = __toESM(require("os"));
|
|
209
|
+
path = __toESM(require("path"));
|
|
210
|
+
import_crypto = require("crypto");
|
|
211
|
+
MAX_WORKSPACES = 50;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
33
215
|
// src/config/config.ts
|
|
34
216
|
var config_exports = {};
|
|
35
217
|
__export(config_exports, {
|
|
@@ -61,7 +243,20 @@ function loadConfig() {
|
|
|
61
243
|
try {
|
|
62
244
|
const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
|
|
63
245
|
const parsed = JSON.parse(raw);
|
|
64
|
-
|
|
246
|
+
const merged = { ...DEFAULT_CONFIG, ...parsed };
|
|
247
|
+
if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
|
|
248
|
+
merged.defaultWorkspaceId = merged.activeWorkspaceId;
|
|
249
|
+
}
|
|
250
|
+
delete merged.activeWorkspaceId;
|
|
251
|
+
const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
|
|
252
|
+
migrateWorkspacesFromRecent(merged);
|
|
253
|
+
if (!hadStoredWorkspaces && (merged.workspaces?.length || 0) > 0) {
|
|
254
|
+
try {
|
|
255
|
+
saveConfig(merged);
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return merged;
|
|
65
260
|
} catch {
|
|
66
261
|
return { ...DEFAULT_CONFIG };
|
|
67
262
|
}
|
|
@@ -132,6 +327,7 @@ var init_config = __esm({
|
|
|
132
327
|
import_os = require("os");
|
|
133
328
|
import_path = require("path");
|
|
134
329
|
import_fs = require("fs");
|
|
330
|
+
init_workspaces();
|
|
135
331
|
DEFAULT_CONFIG = {
|
|
136
332
|
serverUrl: "https://api.adhf.dev",
|
|
137
333
|
apiToken: null,
|
|
@@ -148,6 +344,9 @@ var init_config = __esm({
|
|
|
148
344
|
configuredCLIs: [],
|
|
149
345
|
enabledIdes: [],
|
|
150
346
|
recentCliWorkspaces: [],
|
|
347
|
+
workspaces: [],
|
|
348
|
+
defaultWorkspaceId: null,
|
|
349
|
+
recentWorkspaceActivity: [],
|
|
151
350
|
machineNickname: null,
|
|
152
351
|
cliHistory: [],
|
|
153
352
|
providerSettings: {},
|
|
@@ -187,9 +386,12 @@ __export(index_exports, {
|
|
|
187
386
|
detectIDEs: () => detectIDEs,
|
|
188
387
|
getAIExtensions: () => getAIExtensions,
|
|
189
388
|
getAvailableIdeIds: () => getAvailableIdeIds,
|
|
389
|
+
getHostMemorySnapshot: () => getHostMemorySnapshot,
|
|
190
390
|
getLogLevel: () => getLogLevel,
|
|
191
391
|
getRecentCommands: () => getRecentCommands,
|
|
192
392
|
getRecentLogs: () => getRecentLogs,
|
|
393
|
+
getWorkspaceActivity: () => getWorkspaceActivity,
|
|
394
|
+
getWorkspaceState: () => getWorkspaceState,
|
|
193
395
|
initDaemonComponents: () => initDaemonComponents,
|
|
194
396
|
installExtensions: () => installExtensions,
|
|
195
397
|
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
@@ -212,6 +414,47 @@ __export(index_exports, {
|
|
|
212
414
|
});
|
|
213
415
|
module.exports = __toCommonJS(index_exports);
|
|
214
416
|
init_config();
|
|
417
|
+
init_workspaces();
|
|
418
|
+
|
|
419
|
+
// src/config/workspace-activity.ts
|
|
420
|
+
var path2 = __toESM(require("path"));
|
|
421
|
+
init_workspaces();
|
|
422
|
+
var MAX_ACTIVITY = 30;
|
|
423
|
+
function normWorkspacePath(p) {
|
|
424
|
+
try {
|
|
425
|
+
return path2.resolve(expandPath(p));
|
|
426
|
+
} catch {
|
|
427
|
+
return path2.resolve(p);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function appendWorkspaceActivity(config, rawPath, meta) {
|
|
431
|
+
const abs = normWorkspacePath(rawPath);
|
|
432
|
+
if (!abs) return config;
|
|
433
|
+
const prev = config.recentWorkspaceActivity || [];
|
|
434
|
+
const filtered = prev.filter((e) => normWorkspacePath(e.path) !== abs);
|
|
435
|
+
const entry = {
|
|
436
|
+
path: abs,
|
|
437
|
+
lastUsedAt: Date.now(),
|
|
438
|
+
kind: meta?.kind,
|
|
439
|
+
agentType: meta?.agentType
|
|
440
|
+
};
|
|
441
|
+
const recentWorkspaceActivity = [entry, ...filtered].slice(0, MAX_ACTIVITY);
|
|
442
|
+
return { ...config, recentWorkspaceActivity };
|
|
443
|
+
}
|
|
444
|
+
function getWorkspaceActivity(config, limit = 20) {
|
|
445
|
+
const list = [...config.recentWorkspaceActivity || []];
|
|
446
|
+
list.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
|
|
447
|
+
return list.slice(0, limit);
|
|
448
|
+
}
|
|
449
|
+
function removeActivityForPath(config, rawPath) {
|
|
450
|
+
const n = normWorkspacePath(rawPath);
|
|
451
|
+
return {
|
|
452
|
+
...config,
|
|
453
|
+
recentWorkspaceActivity: (config.recentWorkspaceActivity || []).filter(
|
|
454
|
+
(e) => normWorkspacePath(e.path) !== n
|
|
455
|
+
)
|
|
456
|
+
};
|
|
457
|
+
}
|
|
215
458
|
|
|
216
459
|
// src/detection/ide-detector.ts
|
|
217
460
|
var import_child_process = require("child_process");
|
|
@@ -271,20 +514,20 @@ function checkPathExists(paths) {
|
|
|
271
514
|
return null;
|
|
272
515
|
}
|
|
273
516
|
async function detectIDEs() {
|
|
274
|
-
const
|
|
517
|
+
const os15 = (0, import_os2.platform)();
|
|
275
518
|
const results = [];
|
|
276
519
|
for (const def of getMergedDefinitions()) {
|
|
277
520
|
const cliPath = findCliCommand(def.cli);
|
|
278
|
-
const appPath = checkPathExists(def.paths[
|
|
521
|
+
const appPath = checkPathExists(def.paths[os15] || []);
|
|
279
522
|
const installed = !!(cliPath || appPath);
|
|
280
523
|
let resolvedCli = cliPath;
|
|
281
|
-
if (!resolvedCli && appPath &&
|
|
524
|
+
if (!resolvedCli && appPath && os15 === "darwin") {
|
|
282
525
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
283
526
|
if ((0, import_fs2.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
284
527
|
}
|
|
285
|
-
if (!resolvedCli && appPath &&
|
|
286
|
-
const { dirname:
|
|
287
|
-
const appDir =
|
|
528
|
+
if (!resolvedCli && appPath && os15 === "win32") {
|
|
529
|
+
const { dirname: dirname6 } = await import("path");
|
|
530
|
+
const appDir = dirname6(appPath);
|
|
288
531
|
const candidates = [
|
|
289
532
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
290
533
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -317,22 +560,22 @@ async function detectIDEs() {
|
|
|
317
560
|
|
|
318
561
|
// src/detection/cli-detector.ts
|
|
319
562
|
var import_child_process2 = require("child_process");
|
|
320
|
-
var
|
|
563
|
+
var os2 = __toESM(require("os"));
|
|
321
564
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
322
|
-
return new Promise((
|
|
565
|
+
return new Promise((resolve7) => {
|
|
323
566
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
324
567
|
if (err || !stdout?.trim()) {
|
|
325
|
-
|
|
568
|
+
resolve7(null);
|
|
326
569
|
} else {
|
|
327
|
-
|
|
570
|
+
resolve7(stdout.trim());
|
|
328
571
|
}
|
|
329
572
|
});
|
|
330
|
-
child.on("error", () =>
|
|
573
|
+
child.on("error", () => resolve7(null));
|
|
331
574
|
});
|
|
332
575
|
}
|
|
333
576
|
async function detectCLIs(providerLoader) {
|
|
334
|
-
const
|
|
335
|
-
const whichCmd =
|
|
577
|
+
const platform8 = os2.platform();
|
|
578
|
+
const whichCmd = platform8 === "win32" ? "where" : "which";
|
|
336
579
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
337
580
|
const results = await Promise.all(
|
|
338
581
|
cliList.map(async (cli) => {
|
|
@@ -363,14 +606,56 @@ async function detectCLI(cliId, providerLoader) {
|
|
|
363
606
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
364
607
|
}
|
|
365
608
|
|
|
609
|
+
// src/system/host-memory.ts
|
|
610
|
+
var os3 = __toESM(require("os"));
|
|
611
|
+
var import_child_process3 = require("child_process");
|
|
612
|
+
function parseDarwinAvailableBytes(totalMem) {
|
|
613
|
+
if (os3.platform() !== "darwin") return null;
|
|
614
|
+
try {
|
|
615
|
+
const out = (0, import_child_process3.execSync)("vm_stat", {
|
|
616
|
+
encoding: "utf-8",
|
|
617
|
+
timeout: 4e3,
|
|
618
|
+
maxBuffer: 256 * 1024
|
|
619
|
+
});
|
|
620
|
+
const pageSizeMatch = out.match(/page size of (\d+)\s*bytes/i);
|
|
621
|
+
const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 4096;
|
|
622
|
+
const counts = {};
|
|
623
|
+
for (const line of out.split("\n")) {
|
|
624
|
+
const m = line.match(/^\s*Pages\s+([^:]+):\s+([\d,]+)\s*\.?/);
|
|
625
|
+
if (!m) continue;
|
|
626
|
+
const key = m[1].trim().toLowerCase().replace(/\s+/g, "_");
|
|
627
|
+
const n = parseInt(m[2].replace(/,/g, ""), 10);
|
|
628
|
+
if (!Number.isNaN(n)) counts[key] = n;
|
|
629
|
+
}
|
|
630
|
+
const free = counts["free"] ?? 0;
|
|
631
|
+
const inactive = counts["inactive"] ?? 0;
|
|
632
|
+
const speculative = counts["speculative"] ?? 0;
|
|
633
|
+
const purgeable = counts["purgeable"] ?? 0;
|
|
634
|
+
const fileBacked = counts["file_backed"] ?? 0;
|
|
635
|
+
const availPages = free + inactive + speculative + purgeable + fileBacked;
|
|
636
|
+
const bytes = availPages * pageSize;
|
|
637
|
+
if (!Number.isFinite(bytes) || bytes < 0) return null;
|
|
638
|
+
return Math.min(bytes, totalMem);
|
|
639
|
+
} catch {
|
|
640
|
+
return null;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function getHostMemorySnapshot() {
|
|
644
|
+
const totalMem = os3.totalmem();
|
|
645
|
+
const freeMem = os3.freemem();
|
|
646
|
+
const darwinAvail = parseDarwinAvailableBytes(totalMem);
|
|
647
|
+
const availableMem = darwinAvail != null ? darwinAvail : freeMem;
|
|
648
|
+
return { totalMem, freeMem, availableMem };
|
|
649
|
+
}
|
|
650
|
+
|
|
366
651
|
// src/cdp/manager.ts
|
|
367
652
|
var import_ws = __toESM(require("ws"));
|
|
368
653
|
var http = __toESM(require("http"));
|
|
369
654
|
|
|
370
655
|
// src/logging/logger.ts
|
|
371
|
-
var
|
|
372
|
-
var
|
|
373
|
-
var
|
|
656
|
+
var fs2 = __toESM(require("fs"));
|
|
657
|
+
var path3 = __toESM(require("path"));
|
|
658
|
+
var os4 = __toESM(require("os"));
|
|
374
659
|
var LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
375
660
|
var LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
376
661
|
var currentLevel = "info";
|
|
@@ -381,29 +666,29 @@ function setLogLevel(level) {
|
|
|
381
666
|
function getLogLevel() {
|
|
382
667
|
return currentLevel;
|
|
383
668
|
}
|
|
384
|
-
var LOG_DIR = process.platform === "darwin" ?
|
|
669
|
+
var LOG_DIR = process.platform === "darwin" ? path3.join(os4.homedir(), "Library", "Logs", "adhdev") : path3.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
385
670
|
var MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
386
671
|
var MAX_LOG_DAYS = 7;
|
|
387
672
|
try {
|
|
388
|
-
|
|
673
|
+
fs2.mkdirSync(LOG_DIR, { recursive: true });
|
|
389
674
|
} catch {
|
|
390
675
|
}
|
|
391
676
|
function getDateStr() {
|
|
392
677
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
393
678
|
}
|
|
394
679
|
var currentDate = getDateStr();
|
|
395
|
-
var currentLogFile =
|
|
680
|
+
var currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
396
681
|
function checkDateRotation() {
|
|
397
682
|
const today = getDateStr();
|
|
398
683
|
if (today !== currentDate) {
|
|
399
684
|
currentDate = today;
|
|
400
|
-
currentLogFile =
|
|
685
|
+
currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
401
686
|
cleanOldLogs();
|
|
402
687
|
}
|
|
403
688
|
}
|
|
404
689
|
function cleanOldLogs() {
|
|
405
690
|
try {
|
|
406
|
-
const files =
|
|
691
|
+
const files = fs2.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
407
692
|
const cutoff = /* @__PURE__ */ new Date();
|
|
408
693
|
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
409
694
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -411,7 +696,7 @@ function cleanOldLogs() {
|
|
|
411
696
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
412
697
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
413
698
|
try {
|
|
414
|
-
|
|
699
|
+
fs2.unlinkSync(path3.join(LOG_DIR, file));
|
|
415
700
|
} catch {
|
|
416
701
|
}
|
|
417
702
|
}
|
|
@@ -421,29 +706,29 @@ function cleanOldLogs() {
|
|
|
421
706
|
}
|
|
422
707
|
function rotateSizeIfNeeded() {
|
|
423
708
|
try {
|
|
424
|
-
const stat =
|
|
709
|
+
const stat = fs2.statSync(currentLogFile);
|
|
425
710
|
if (stat.size > MAX_LOG_SIZE) {
|
|
426
711
|
const backup = currentLogFile.replace(".log", ".1.log");
|
|
427
712
|
try {
|
|
428
|
-
|
|
713
|
+
fs2.unlinkSync(backup);
|
|
429
714
|
} catch {
|
|
430
715
|
}
|
|
431
|
-
|
|
716
|
+
fs2.renameSync(currentLogFile, backup);
|
|
432
717
|
}
|
|
433
718
|
} catch {
|
|
434
719
|
}
|
|
435
720
|
}
|
|
436
721
|
cleanOldLogs();
|
|
437
722
|
try {
|
|
438
|
-
const oldLog =
|
|
439
|
-
if (
|
|
440
|
-
const stat =
|
|
723
|
+
const oldLog = path3.join(LOG_DIR, "daemon.log");
|
|
724
|
+
if (fs2.existsSync(oldLog)) {
|
|
725
|
+
const stat = fs2.statSync(oldLog);
|
|
441
726
|
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
442
|
-
|
|
727
|
+
fs2.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
443
728
|
}
|
|
444
|
-
const oldLogBackup =
|
|
445
|
-
if (
|
|
446
|
-
|
|
729
|
+
const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
|
|
730
|
+
if (fs2.existsSync(oldLogBackup)) {
|
|
731
|
+
fs2.unlinkSync(oldLogBackup);
|
|
447
732
|
}
|
|
448
733
|
} catch {
|
|
449
734
|
}
|
|
@@ -454,7 +739,7 @@ function writeToFile(line) {
|
|
|
454
739
|
checkDateRotation();
|
|
455
740
|
rotateSizeIfNeeded();
|
|
456
741
|
}
|
|
457
|
-
|
|
742
|
+
fs2.appendFileSync(currentLogFile, line + "\n");
|
|
458
743
|
} catch {
|
|
459
744
|
}
|
|
460
745
|
}
|
|
@@ -568,7 +853,7 @@ function installGlobalInterceptor() {
|
|
|
568
853
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
569
854
|
writeToFile(`Log level: ${currentLevel}`);
|
|
570
855
|
}
|
|
571
|
-
var LOG_PATH =
|
|
856
|
+
var LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
572
857
|
|
|
573
858
|
// src/cdp/manager.ts
|
|
574
859
|
var DaemonCdpManager = class {
|
|
@@ -643,7 +928,7 @@ var DaemonCdpManager = class {
|
|
|
643
928
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
644
929
|
*/
|
|
645
930
|
static listAllTargets(port) {
|
|
646
|
-
return new Promise((
|
|
931
|
+
return new Promise((resolve7) => {
|
|
647
932
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
648
933
|
let data = "";
|
|
649
934
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -659,16 +944,16 @@ var DaemonCdpManager = class {
|
|
|
659
944
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
660
945
|
);
|
|
661
946
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
662
|
-
|
|
947
|
+
resolve7(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
663
948
|
} catch {
|
|
664
|
-
|
|
949
|
+
resolve7([]);
|
|
665
950
|
}
|
|
666
951
|
});
|
|
667
952
|
});
|
|
668
|
-
req.on("error", () =>
|
|
953
|
+
req.on("error", () => resolve7([]));
|
|
669
954
|
req.setTimeout(2e3, () => {
|
|
670
955
|
req.destroy();
|
|
671
|
-
|
|
956
|
+
resolve7([]);
|
|
672
957
|
});
|
|
673
958
|
});
|
|
674
959
|
}
|
|
@@ -708,7 +993,7 @@ var DaemonCdpManager = class {
|
|
|
708
993
|
}
|
|
709
994
|
}
|
|
710
995
|
findTargetOnPort(port) {
|
|
711
|
-
return new Promise((
|
|
996
|
+
return new Promise((resolve7) => {
|
|
712
997
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
713
998
|
let data = "";
|
|
714
999
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -719,7 +1004,7 @@ var DaemonCdpManager = class {
|
|
|
719
1004
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
720
1005
|
);
|
|
721
1006
|
if (pages.length === 0) {
|
|
722
|
-
|
|
1007
|
+
resolve7(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
723
1008
|
return;
|
|
724
1009
|
}
|
|
725
1010
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -729,24 +1014,24 @@ var DaemonCdpManager = class {
|
|
|
729
1014
|
const specific = list.find((t) => t.id === this._targetId);
|
|
730
1015
|
if (specific) {
|
|
731
1016
|
this._pageTitle = specific.title || "";
|
|
732
|
-
|
|
1017
|
+
resolve7(specific);
|
|
733
1018
|
} else {
|
|
734
1019
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
735
|
-
|
|
1020
|
+
resolve7(null);
|
|
736
1021
|
}
|
|
737
1022
|
return;
|
|
738
1023
|
}
|
|
739
1024
|
this._pageTitle = list[0]?.title || "";
|
|
740
|
-
|
|
1025
|
+
resolve7(list[0]);
|
|
741
1026
|
} catch {
|
|
742
|
-
|
|
1027
|
+
resolve7(null);
|
|
743
1028
|
}
|
|
744
1029
|
});
|
|
745
1030
|
});
|
|
746
|
-
req.on("error", () =>
|
|
1031
|
+
req.on("error", () => resolve7(null));
|
|
747
1032
|
req.setTimeout(2e3, () => {
|
|
748
1033
|
req.destroy();
|
|
749
|
-
|
|
1034
|
+
resolve7(null);
|
|
750
1035
|
});
|
|
751
1036
|
});
|
|
752
1037
|
}
|
|
@@ -757,7 +1042,7 @@ var DaemonCdpManager = class {
|
|
|
757
1042
|
this.extensionProviders = providers;
|
|
758
1043
|
}
|
|
759
1044
|
connectToTarget(wsUrl) {
|
|
760
|
-
return new Promise((
|
|
1045
|
+
return new Promise((resolve7) => {
|
|
761
1046
|
this.ws = new import_ws.default(wsUrl);
|
|
762
1047
|
this.ws.on("open", async () => {
|
|
763
1048
|
this._connected = true;
|
|
@@ -767,17 +1052,17 @@ var DaemonCdpManager = class {
|
|
|
767
1052
|
}
|
|
768
1053
|
this.connectBrowserWs().catch(() => {
|
|
769
1054
|
});
|
|
770
|
-
|
|
1055
|
+
resolve7(true);
|
|
771
1056
|
});
|
|
772
1057
|
this.ws.on("message", (data) => {
|
|
773
1058
|
try {
|
|
774
1059
|
const msg = JSON.parse(data.toString());
|
|
775
1060
|
if (msg.id && this.pending.has(msg.id)) {
|
|
776
|
-
const { resolve:
|
|
1061
|
+
const { resolve: resolve8, reject } = this.pending.get(msg.id);
|
|
777
1062
|
this.pending.delete(msg.id);
|
|
778
1063
|
this.failureCount = 0;
|
|
779
1064
|
if (msg.error) reject(new Error(msg.error.message));
|
|
780
|
-
else
|
|
1065
|
+
else resolve8(msg.result);
|
|
781
1066
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
782
1067
|
this.contexts.add(msg.params.context.id);
|
|
783
1068
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -800,7 +1085,7 @@ var DaemonCdpManager = class {
|
|
|
800
1085
|
this.ws.on("error", (err) => {
|
|
801
1086
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
802
1087
|
this._connected = false;
|
|
803
|
-
|
|
1088
|
+
resolve7(false);
|
|
804
1089
|
});
|
|
805
1090
|
});
|
|
806
1091
|
}
|
|
@@ -814,7 +1099,7 @@ var DaemonCdpManager = class {
|
|
|
814
1099
|
return;
|
|
815
1100
|
}
|
|
816
1101
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
817
|
-
await new Promise((
|
|
1102
|
+
await new Promise((resolve7, reject) => {
|
|
818
1103
|
this.browserWs = new import_ws.default(browserWsUrl);
|
|
819
1104
|
this.browserWs.on("open", async () => {
|
|
820
1105
|
this._browserConnected = true;
|
|
@@ -824,16 +1109,16 @@ var DaemonCdpManager = class {
|
|
|
824
1109
|
} catch (e) {
|
|
825
1110
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
826
1111
|
}
|
|
827
|
-
|
|
1112
|
+
resolve7();
|
|
828
1113
|
});
|
|
829
1114
|
this.browserWs.on("message", (data) => {
|
|
830
1115
|
try {
|
|
831
1116
|
const msg = JSON.parse(data.toString());
|
|
832
1117
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
833
|
-
const { resolve:
|
|
1118
|
+
const { resolve: resolve8, reject: reject2 } = this.browserPending.get(msg.id);
|
|
834
1119
|
this.browserPending.delete(msg.id);
|
|
835
1120
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
836
|
-
else
|
|
1121
|
+
else resolve8(msg.result);
|
|
837
1122
|
}
|
|
838
1123
|
} catch {
|
|
839
1124
|
}
|
|
@@ -853,31 +1138,31 @@ var DaemonCdpManager = class {
|
|
|
853
1138
|
}
|
|
854
1139
|
}
|
|
855
1140
|
getBrowserWsUrl() {
|
|
856
|
-
return new Promise((
|
|
1141
|
+
return new Promise((resolve7) => {
|
|
857
1142
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
858
1143
|
let data = "";
|
|
859
1144
|
res.on("data", (chunk) => data += chunk.toString());
|
|
860
1145
|
res.on("end", () => {
|
|
861
1146
|
try {
|
|
862
1147
|
const info = JSON.parse(data);
|
|
863
|
-
|
|
1148
|
+
resolve7(info.webSocketDebuggerUrl || null);
|
|
864
1149
|
} catch {
|
|
865
|
-
|
|
1150
|
+
resolve7(null);
|
|
866
1151
|
}
|
|
867
1152
|
});
|
|
868
1153
|
});
|
|
869
|
-
req.on("error", () =>
|
|
1154
|
+
req.on("error", () => resolve7(null));
|
|
870
1155
|
req.setTimeout(3e3, () => {
|
|
871
1156
|
req.destroy();
|
|
872
|
-
|
|
1157
|
+
resolve7(null);
|
|
873
1158
|
});
|
|
874
1159
|
});
|
|
875
1160
|
}
|
|
876
1161
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
877
|
-
return new Promise((
|
|
1162
|
+
return new Promise((resolve7, reject) => {
|
|
878
1163
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
879
1164
|
const id = this.browserMsgId++;
|
|
880
|
-
this.browserPending.set(id, { resolve:
|
|
1165
|
+
this.browserPending.set(id, { resolve: resolve7, reject });
|
|
881
1166
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
882
1167
|
setTimeout(() => {
|
|
883
1168
|
if (this.browserPending.has(id)) {
|
|
@@ -917,11 +1202,11 @@ var DaemonCdpManager = class {
|
|
|
917
1202
|
}
|
|
918
1203
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
919
1204
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
920
|
-
return new Promise((
|
|
1205
|
+
return new Promise((resolve7, reject) => {
|
|
921
1206
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
922
1207
|
if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
923
1208
|
const id = this.msgId++;
|
|
924
|
-
this.pending.set(id, { resolve:
|
|
1209
|
+
this.pending.set(id, { resolve: resolve7, reject });
|
|
925
1210
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
926
1211
|
setTimeout(() => {
|
|
927
1212
|
if (this.pending.has(id)) {
|
|
@@ -1130,7 +1415,7 @@ var DaemonCdpManager = class {
|
|
|
1130
1415
|
const browserWs = this.browserWs;
|
|
1131
1416
|
let msgId = this.browserMsgId;
|
|
1132
1417
|
const sendWs = (method, params = {}, sessionId) => {
|
|
1133
|
-
return new Promise((
|
|
1418
|
+
return new Promise((resolve7, reject) => {
|
|
1134
1419
|
const mid = msgId++;
|
|
1135
1420
|
this.browserMsgId = msgId;
|
|
1136
1421
|
const handler = (raw) => {
|
|
@@ -1139,7 +1424,7 @@ var DaemonCdpManager = class {
|
|
|
1139
1424
|
if (msg.id === mid) {
|
|
1140
1425
|
browserWs.removeListener("message", handler);
|
|
1141
1426
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
1142
|
-
else
|
|
1427
|
+
else resolve7(msg.result);
|
|
1143
1428
|
}
|
|
1144
1429
|
} catch {
|
|
1145
1430
|
}
|
|
@@ -1313,14 +1598,14 @@ var DaemonCdpManager = class {
|
|
|
1313
1598
|
if (!ws || ws.readyState !== import_ws.default.OPEN) {
|
|
1314
1599
|
throw new Error("CDP not connected");
|
|
1315
1600
|
}
|
|
1316
|
-
return new Promise((
|
|
1601
|
+
return new Promise((resolve7, reject) => {
|
|
1317
1602
|
const id = getNextId();
|
|
1318
1603
|
pendingMap.set(id, {
|
|
1319
1604
|
resolve: (result) => {
|
|
1320
1605
|
if (result?.result?.subtype === "error") {
|
|
1321
1606
|
reject(new Error(result.result.description));
|
|
1322
1607
|
} else {
|
|
1323
|
-
|
|
1608
|
+
resolve7(result?.result?.value);
|
|
1324
1609
|
}
|
|
1325
1610
|
},
|
|
1326
1611
|
reject
|
|
@@ -1901,10 +2186,10 @@ var ExtensionProviderInstance = class {
|
|
|
1901
2186
|
};
|
|
1902
2187
|
|
|
1903
2188
|
// src/config/chat-history.ts
|
|
1904
|
-
var
|
|
1905
|
-
var
|
|
1906
|
-
var
|
|
1907
|
-
var HISTORY_DIR =
|
|
2189
|
+
var fs3 = __toESM(require("fs"));
|
|
2190
|
+
var path4 = __toESM(require("path"));
|
|
2191
|
+
var os5 = __toESM(require("os"));
|
|
2192
|
+
var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
|
|
1908
2193
|
var RETAIN_DAYS = 30;
|
|
1909
2194
|
var ChatHistoryWriter = class {
|
|
1910
2195
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -1945,13 +2230,13 @@ var ChatHistoryWriter = class {
|
|
|
1945
2230
|
});
|
|
1946
2231
|
}
|
|
1947
2232
|
if (newMessages.length === 0) return;
|
|
1948
|
-
const dir =
|
|
1949
|
-
|
|
2233
|
+
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
2234
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
1950
2235
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1951
2236
|
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
1952
|
-
const filePath =
|
|
2237
|
+
const filePath = path4.join(dir, `${filePrefix}${date}.jsonl`);
|
|
1953
2238
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
1954
|
-
|
|
2239
|
+
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
1955
2240
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
1956
2241
|
if (messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
1957
2242
|
seenHashes.clear();
|
|
@@ -1976,17 +2261,17 @@ var ChatHistoryWriter = class {
|
|
|
1976
2261
|
/** Delete history files older than 30 days */
|
|
1977
2262
|
async rotateOldFiles() {
|
|
1978
2263
|
try {
|
|
1979
|
-
if (!
|
|
2264
|
+
if (!fs3.existsSync(HISTORY_DIR)) return;
|
|
1980
2265
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
1981
|
-
const agentDirs =
|
|
2266
|
+
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1982
2267
|
for (const dir of agentDirs) {
|
|
1983
|
-
const dirPath =
|
|
1984
|
-
const files =
|
|
2268
|
+
const dirPath = path4.join(HISTORY_DIR, dir.name);
|
|
2269
|
+
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
1985
2270
|
for (const file of files) {
|
|
1986
|
-
const filePath =
|
|
1987
|
-
const stat =
|
|
2271
|
+
const filePath = path4.join(dirPath, file);
|
|
2272
|
+
const stat = fs3.statSync(filePath);
|
|
1988
2273
|
if (stat.mtimeMs < cutoff) {
|
|
1989
|
-
|
|
2274
|
+
fs3.unlinkSync(filePath);
|
|
1990
2275
|
}
|
|
1991
2276
|
}
|
|
1992
2277
|
}
|
|
@@ -2001,10 +2286,10 @@ var ChatHistoryWriter = class {
|
|
|
2001
2286
|
function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
|
|
2002
2287
|
try {
|
|
2003
2288
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2004
|
-
const dir =
|
|
2005
|
-
if (!
|
|
2289
|
+
const dir = path4.join(HISTORY_DIR, sanitized);
|
|
2290
|
+
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
2006
2291
|
const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2007
|
-
const files =
|
|
2292
|
+
const files = fs3.readdirSync(dir).filter((f) => {
|
|
2008
2293
|
if (!f.endsWith(".jsonl")) return false;
|
|
2009
2294
|
if (sanitizedInstance) {
|
|
2010
2295
|
return f.startsWith(`${sanitizedInstance}_`);
|
|
@@ -2015,8 +2300,8 @@ function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
|
|
|
2015
2300
|
const needed = offset + limit + 1;
|
|
2016
2301
|
for (const file of files) {
|
|
2017
2302
|
if (allMessages.length >= needed) break;
|
|
2018
|
-
const filePath =
|
|
2019
|
-
const content =
|
|
2303
|
+
const filePath = path4.join(dir, file);
|
|
2304
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
2020
2305
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
2021
2306
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2022
2307
|
if (allMessages.length >= needed) break;
|
|
@@ -2256,6 +2541,15 @@ var IdeProviderInstance = class {
|
|
|
2256
2541
|
const h = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
|
|
2257
2542
|
msg.receivedAt = prevByHash.get(h) || now;
|
|
2258
2543
|
}
|
|
2544
|
+
if (raw.messages?.length > 0) {
|
|
2545
|
+
const hiddenKinds = /* @__PURE__ */ new Set();
|
|
2546
|
+
if (this.settings.showThinking === false) hiddenKinds.add("thought");
|
|
2547
|
+
if (this.settings.showToolCalls === false) hiddenKinds.add("tool");
|
|
2548
|
+
if (this.settings.showTerminal === false) hiddenKinds.add("terminal");
|
|
2549
|
+
if (hiddenKinds.size > 0) {
|
|
2550
|
+
raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2259
2553
|
this.cachedChat = { ...raw, activeModal };
|
|
2260
2554
|
this.detectAgentTransitions(raw, now);
|
|
2261
2555
|
if (raw.messages?.length > 0) {
|
|
@@ -3360,9 +3654,9 @@ async function handleResolveAction(h, args) {
|
|
|
3360
3654
|
}
|
|
3361
3655
|
|
|
3362
3656
|
// src/commands/cdp-commands.ts
|
|
3363
|
-
var
|
|
3364
|
-
var
|
|
3365
|
-
var
|
|
3657
|
+
var fs4 = __toESM(require("fs"));
|
|
3658
|
+
var path5 = __toESM(require("path"));
|
|
3659
|
+
var os6 = __toESM(require("os"));
|
|
3366
3660
|
async function handleCdpEval(h, args) {
|
|
3367
3661
|
if (!h.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3368
3662
|
const expression = args?.expression || args?.script;
|
|
@@ -3514,21 +3808,21 @@ async function handleDiscoverAgents(h, args) {
|
|
|
3514
3808
|
return { success: true, agents };
|
|
3515
3809
|
}
|
|
3516
3810
|
function resolveSafePath(requestedPath) {
|
|
3517
|
-
const home =
|
|
3811
|
+
const home = os6.homedir();
|
|
3518
3812
|
let resolved;
|
|
3519
3813
|
if (requestedPath.startsWith("~")) {
|
|
3520
|
-
resolved =
|
|
3521
|
-
} else if (
|
|
3814
|
+
resolved = path5.join(home, requestedPath.slice(1));
|
|
3815
|
+
} else if (path5.isAbsolute(requestedPath)) {
|
|
3522
3816
|
resolved = requestedPath;
|
|
3523
3817
|
} else {
|
|
3524
|
-
resolved =
|
|
3818
|
+
resolved = path5.resolve(requestedPath);
|
|
3525
3819
|
}
|
|
3526
3820
|
return resolved;
|
|
3527
3821
|
}
|
|
3528
3822
|
async function handleFileRead(h, args) {
|
|
3529
3823
|
try {
|
|
3530
3824
|
const filePath = resolveSafePath(args?.path);
|
|
3531
|
-
const content =
|
|
3825
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
3532
3826
|
return { success: true, content, path: filePath };
|
|
3533
3827
|
} catch (e) {
|
|
3534
3828
|
return { success: false, error: e.message };
|
|
@@ -3537,8 +3831,8 @@ async function handleFileRead(h, args) {
|
|
|
3537
3831
|
async function handleFileWrite(h, args) {
|
|
3538
3832
|
try {
|
|
3539
3833
|
const filePath = resolveSafePath(args?.path);
|
|
3540
|
-
|
|
3541
|
-
|
|
3834
|
+
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
3835
|
+
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
3542
3836
|
return { success: true, path: filePath };
|
|
3543
3837
|
} catch (e) {
|
|
3544
3838
|
return { success: false, error: e.message };
|
|
@@ -3547,11 +3841,11 @@ async function handleFileWrite(h, args) {
|
|
|
3547
3841
|
async function handleFileList(h, args) {
|
|
3548
3842
|
try {
|
|
3549
3843
|
const dirPath = resolveSafePath(args?.path || ".");
|
|
3550
|
-
const entries =
|
|
3844
|
+
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
3551
3845
|
const files = entries.map((e) => ({
|
|
3552
3846
|
name: e.name,
|
|
3553
3847
|
type: e.isDirectory() ? "directory" : "file",
|
|
3554
|
-
size: e.isFile() ?
|
|
3848
|
+
size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
|
|
3555
3849
|
}));
|
|
3556
3850
|
return { success: true, files, path: dirPath };
|
|
3557
3851
|
} catch (e) {
|
|
@@ -3841,7 +4135,95 @@ function handleSetIdeExtension(h, args) {
|
|
|
3841
4135
|
return { success: false, error: "Failed to save setting" };
|
|
3842
4136
|
}
|
|
3843
4137
|
|
|
4138
|
+
// src/commands/workspace-commands.ts
|
|
4139
|
+
init_config();
|
|
4140
|
+
init_workspaces();
|
|
4141
|
+
function handleWorkspaceList() {
|
|
4142
|
+
const config = loadConfig();
|
|
4143
|
+
const state = getWorkspaceState(config);
|
|
4144
|
+
return {
|
|
4145
|
+
success: true,
|
|
4146
|
+
workspaces: state.workspaces,
|
|
4147
|
+
defaultWorkspaceId: state.defaultWorkspaceId,
|
|
4148
|
+
defaultWorkspacePath: state.defaultWorkspacePath,
|
|
4149
|
+
legacyRecentPaths: config.recentCliWorkspaces || [],
|
|
4150
|
+
activity: getWorkspaceActivity(config, 25)
|
|
4151
|
+
};
|
|
4152
|
+
}
|
|
4153
|
+
function handleWorkspaceAdd(args) {
|
|
4154
|
+
const rawPath = (args?.path || args?.dir || "").trim();
|
|
4155
|
+
const label = (args?.label || "").trim() || void 0;
|
|
4156
|
+
if (!rawPath) return { success: false, error: "path required" };
|
|
4157
|
+
const config = loadConfig();
|
|
4158
|
+
const result = addWorkspaceEntry(config, rawPath, label);
|
|
4159
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
4160
|
+
let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
|
|
4161
|
+
saveConfig(cfg);
|
|
4162
|
+
const state = getWorkspaceState(cfg);
|
|
4163
|
+
return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
4164
|
+
}
|
|
4165
|
+
function handleWorkspaceRemove(args) {
|
|
4166
|
+
const id = (args?.id || "").trim();
|
|
4167
|
+
if (!id) return { success: false, error: "id required" };
|
|
4168
|
+
const config = loadConfig();
|
|
4169
|
+
const removed = (config.workspaces || []).find((w) => w.id === id);
|
|
4170
|
+
const result = removeWorkspaceEntry(config, id);
|
|
4171
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
4172
|
+
let cfg = result.config;
|
|
4173
|
+
if (removed) {
|
|
4174
|
+
cfg = removeActivityForPath(cfg, removed.path);
|
|
4175
|
+
}
|
|
4176
|
+
saveConfig(cfg);
|
|
4177
|
+
const state = getWorkspaceState(cfg);
|
|
4178
|
+
return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
4179
|
+
}
|
|
4180
|
+
function handleWorkspaceSetDefault(args) {
|
|
4181
|
+
const clear = args?.clear === true || args?.id === null || args?.id === "";
|
|
4182
|
+
if (clear) {
|
|
4183
|
+
const config2 = loadConfig();
|
|
4184
|
+
const result2 = setDefaultWorkspaceId(config2, null);
|
|
4185
|
+
if ("error" in result2) return { success: false, error: result2.error };
|
|
4186
|
+
saveConfig(result2.config);
|
|
4187
|
+
const state2 = getWorkspaceState(result2.config);
|
|
4188
|
+
return {
|
|
4189
|
+
success: true,
|
|
4190
|
+
...state2,
|
|
4191
|
+
activity: getWorkspaceActivity(result2.config, 25)
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
const pathArg = args?.path != null && String(args.path).trim() ? String(args.path).trim() : "";
|
|
4195
|
+
const idArg = args?.id !== void 0 && args?.id !== null && String(args.id).trim() ? String(args.id).trim() : "";
|
|
4196
|
+
if (!pathArg && !idArg) {
|
|
4197
|
+
return { success: false, error: "id or path required (or clear: true)" };
|
|
4198
|
+
}
|
|
4199
|
+
let config = loadConfig();
|
|
4200
|
+
let nextId;
|
|
4201
|
+
if (pathArg) {
|
|
4202
|
+
let w = findWorkspaceByPath(config, pathArg);
|
|
4203
|
+
if (!w) {
|
|
4204
|
+
const add = addWorkspaceEntry(config, pathArg);
|
|
4205
|
+
if ("error" in add) return { success: false, error: add.error };
|
|
4206
|
+
config = add.config;
|
|
4207
|
+
w = add.entry;
|
|
4208
|
+
}
|
|
4209
|
+
nextId = w.id;
|
|
4210
|
+
} else {
|
|
4211
|
+
nextId = idArg;
|
|
4212
|
+
}
|
|
4213
|
+
const result = setDefaultWorkspaceId(config, nextId);
|
|
4214
|
+
if ("error" in result) return { success: false, error: result.error };
|
|
4215
|
+
let out = result.config;
|
|
4216
|
+
const ap = getDefaultWorkspacePath(out);
|
|
4217
|
+
if (ap) {
|
|
4218
|
+
out = appendWorkspaceActivity(out, ap, { kind: "default" });
|
|
4219
|
+
}
|
|
4220
|
+
saveConfig(out);
|
|
4221
|
+
const state = getWorkspaceState(out);
|
|
4222
|
+
return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
|
|
4223
|
+
}
|
|
4224
|
+
|
|
3844
4225
|
// src/commands/handler.ts
|
|
4226
|
+
init_workspaces();
|
|
3845
4227
|
var DaemonCommandHandler = class {
|
|
3846
4228
|
_ctx;
|
|
3847
4229
|
_agentStream = null;
|
|
@@ -3950,6 +4332,9 @@ var DaemonCommandHandler = class {
|
|
|
3950
4332
|
}
|
|
3951
4333
|
/** Extract ideType from _targetInstance */
|
|
3952
4334
|
extractIdeType(args) {
|
|
4335
|
+
if (args?.ideType && this._ctx.cdpManagers.has(args.ideType)) {
|
|
4336
|
+
return args.ideType;
|
|
4337
|
+
}
|
|
3953
4338
|
if (args?._targetInstance) {
|
|
3954
4339
|
let raw = args._targetInstance;
|
|
3955
4340
|
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
@@ -3961,8 +4346,19 @@ var DaemonCommandHandler = class {
|
|
|
3961
4346
|
if (this._ctx.instanceIdMap?.has(raw)) {
|
|
3962
4347
|
return this._ctx.instanceIdMap.get(raw);
|
|
3963
4348
|
}
|
|
4349
|
+
if (this._ctx.cdpManagers.has(raw)) {
|
|
4350
|
+
return raw;
|
|
4351
|
+
}
|
|
4352
|
+
if (!ideMatch && !cliMatch && !acpMatch) {
|
|
4353
|
+
for (const [key, mgr] of this._ctx.cdpManagers.entries()) {
|
|
4354
|
+
if (mgr.isConnected) return key;
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
3964
4357
|
const lastUnderscore = raw.lastIndexOf("_");
|
|
3965
|
-
if (lastUnderscore > 0)
|
|
4358
|
+
if (lastUnderscore > 0) {
|
|
4359
|
+
const stripped = raw.substring(0, lastUnderscore);
|
|
4360
|
+
if (this._ctx.cdpManagers.has(stripped)) return stripped;
|
|
4361
|
+
}
|
|
3966
4362
|
return raw;
|
|
3967
4363
|
}
|
|
3968
4364
|
return void 0;
|
|
@@ -4058,6 +4454,19 @@ var DaemonCommandHandler = class {
|
|
|
4058
4454
|
return { success: false, error: `${cmd} requires bridge-extension (removed)` };
|
|
4059
4455
|
case "get_recent_workspaces":
|
|
4060
4456
|
return this.handleGetRecentWorkspaces(args);
|
|
4457
|
+
case "get_cli_history": {
|
|
4458
|
+
const config = loadConfig();
|
|
4459
|
+
return { success: true, history: config.cliHistory || [] };
|
|
4460
|
+
}
|
|
4461
|
+
case "workspace_list":
|
|
4462
|
+
return handleWorkspaceList();
|
|
4463
|
+
case "workspace_add":
|
|
4464
|
+
return handleWorkspaceAdd(args);
|
|
4465
|
+
case "workspace_remove":
|
|
4466
|
+
return handleWorkspaceRemove(args);
|
|
4467
|
+
case "workspace_set_default":
|
|
4468
|
+
case "workspace_set_active":
|
|
4469
|
+
return handleWorkspaceSetDefault(args);
|
|
4061
4470
|
// ─── Script manage ───────────────────
|
|
4062
4471
|
case "refresh_scripts":
|
|
4063
4472
|
return this.handleRefreshScripts(args);
|
|
@@ -4107,10 +4516,18 @@ var DaemonCommandHandler = class {
|
|
|
4107
4516
|
}
|
|
4108
4517
|
}
|
|
4109
4518
|
// ─── Misc (kept in handler — too small to extract) ───────
|
|
4110
|
-
async handleGetRecentWorkspaces(
|
|
4519
|
+
async handleGetRecentWorkspaces(_args) {
|
|
4111
4520
|
const config = loadConfig();
|
|
4112
4521
|
const cliRecent = config.recentCliWorkspaces || [];
|
|
4113
|
-
|
|
4522
|
+
const ws = getWorkspaceState(config);
|
|
4523
|
+
return {
|
|
4524
|
+
success: true,
|
|
4525
|
+
result: cliRecent,
|
|
4526
|
+
workspaces: ws.workspaces,
|
|
4527
|
+
defaultWorkspaceId: ws.defaultWorkspaceId,
|
|
4528
|
+
defaultWorkspacePath: ws.defaultWorkspacePath,
|
|
4529
|
+
activity: getWorkspaceActivity(config, 25)
|
|
4530
|
+
};
|
|
4114
4531
|
}
|
|
4115
4532
|
async handleRefreshScripts(_args) {
|
|
4116
4533
|
if (this._ctx.providerLoader) {
|
|
@@ -4122,15 +4539,15 @@ var DaemonCommandHandler = class {
|
|
|
4122
4539
|
};
|
|
4123
4540
|
|
|
4124
4541
|
// src/launch.ts
|
|
4125
|
-
var
|
|
4542
|
+
var import_child_process4 = require("child_process");
|
|
4126
4543
|
var net = __toESM(require("net"));
|
|
4127
|
-
var
|
|
4128
|
-
var
|
|
4544
|
+
var os8 = __toESM(require("os"));
|
|
4545
|
+
var path7 = __toESM(require("path"));
|
|
4129
4546
|
|
|
4130
4547
|
// src/providers/provider-loader.ts
|
|
4131
|
-
var
|
|
4132
|
-
var
|
|
4133
|
-
var
|
|
4548
|
+
var fs5 = __toESM(require("fs"));
|
|
4549
|
+
var path6 = __toESM(require("path"));
|
|
4550
|
+
var os7 = __toESM(require("os"));
|
|
4134
4551
|
var ProviderLoader = class _ProviderLoader {
|
|
4135
4552
|
providers = /* @__PURE__ */ new Map();
|
|
4136
4553
|
builtinDirs;
|
|
@@ -4150,10 +4567,10 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4150
4567
|
if (options?.builtinDir) {
|
|
4151
4568
|
this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
|
|
4152
4569
|
} else {
|
|
4153
|
-
this.builtinDirs = [
|
|
4570
|
+
this.builtinDirs = [path6.resolve(__dirname, "../providers/_builtin")];
|
|
4154
4571
|
}
|
|
4155
|
-
this.userDir = options?.userDir ||
|
|
4156
|
-
this.upstreamDir =
|
|
4572
|
+
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
4573
|
+
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
4157
4574
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
4158
4575
|
}
|
|
4159
4576
|
log(msg) {
|
|
@@ -4171,19 +4588,19 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4171
4588
|
this.providers.clear();
|
|
4172
4589
|
let builtinCount = 0;
|
|
4173
4590
|
for (const dir of this.builtinDirs) {
|
|
4174
|
-
if (
|
|
4591
|
+
if (fs5.existsSync(dir)) {
|
|
4175
4592
|
builtinCount += this.loadDir(dir);
|
|
4176
4593
|
}
|
|
4177
4594
|
}
|
|
4178
4595
|
this.log(`Loaded ${builtinCount} builtin providers`);
|
|
4179
4596
|
let upstreamCount = 0;
|
|
4180
|
-
if (
|
|
4597
|
+
if (fs5.existsSync(this.upstreamDir)) {
|
|
4181
4598
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
4182
4599
|
if (upstreamCount > 0) {
|
|
4183
4600
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
4184
4601
|
}
|
|
4185
4602
|
}
|
|
4186
|
-
if (
|
|
4603
|
+
if (fs5.existsSync(this.userDir)) {
|
|
4187
4604
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
4188
4605
|
if (userCount > 0) {
|
|
4189
4606
|
this.log(`Loaded ${userCount} user custom providers (never auto-updated)`);
|
|
@@ -4487,15 +4904,15 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4487
4904
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
4488
4905
|
return null;
|
|
4489
4906
|
}
|
|
4490
|
-
const dir =
|
|
4491
|
-
if (!
|
|
4907
|
+
const dir = path6.join(providerDir, scriptDir);
|
|
4908
|
+
if (!fs5.existsSync(dir)) {
|
|
4492
4909
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
4493
4910
|
return null;
|
|
4494
4911
|
}
|
|
4495
4912
|
const cached = this.scriptsCache.get(dir);
|
|
4496
4913
|
if (cached) return cached;
|
|
4497
|
-
const scriptsJs =
|
|
4498
|
-
if (
|
|
4914
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
4915
|
+
if (fs5.existsSync(scriptsJs)) {
|
|
4499
4916
|
try {
|
|
4500
4917
|
delete require.cache[require.resolve(scriptsJs)];
|
|
4501
4918
|
const loaded = require(scriptsJs);
|
|
@@ -4517,15 +4934,15 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4517
4934
|
watch() {
|
|
4518
4935
|
this.stopWatch();
|
|
4519
4936
|
const watchDir = (dir) => {
|
|
4520
|
-
if (!
|
|
4937
|
+
if (!fs5.existsSync(dir)) {
|
|
4521
4938
|
try {
|
|
4522
|
-
|
|
4939
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
4523
4940
|
} catch {
|
|
4524
4941
|
return;
|
|
4525
4942
|
}
|
|
4526
4943
|
}
|
|
4527
4944
|
try {
|
|
4528
|
-
const watcher =
|
|
4945
|
+
const watcher = fs5.watch(dir, { recursive: true }, (event, filename) => {
|
|
4529
4946
|
if (filename?.endsWith(".js") || filename?.endsWith(".json")) {
|
|
4530
4947
|
this.log(`File changed: ${filename}, reloading...`);
|
|
4531
4948
|
this.loadAll();
|
|
@@ -4575,13 +4992,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4575
4992
|
*/
|
|
4576
4993
|
async fetchLatest() {
|
|
4577
4994
|
const https = require("https");
|
|
4578
|
-
const { execSync:
|
|
4579
|
-
const metaPath =
|
|
4995
|
+
const { execSync: execSync7 } = require("child_process");
|
|
4996
|
+
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
4580
4997
|
let prevEtag = "";
|
|
4581
4998
|
let prevTimestamp = 0;
|
|
4582
4999
|
try {
|
|
4583
|
-
if (
|
|
4584
|
-
const meta = JSON.parse(
|
|
5000
|
+
if (fs5.existsSync(metaPath)) {
|
|
5001
|
+
const meta = JSON.parse(fs5.readFileSync(metaPath, "utf-8"));
|
|
4585
5002
|
prevEtag = meta.etag || "";
|
|
4586
5003
|
prevTimestamp = meta.timestamp || 0;
|
|
4587
5004
|
}
|
|
@@ -4593,7 +5010,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4593
5010
|
return { updated: false };
|
|
4594
5011
|
}
|
|
4595
5012
|
try {
|
|
4596
|
-
const etag = await new Promise((
|
|
5013
|
+
const etag = await new Promise((resolve7, reject) => {
|
|
4597
5014
|
const options = {
|
|
4598
5015
|
method: "HEAD",
|
|
4599
5016
|
hostname: "github.com",
|
|
@@ -4611,7 +5028,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4611
5028
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
4612
5029
|
timeout: 1e4
|
|
4613
5030
|
}, (res2) => {
|
|
4614
|
-
|
|
5031
|
+
resolve7(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
4615
5032
|
});
|
|
4616
5033
|
req2.on("error", reject);
|
|
4617
5034
|
req2.on("timeout", () => {
|
|
@@ -4620,7 +5037,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4620
5037
|
});
|
|
4621
5038
|
req2.end();
|
|
4622
5039
|
} else {
|
|
4623
|
-
|
|
5040
|
+
resolve7(res.headers.etag || res.headers["last-modified"] || "");
|
|
4624
5041
|
}
|
|
4625
5042
|
});
|
|
4626
5043
|
req.on("error", reject);
|
|
@@ -4636,39 +5053,39 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4636
5053
|
return { updated: false };
|
|
4637
5054
|
}
|
|
4638
5055
|
this.log("Downloading latest providers from GitHub...");
|
|
4639
|
-
const tmpTar =
|
|
4640
|
-
const tmpExtract =
|
|
5056
|
+
const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
5057
|
+
const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
4641
5058
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
const extracted =
|
|
5059
|
+
fs5.mkdirSync(tmpExtract, { recursive: true });
|
|
5060
|
+
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
5061
|
+
const extracted = fs5.readdirSync(tmpExtract);
|
|
4645
5062
|
const rootDir = extracted.find(
|
|
4646
|
-
(d) =>
|
|
5063
|
+
(d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
4647
5064
|
);
|
|
4648
5065
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
4649
|
-
const sourceDir =
|
|
5066
|
+
const sourceDir = path6.join(tmpExtract, rootDir);
|
|
4650
5067
|
const backupDir = this.upstreamDir + ".bak";
|
|
4651
|
-
if (
|
|
4652
|
-
if (
|
|
4653
|
-
|
|
5068
|
+
if (fs5.existsSync(this.upstreamDir)) {
|
|
5069
|
+
if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
|
|
5070
|
+
fs5.renameSync(this.upstreamDir, backupDir);
|
|
4654
5071
|
}
|
|
4655
5072
|
try {
|
|
4656
5073
|
this.copyDirRecursive(sourceDir, this.upstreamDir);
|
|
4657
5074
|
this.writeMeta(metaPath, etag || `ts-${Date.now()}`, Date.now());
|
|
4658
|
-
if (
|
|
5075
|
+
if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
|
|
4659
5076
|
} catch (e) {
|
|
4660
|
-
if (
|
|
4661
|
-
if (
|
|
4662
|
-
|
|
5077
|
+
if (fs5.existsSync(backupDir)) {
|
|
5078
|
+
if (fs5.existsSync(this.upstreamDir)) fs5.rmSync(this.upstreamDir, { recursive: true, force: true });
|
|
5079
|
+
fs5.renameSync(backupDir, this.upstreamDir);
|
|
4663
5080
|
}
|
|
4664
5081
|
throw e;
|
|
4665
5082
|
}
|
|
4666
5083
|
try {
|
|
4667
|
-
|
|
5084
|
+
fs5.rmSync(tmpTar, { force: true });
|
|
4668
5085
|
} catch {
|
|
4669
5086
|
}
|
|
4670
5087
|
try {
|
|
4671
|
-
|
|
5088
|
+
fs5.rmSync(tmpExtract, { recursive: true, force: true });
|
|
4672
5089
|
} catch {
|
|
4673
5090
|
}
|
|
4674
5091
|
const upstreamCount = this.countProviders(this.upstreamDir);
|
|
@@ -4684,7 +5101,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4684
5101
|
downloadFile(url, destPath) {
|
|
4685
5102
|
const https = require("https");
|
|
4686
5103
|
const http3 = require("http");
|
|
4687
|
-
return new Promise((
|
|
5104
|
+
return new Promise((resolve7, reject) => {
|
|
4688
5105
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
4689
5106
|
if (redirectCount > 5) {
|
|
4690
5107
|
reject(new Error("Too many redirects"));
|
|
@@ -4700,11 +5117,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4700
5117
|
reject(new Error(`HTTP ${res.statusCode}`));
|
|
4701
5118
|
return;
|
|
4702
5119
|
}
|
|
4703
|
-
const ws =
|
|
5120
|
+
const ws = fs5.createWriteStream(destPath);
|
|
4704
5121
|
res.pipe(ws);
|
|
4705
5122
|
ws.on("finish", () => {
|
|
4706
5123
|
ws.close();
|
|
4707
|
-
|
|
5124
|
+
resolve7();
|
|
4708
5125
|
});
|
|
4709
5126
|
ws.on("error", reject);
|
|
4710
5127
|
});
|
|
@@ -4719,22 +5136,22 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4719
5136
|
}
|
|
4720
5137
|
/** Recursive directory copy */
|
|
4721
5138
|
copyDirRecursive(src, dest) {
|
|
4722
|
-
|
|
4723
|
-
for (const entry of
|
|
4724
|
-
const srcPath =
|
|
4725
|
-
const destPath =
|
|
5139
|
+
fs5.mkdirSync(dest, { recursive: true });
|
|
5140
|
+
for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
|
|
5141
|
+
const srcPath = path6.join(src, entry.name);
|
|
5142
|
+
const destPath = path6.join(dest, entry.name);
|
|
4726
5143
|
if (entry.isDirectory()) {
|
|
4727
5144
|
this.copyDirRecursive(srcPath, destPath);
|
|
4728
5145
|
} else {
|
|
4729
|
-
|
|
5146
|
+
fs5.copyFileSync(srcPath, destPath);
|
|
4730
5147
|
}
|
|
4731
5148
|
}
|
|
4732
5149
|
}
|
|
4733
5150
|
/** .meta.json save */
|
|
4734
5151
|
writeMeta(metaPath, etag, timestamp) {
|
|
4735
5152
|
try {
|
|
4736
|
-
|
|
4737
|
-
|
|
5153
|
+
fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
|
|
5154
|
+
fs5.writeFileSync(metaPath, JSON.stringify({
|
|
4738
5155
|
etag,
|
|
4739
5156
|
timestamp,
|
|
4740
5157
|
lastCheck: new Date(timestamp).toISOString(),
|
|
@@ -4745,12 +5162,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4745
5162
|
}
|
|
4746
5163
|
/** Count provider files (provider.js or provider.json) */
|
|
4747
5164
|
countProviders(dir) {
|
|
4748
|
-
if (!
|
|
5165
|
+
if (!fs5.existsSync(dir)) return 0;
|
|
4749
5166
|
let count = 0;
|
|
4750
5167
|
const scan = (d) => {
|
|
4751
5168
|
try {
|
|
4752
|
-
for (const entry of
|
|
4753
|
-
if (entry.isDirectory()) scan(
|
|
5169
|
+
for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
|
|
5170
|
+
if (entry.isDirectory()) scan(path6.join(d, entry.name));
|
|
4754
5171
|
else if (entry.name === "provider.json") count++;
|
|
4755
5172
|
}
|
|
4756
5173
|
} catch {
|
|
@@ -4847,20 +5264,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4847
5264
|
const cat = provider.category;
|
|
4848
5265
|
const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
|
|
4849
5266
|
for (const root of searchRoots) {
|
|
4850
|
-
if (!
|
|
4851
|
-
for (const candidate of [
|
|
4852
|
-
if (
|
|
5267
|
+
if (!fs5.existsSync(root)) continue;
|
|
5268
|
+
for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
|
|
5269
|
+
if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
|
|
4853
5270
|
}
|
|
4854
|
-
const catDir =
|
|
4855
|
-
if (
|
|
5271
|
+
const catDir = path6.join(root, cat);
|
|
5272
|
+
if (fs5.existsSync(catDir)) {
|
|
4856
5273
|
try {
|
|
4857
|
-
for (const entry of
|
|
5274
|
+
for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
|
|
4858
5275
|
if (!entry.isDirectory()) continue;
|
|
4859
|
-
const jsonPath =
|
|
4860
|
-
if (
|
|
5276
|
+
const jsonPath = path6.join(catDir, entry.name, "provider.json");
|
|
5277
|
+
if (fs5.existsSync(jsonPath)) {
|
|
4861
5278
|
try {
|
|
4862
|
-
const data = JSON.parse(
|
|
4863
|
-
if (data.type === type) return
|
|
5279
|
+
const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
|
|
5280
|
+
if (data.type === type) return path6.join(catDir, entry.name);
|
|
4864
5281
|
} catch {
|
|
4865
5282
|
}
|
|
4866
5283
|
}
|
|
@@ -4877,8 +5294,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4877
5294
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
4878
5295
|
*/
|
|
4879
5296
|
buildScriptWrappersFromDir(dir) {
|
|
4880
|
-
const scriptsJs =
|
|
4881
|
-
if (
|
|
5297
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
5298
|
+
if (fs5.existsSync(scriptsJs)) {
|
|
4882
5299
|
try {
|
|
4883
5300
|
delete require.cache[require.resolve(scriptsJs)];
|
|
4884
5301
|
return require(scriptsJs);
|
|
@@ -4888,13 +5305,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4888
5305
|
const toCamel = (name) => name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
4889
5306
|
const result = {};
|
|
4890
5307
|
try {
|
|
4891
|
-
for (const file of
|
|
5308
|
+
for (const file of fs5.readdirSync(dir)) {
|
|
4892
5309
|
if (!file.endsWith(".js")) continue;
|
|
4893
5310
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
4894
|
-
const filePath =
|
|
5311
|
+
const filePath = path6.join(dir, file);
|
|
4895
5312
|
result[scriptName] = (..._args) => {
|
|
4896
5313
|
try {
|
|
4897
|
-
return
|
|
5314
|
+
return fs5.readFileSync(filePath, "utf-8");
|
|
4898
5315
|
} catch {
|
|
4899
5316
|
return "";
|
|
4900
5317
|
}
|
|
@@ -4912,20 +5329,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4912
5329
|
* Structure: dir/category/agent-name/provider.{json,js}
|
|
4913
5330
|
*/
|
|
4914
5331
|
loadDir(dir, excludeDirs) {
|
|
4915
|
-
if (!
|
|
5332
|
+
if (!fs5.existsSync(dir)) return 0;
|
|
4916
5333
|
let count = 0;
|
|
4917
5334
|
const scan = (d) => {
|
|
4918
5335
|
let entries;
|
|
4919
5336
|
try {
|
|
4920
|
-
entries =
|
|
5337
|
+
entries = fs5.readdirSync(d, { withFileTypes: true });
|
|
4921
5338
|
} catch {
|
|
4922
5339
|
return;
|
|
4923
5340
|
}
|
|
4924
5341
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
4925
5342
|
if (hasJson) {
|
|
4926
|
-
const jsonPath =
|
|
5343
|
+
const jsonPath = path6.join(d, "provider.json");
|
|
4927
5344
|
try {
|
|
4928
|
-
const raw =
|
|
5345
|
+
const raw = fs5.readFileSync(jsonPath, "utf-8");
|
|
4929
5346
|
const mod = JSON.parse(raw);
|
|
4930
5347
|
if (!mod.type || !mod.name || !mod.category) {
|
|
4931
5348
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: missing type/name/category`);
|
|
@@ -4936,8 +5353,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4936
5353
|
delete mod.extensionIdPattern_flags;
|
|
4937
5354
|
}
|
|
4938
5355
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
4939
|
-
const scriptsPath =
|
|
4940
|
-
if (!hasCompatibility &&
|
|
5356
|
+
const scriptsPath = path6.join(d, "scripts.js");
|
|
5357
|
+
if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
|
|
4941
5358
|
try {
|
|
4942
5359
|
delete require.cache[require.resolve(scriptsPath)];
|
|
4943
5360
|
const scripts = require(scriptsPath);
|
|
@@ -4962,7 +5379,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
4962
5379
|
if (!entry.isDirectory()) continue;
|
|
4963
5380
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
4964
5381
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
4965
|
-
scan(
|
|
5382
|
+
scan(path6.join(d, entry.name));
|
|
4966
5383
|
}
|
|
4967
5384
|
}
|
|
4968
5385
|
};
|
|
@@ -5041,17 +5458,17 @@ async function findFreePort(ports) {
|
|
|
5041
5458
|
throw new Error("No free port found");
|
|
5042
5459
|
}
|
|
5043
5460
|
function checkPortFree(port) {
|
|
5044
|
-
return new Promise((
|
|
5461
|
+
return new Promise((resolve7) => {
|
|
5045
5462
|
const server = net.createServer();
|
|
5046
5463
|
server.unref();
|
|
5047
|
-
server.on("error", () =>
|
|
5464
|
+
server.on("error", () => resolve7(false));
|
|
5048
5465
|
server.listen(port, "127.0.0.1", () => {
|
|
5049
|
-
server.close(() =>
|
|
5466
|
+
server.close(() => resolve7(true));
|
|
5050
5467
|
});
|
|
5051
5468
|
});
|
|
5052
5469
|
}
|
|
5053
5470
|
async function isCdpActive(port) {
|
|
5054
|
-
return new Promise((
|
|
5471
|
+
return new Promise((resolve7) => {
|
|
5055
5472
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
5056
5473
|
timeout: 2e3
|
|
5057
5474
|
}, (res) => {
|
|
@@ -5060,52 +5477,52 @@ async function isCdpActive(port) {
|
|
|
5060
5477
|
res.on("end", () => {
|
|
5061
5478
|
try {
|
|
5062
5479
|
const info = JSON.parse(data);
|
|
5063
|
-
|
|
5480
|
+
resolve7(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
5064
5481
|
} catch {
|
|
5065
|
-
|
|
5482
|
+
resolve7(false);
|
|
5066
5483
|
}
|
|
5067
5484
|
});
|
|
5068
5485
|
});
|
|
5069
|
-
req.on("error", () =>
|
|
5486
|
+
req.on("error", () => resolve7(false));
|
|
5070
5487
|
req.on("timeout", () => {
|
|
5071
5488
|
req.destroy();
|
|
5072
|
-
|
|
5489
|
+
resolve7(false);
|
|
5073
5490
|
});
|
|
5074
5491
|
});
|
|
5075
5492
|
}
|
|
5076
5493
|
async function killIdeProcess(ideId) {
|
|
5077
|
-
const plat =
|
|
5494
|
+
const plat = os8.platform();
|
|
5078
5495
|
const appName = getMacAppIdentifiers()[ideId];
|
|
5079
5496
|
const winProcesses = getWinProcessNames()[ideId];
|
|
5080
5497
|
try {
|
|
5081
5498
|
if (plat === "darwin" && appName) {
|
|
5082
5499
|
try {
|
|
5083
|
-
(0,
|
|
5500
|
+
(0, import_child_process4.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
5084
5501
|
timeout: 5e3
|
|
5085
5502
|
});
|
|
5086
5503
|
} catch {
|
|
5087
5504
|
try {
|
|
5088
|
-
(0,
|
|
5505
|
+
(0, import_child_process4.execSync)(`pkill -f "${appName}" 2>/dev/null`);
|
|
5089
5506
|
} catch {
|
|
5090
5507
|
}
|
|
5091
5508
|
}
|
|
5092
5509
|
} else if (plat === "win32" && winProcesses) {
|
|
5093
5510
|
for (const proc of winProcesses) {
|
|
5094
5511
|
try {
|
|
5095
|
-
(0,
|
|
5512
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`, { timeout: 5e3 });
|
|
5096
5513
|
} catch {
|
|
5097
5514
|
}
|
|
5098
5515
|
}
|
|
5099
5516
|
try {
|
|
5100
5517
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
5101
|
-
(0,
|
|
5518
|
+
(0, import_child_process4.execSync)(`powershell -Command "Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue | Stop-Process -Force"`, {
|
|
5102
5519
|
timeout: 1e4
|
|
5103
5520
|
});
|
|
5104
5521
|
} catch {
|
|
5105
5522
|
}
|
|
5106
5523
|
} else {
|
|
5107
5524
|
try {
|
|
5108
|
-
(0,
|
|
5525
|
+
(0, import_child_process4.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
|
|
5109
5526
|
} catch {
|
|
5110
5527
|
}
|
|
5111
5528
|
}
|
|
@@ -5115,13 +5532,13 @@ async function killIdeProcess(ideId) {
|
|
|
5115
5532
|
}
|
|
5116
5533
|
if (plat === "darwin" && appName) {
|
|
5117
5534
|
try {
|
|
5118
|
-
(0,
|
|
5535
|
+
(0, import_child_process4.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
|
|
5119
5536
|
} catch {
|
|
5120
5537
|
}
|
|
5121
5538
|
} else if (plat === "win32" && winProcesses) {
|
|
5122
5539
|
for (const proc of winProcesses) {
|
|
5123
5540
|
try {
|
|
5124
|
-
(0,
|
|
5541
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`);
|
|
5125
5542
|
} catch {
|
|
5126
5543
|
}
|
|
5127
5544
|
}
|
|
@@ -5133,26 +5550,26 @@ async function killIdeProcess(ideId) {
|
|
|
5133
5550
|
}
|
|
5134
5551
|
}
|
|
5135
5552
|
function isIdeRunning(ideId) {
|
|
5136
|
-
const plat =
|
|
5553
|
+
const plat = os8.platform();
|
|
5137
5554
|
try {
|
|
5138
5555
|
if (plat === "darwin") {
|
|
5139
5556
|
const appName = getMacAppIdentifiers()[ideId];
|
|
5140
5557
|
if (!appName) return false;
|
|
5141
|
-
const result = (0,
|
|
5558
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
|
|
5142
5559
|
return result.trim().length > 0;
|
|
5143
5560
|
} else if (plat === "win32") {
|
|
5144
5561
|
const winProcesses = getWinProcessNames()[ideId];
|
|
5145
5562
|
if (!winProcesses) return false;
|
|
5146
5563
|
for (const proc of winProcesses) {
|
|
5147
5564
|
try {
|
|
5148
|
-
const result = (0,
|
|
5565
|
+
const result = (0, import_child_process4.execSync)(`tasklist /FI "IMAGENAME eq ${proc}" /NH 2>nul`, { encoding: "utf-8" });
|
|
5149
5566
|
if (result.includes(proc)) return true;
|
|
5150
5567
|
} catch {
|
|
5151
5568
|
}
|
|
5152
5569
|
}
|
|
5153
5570
|
try {
|
|
5154
5571
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
5155
|
-
const result = (0,
|
|
5572
|
+
const result = (0, import_child_process4.execSync)(
|
|
5156
5573
|
`powershell -Command "(Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue).Count"`,
|
|
5157
5574
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
5158
5575
|
);
|
|
@@ -5161,7 +5578,7 @@ function isIdeRunning(ideId) {
|
|
|
5161
5578
|
}
|
|
5162
5579
|
return false;
|
|
5163
5580
|
} else {
|
|
5164
|
-
const result = (0,
|
|
5581
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
|
|
5165
5582
|
return result.trim().length > 0;
|
|
5166
5583
|
}
|
|
5167
5584
|
} catch {
|
|
@@ -5169,12 +5586,12 @@ function isIdeRunning(ideId) {
|
|
|
5169
5586
|
}
|
|
5170
5587
|
}
|
|
5171
5588
|
function detectCurrentWorkspace(ideId) {
|
|
5172
|
-
const plat =
|
|
5589
|
+
const plat = os8.platform();
|
|
5173
5590
|
if (plat === "darwin") {
|
|
5174
5591
|
try {
|
|
5175
5592
|
const appName = getMacAppIdentifiers()[ideId];
|
|
5176
5593
|
if (!appName) return void 0;
|
|
5177
|
-
const result = (0,
|
|
5594
|
+
const result = (0, import_child_process4.execSync)(
|
|
5178
5595
|
`lsof -c "${appName}" 2>/dev/null | grep cwd | head -1 | awk '{print $NF}'`,
|
|
5179
5596
|
{ encoding: "utf-8", timeout: 3e3 }
|
|
5180
5597
|
);
|
|
@@ -5184,17 +5601,17 @@ function detectCurrentWorkspace(ideId) {
|
|
|
5184
5601
|
}
|
|
5185
5602
|
} else if (plat === "win32") {
|
|
5186
5603
|
try {
|
|
5187
|
-
const
|
|
5604
|
+
const fs10 = require("fs");
|
|
5188
5605
|
const appNameMap = getMacAppIdentifiers();
|
|
5189
5606
|
const appName = appNameMap[ideId];
|
|
5190
5607
|
if (appName) {
|
|
5191
|
-
const storagePath =
|
|
5192
|
-
process.env.APPDATA ||
|
|
5608
|
+
const storagePath = path7.join(
|
|
5609
|
+
process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
|
|
5193
5610
|
appName,
|
|
5194
5611
|
"storage.json"
|
|
5195
5612
|
);
|
|
5196
|
-
if (
|
|
5197
|
-
const data = JSON.parse(
|
|
5613
|
+
if (fs10.existsSync(storagePath)) {
|
|
5614
|
+
const data = JSON.parse(fs10.readFileSync(storagePath, "utf-8"));
|
|
5198
5615
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
5199
5616
|
if (workspaces.length > 0) {
|
|
5200
5617
|
const recent = workspaces[0];
|
|
@@ -5211,7 +5628,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
5211
5628
|
return void 0;
|
|
5212
5629
|
}
|
|
5213
5630
|
async function launchWithCdp(options = {}) {
|
|
5214
|
-
const
|
|
5631
|
+
const platform8 = os8.platform();
|
|
5215
5632
|
let targetIde;
|
|
5216
5633
|
const ides = await detectIDEs();
|
|
5217
5634
|
if (options.ideId) {
|
|
@@ -5280,9 +5697,9 @@ async function launchWithCdp(options = {}) {
|
|
|
5280
5697
|
}
|
|
5281
5698
|
const port = await findFreePort(portPair);
|
|
5282
5699
|
try {
|
|
5283
|
-
if (
|
|
5700
|
+
if (platform8 === "darwin") {
|
|
5284
5701
|
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
5285
|
-
} else if (
|
|
5702
|
+
} else if (platform8 === "win32") {
|
|
5286
5703
|
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
5287
5704
|
} else {
|
|
5288
5705
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
@@ -5322,9 +5739,9 @@ async function launchMacOS(ide, port, workspace, newWindow) {
|
|
|
5322
5739
|
if (workspace) args.push(workspace);
|
|
5323
5740
|
if (appName) {
|
|
5324
5741
|
const openArgs = ["-a", appName, "--args", ...args];
|
|
5325
|
-
(0,
|
|
5742
|
+
(0, import_child_process4.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
5326
5743
|
} else if (ide.cliCommand) {
|
|
5327
|
-
(0,
|
|
5744
|
+
(0, import_child_process4.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
5328
5745
|
} else {
|
|
5329
5746
|
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
5330
5747
|
}
|
|
@@ -5350,21 +5767,25 @@ async function launchLinux(ide, port, workspace, newWindow) {
|
|
|
5350
5767
|
const args = ["--remote-debugging-port=" + port];
|
|
5351
5768
|
if (newWindow) args.push("--new-window");
|
|
5352
5769
|
if (workspace) args.push(workspace);
|
|
5353
|
-
(0,
|
|
5770
|
+
(0, import_child_process4.spawn)(cli, args, { detached: true, stdio: "ignore" }).unref();
|
|
5354
5771
|
}
|
|
5355
5772
|
function getAvailableIdeIds() {
|
|
5356
5773
|
return getProviderLoader().getAvailableIdeTypes();
|
|
5357
5774
|
}
|
|
5358
5775
|
|
|
5776
|
+
// src/commands/router.ts
|
|
5777
|
+
init_config();
|
|
5778
|
+
init_workspaces();
|
|
5779
|
+
|
|
5359
5780
|
// src/logging/command-log.ts
|
|
5360
|
-
var
|
|
5361
|
-
var
|
|
5362
|
-
var
|
|
5363
|
-
var LOG_DIR2 = process.platform === "darwin" ?
|
|
5781
|
+
var fs6 = __toESM(require("fs"));
|
|
5782
|
+
var path8 = __toESM(require("path"));
|
|
5783
|
+
var os9 = __toESM(require("os"));
|
|
5784
|
+
var LOG_DIR2 = process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
|
|
5364
5785
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
5365
5786
|
var MAX_DAYS = 7;
|
|
5366
5787
|
try {
|
|
5367
|
-
|
|
5788
|
+
fs6.mkdirSync(LOG_DIR2, { recursive: true });
|
|
5368
5789
|
} catch {
|
|
5369
5790
|
}
|
|
5370
5791
|
var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -5398,19 +5819,19 @@ function getDateStr2() {
|
|
|
5398
5819
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5399
5820
|
}
|
|
5400
5821
|
var currentDate2 = getDateStr2();
|
|
5401
|
-
var currentFile =
|
|
5822
|
+
var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
5402
5823
|
var writeCount2 = 0;
|
|
5403
5824
|
function checkRotation() {
|
|
5404
5825
|
const today = getDateStr2();
|
|
5405
5826
|
if (today !== currentDate2) {
|
|
5406
5827
|
currentDate2 = today;
|
|
5407
|
-
currentFile =
|
|
5828
|
+
currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
5408
5829
|
cleanOldFiles();
|
|
5409
5830
|
}
|
|
5410
5831
|
}
|
|
5411
5832
|
function cleanOldFiles() {
|
|
5412
5833
|
try {
|
|
5413
|
-
const files =
|
|
5834
|
+
const files = fs6.readdirSync(LOG_DIR2).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
|
|
5414
5835
|
const cutoff = /* @__PURE__ */ new Date();
|
|
5415
5836
|
cutoff.setDate(cutoff.getDate() - MAX_DAYS);
|
|
5416
5837
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -5418,7 +5839,7 @@ function cleanOldFiles() {
|
|
|
5418
5839
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
5419
5840
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
5420
5841
|
try {
|
|
5421
|
-
|
|
5842
|
+
fs6.unlinkSync(path8.join(LOG_DIR2, file));
|
|
5422
5843
|
} catch {
|
|
5423
5844
|
}
|
|
5424
5845
|
}
|
|
@@ -5428,14 +5849,14 @@ function cleanOldFiles() {
|
|
|
5428
5849
|
}
|
|
5429
5850
|
function checkSize() {
|
|
5430
5851
|
try {
|
|
5431
|
-
const stat =
|
|
5852
|
+
const stat = fs6.statSync(currentFile);
|
|
5432
5853
|
if (stat.size > MAX_FILE_SIZE) {
|
|
5433
5854
|
const backup = currentFile.replace(".jsonl", ".1.jsonl");
|
|
5434
5855
|
try {
|
|
5435
|
-
|
|
5856
|
+
fs6.unlinkSync(backup);
|
|
5436
5857
|
} catch {
|
|
5437
5858
|
}
|
|
5438
|
-
|
|
5859
|
+
fs6.renameSync(currentFile, backup);
|
|
5439
5860
|
}
|
|
5440
5861
|
} catch {
|
|
5441
5862
|
}
|
|
@@ -5460,14 +5881,14 @@ function logCommand(entry) {
|
|
|
5460
5881
|
...entry.error ? { err: entry.error } : {},
|
|
5461
5882
|
...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
|
|
5462
5883
|
});
|
|
5463
|
-
|
|
5884
|
+
fs6.appendFileSync(currentFile, line + "\n");
|
|
5464
5885
|
} catch {
|
|
5465
5886
|
}
|
|
5466
5887
|
}
|
|
5467
5888
|
function getRecentCommands(count = 50) {
|
|
5468
5889
|
try {
|
|
5469
|
-
if (!
|
|
5470
|
-
const content =
|
|
5890
|
+
if (!fs6.existsSync(currentFile)) return [];
|
|
5891
|
+
const content = fs6.readFileSync(currentFile, "utf-8");
|
|
5471
5892
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
5472
5893
|
return lines.slice(-count).map((line) => {
|
|
5473
5894
|
try {
|
|
@@ -5492,7 +5913,7 @@ function getRecentCommands(count = 50) {
|
|
|
5492
5913
|
cleanOldFiles();
|
|
5493
5914
|
|
|
5494
5915
|
// src/commands/router.ts
|
|
5495
|
-
var
|
|
5916
|
+
var fs7 = __toESM(require("fs"));
|
|
5496
5917
|
var CHAT_COMMANDS = [
|
|
5497
5918
|
"send_chat",
|
|
5498
5919
|
"new_chat",
|
|
@@ -5562,8 +5983,8 @@ var DaemonCommandRouter = class {
|
|
|
5562
5983
|
if (logs.length > 0) {
|
|
5563
5984
|
return { success: true, logs, totalBuffered: logs.length };
|
|
5564
5985
|
}
|
|
5565
|
-
if (
|
|
5566
|
-
const content =
|
|
5986
|
+
if (fs7.existsSync(LOG_PATH)) {
|
|
5987
|
+
const content = fs7.readFileSync(LOG_PATH, "utf-8");
|
|
5567
5988
|
const allLines = content.split("\n");
|
|
5568
5989
|
const recent = allLines.slice(-count).join("\n");
|
|
5569
5990
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -5602,8 +6023,20 @@ var DaemonCommandRouter = class {
|
|
|
5602
6023
|
}
|
|
5603
6024
|
// ─── IDE launch + CDP connect ───
|
|
5604
6025
|
case "launch_ide": {
|
|
5605
|
-
const
|
|
5606
|
-
const
|
|
6026
|
+
const ideKey = args?.ideId || args?.ideType;
|
|
6027
|
+
const resolvedWorkspace = resolveIdeLaunchWorkspace(
|
|
6028
|
+
{
|
|
6029
|
+
workspace: args?.workspace,
|
|
6030
|
+
workspaceId: args?.workspaceId,
|
|
6031
|
+
useDefaultWorkspace: args?.useDefaultWorkspace
|
|
6032
|
+
},
|
|
6033
|
+
loadConfig()
|
|
6034
|
+
);
|
|
6035
|
+
const launchArgs = {
|
|
6036
|
+
ideId: ideKey,
|
|
6037
|
+
workspace: resolvedWorkspace,
|
|
6038
|
+
newWindow: args?.newWindow
|
|
6039
|
+
};
|
|
5607
6040
|
LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
5608
6041
|
const result = await launchWithCdp(launchArgs);
|
|
5609
6042
|
if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
|
|
@@ -5620,6 +6053,15 @@ var DaemonCommandRouter = class {
|
|
|
5620
6053
|
}
|
|
5621
6054
|
}
|
|
5622
6055
|
this.deps.onIdeConnected?.();
|
|
6056
|
+
if (result.success && resolvedWorkspace) {
|
|
6057
|
+
try {
|
|
6058
|
+
saveConfig(appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
|
|
6059
|
+
kind: "ide",
|
|
6060
|
+
agentType: result.ideId
|
|
6061
|
+
}));
|
|
6062
|
+
} catch {
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
5623
6065
|
return { success: result.success, ...result };
|
|
5624
6066
|
}
|
|
5625
6067
|
// ─── IDE detection ───
|
|
@@ -5627,6 +6069,12 @@ var DaemonCommandRouter = class {
|
|
|
5627
6069
|
this.deps.detectedIdes.value = await detectIDEs();
|
|
5628
6070
|
return { success: true, ides: this.deps.detectedIdes.value };
|
|
5629
6071
|
}
|
|
6072
|
+
// ─── Machine Settings ───
|
|
6073
|
+
case "set_machine_nickname": {
|
|
6074
|
+
const nickname = args?.nickname;
|
|
6075
|
+
updateConfig({ machineNickname: nickname || null });
|
|
6076
|
+
return { success: true };
|
|
6077
|
+
}
|
|
5630
6078
|
}
|
|
5631
6079
|
return null;
|
|
5632
6080
|
}
|
|
@@ -5663,8 +6111,9 @@ var DaemonCommandRouter = class {
|
|
|
5663
6111
|
};
|
|
5664
6112
|
|
|
5665
6113
|
// src/status/reporter.ts
|
|
5666
|
-
var
|
|
6114
|
+
var os10 = __toESM(require("os"));
|
|
5667
6115
|
init_config();
|
|
6116
|
+
init_workspaces();
|
|
5668
6117
|
var DaemonStatusReporter = class {
|
|
5669
6118
|
deps;
|
|
5670
6119
|
log;
|
|
@@ -5731,6 +6180,10 @@ var DaemonStatusReporter = class {
|
|
|
5731
6180
|
// (agent-stream polling backward compat)
|
|
5732
6181
|
updateAgentStreams(_ideType, _streams) {
|
|
5733
6182
|
}
|
|
6183
|
+
/** Reset P2P dedup hash — forces next send to transmit even if content unchanged */
|
|
6184
|
+
resetP2PHash() {
|
|
6185
|
+
this.lastP2PStatusHash = "";
|
|
6186
|
+
}
|
|
5734
6187
|
// ─── Core ────────────────────────────────────────
|
|
5735
6188
|
ts() {
|
|
5736
6189
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
@@ -5810,18 +6263,26 @@ var DaemonStatusReporter = class {
|
|
|
5810
6263
|
acpConfigOptions: s.acpConfigOptions,
|
|
5811
6264
|
acpModes: s.acpModes
|
|
5812
6265
|
}));
|
|
6266
|
+
const cfg = loadConfig();
|
|
6267
|
+
const wsState = getWorkspaceState(cfg);
|
|
6268
|
+
const memSnap = getHostMemorySnapshot();
|
|
5813
6269
|
const payload = {
|
|
5814
6270
|
daemonMode: true,
|
|
5815
|
-
machineNickname:
|
|
6271
|
+
machineNickname: cfg.machineNickname || null,
|
|
6272
|
+
workspaces: wsState.workspaces,
|
|
6273
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
6274
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
6275
|
+
workspaceActivity: getWorkspaceActivity(cfg, 15),
|
|
5816
6276
|
machine: {
|
|
5817
|
-
hostname:
|
|
5818
|
-
platform:
|
|
5819
|
-
arch:
|
|
5820
|
-
cpus:
|
|
5821
|
-
totalMem:
|
|
5822
|
-
freeMem:
|
|
5823
|
-
|
|
5824
|
-
|
|
6277
|
+
hostname: os10.hostname(),
|
|
6278
|
+
platform: os10.platform(),
|
|
6279
|
+
arch: os10.arch(),
|
|
6280
|
+
cpus: os10.cpus().length,
|
|
6281
|
+
totalMem: memSnap.totalMem,
|
|
6282
|
+
freeMem: memSnap.freeMem,
|
|
6283
|
+
availableMem: memSnap.availableMem,
|
|
6284
|
+
loadavg: os10.loadavg(),
|
|
6285
|
+
uptime: os10.uptime()
|
|
5825
6286
|
},
|
|
5826
6287
|
managedIdes,
|
|
5827
6288
|
managedClis,
|
|
@@ -5853,6 +6314,8 @@ var DaemonStatusReporter = class {
|
|
|
5853
6314
|
const wsPayload = {
|
|
5854
6315
|
daemonMode: true,
|
|
5855
6316
|
machineNickname: payload.machineNickname,
|
|
6317
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
6318
|
+
workspaceCount: (wsState.workspaces || []).length,
|
|
5856
6319
|
// managedIdes: server only saves id, type, cdpConnected
|
|
5857
6320
|
managedIdes: managedIdes.map((ide) => ({
|
|
5858
6321
|
ideType: ide.ideType,
|
|
@@ -5883,7 +6346,7 @@ var DaemonStatusReporter = class {
|
|
|
5883
6346
|
sendP2PPayload(payload) {
|
|
5884
6347
|
const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
|
|
5885
6348
|
if (hashTarget.machine) {
|
|
5886
|
-
const { freeMem: _f, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
6349
|
+
const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
5887
6350
|
hashTarget.machine = stableMachine;
|
|
5888
6351
|
}
|
|
5889
6352
|
const h = this.simpleHash(JSON.stringify(hashTarget));
|
|
@@ -5905,17 +6368,34 @@ var DaemonStatusReporter = class {
|
|
|
5905
6368
|
};
|
|
5906
6369
|
|
|
5907
6370
|
// src/commands/cli-manager.ts
|
|
5908
|
-
var
|
|
5909
|
-
var
|
|
6371
|
+
var os12 = __toESM(require("os"));
|
|
6372
|
+
var path10 = __toESM(require("path"));
|
|
5910
6373
|
var crypto4 = __toESM(require("crypto"));
|
|
5911
6374
|
var import_chalk = __toESM(require("chalk"));
|
|
5912
6375
|
|
|
5913
6376
|
// src/cli-adapters/provider-cli-adapter.ts
|
|
5914
|
-
var
|
|
5915
|
-
var
|
|
6377
|
+
var os11 = __toESM(require("os"));
|
|
6378
|
+
var path9 = __toESM(require("path"));
|
|
6379
|
+
var import_child_process5 = require("child_process");
|
|
5916
6380
|
var pty;
|
|
5917
6381
|
try {
|
|
5918
6382
|
pty = require("node-pty");
|
|
6383
|
+
if (os11.platform() !== "win32") {
|
|
6384
|
+
try {
|
|
6385
|
+
const fs10 = require("fs");
|
|
6386
|
+
const ptyDir = path9.dirname(require.resolve("node-pty"));
|
|
6387
|
+
const arch3 = os11.arch() === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
6388
|
+
const helper = path9.join(ptyDir, "prebuilds", arch3, "spawn-helper");
|
|
6389
|
+
if (fs10.existsSync(helper)) {
|
|
6390
|
+
const stat = fs10.statSync(helper);
|
|
6391
|
+
if (!(stat.mode & 73)) {
|
|
6392
|
+
fs10.chmodSync(helper, stat.mode | 493);
|
|
6393
|
+
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6396
|
+
} catch {
|
|
6397
|
+
}
|
|
6398
|
+
}
|
|
5919
6399
|
} catch {
|
|
5920
6400
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Install: npm install node-pty@1.0.0");
|
|
5921
6401
|
}
|
|
@@ -5923,21 +6403,121 @@ function stripAnsi(str) {
|
|
|
5923
6403
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
5924
6404
|
}
|
|
5925
6405
|
function findBinary(name) {
|
|
5926
|
-
const isWin =
|
|
6406
|
+
const isWin = os11.platform() === "win32";
|
|
5927
6407
|
try {
|
|
5928
6408
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
5929
|
-
return (0,
|
|
6409
|
+
return (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
5930
6410
|
} catch {
|
|
5931
6411
|
return isWin ? `${name}.cmd` : name;
|
|
5932
6412
|
}
|
|
5933
6413
|
}
|
|
6414
|
+
function isScriptBinary(binaryPath) {
|
|
6415
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
6416
|
+
try {
|
|
6417
|
+
const fs10 = require("fs");
|
|
6418
|
+
const resolved = fs10.realpathSync(binaryPath);
|
|
6419
|
+
const head = Buffer.alloc(8);
|
|
6420
|
+
const fd = fs10.openSync(resolved, "r");
|
|
6421
|
+
fs10.readSync(fd, head, 0, 8, 0);
|
|
6422
|
+
fs10.closeSync(fd);
|
|
6423
|
+
let i = 0;
|
|
6424
|
+
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
6425
|
+
return head[i] === 35 && head[i + 1] === 33;
|
|
6426
|
+
} catch {
|
|
6427
|
+
return false;
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6430
|
+
function looksLikeMachOOrElf(filePath) {
|
|
6431
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
6432
|
+
try {
|
|
6433
|
+
const fs10 = require("fs");
|
|
6434
|
+
const resolved = fs10.realpathSync(filePath);
|
|
6435
|
+
const buf = Buffer.alloc(8);
|
|
6436
|
+
const fd = fs10.openSync(resolved, "r");
|
|
6437
|
+
fs10.readSync(fd, buf, 0, 8, 0);
|
|
6438
|
+
fs10.closeSync(fd);
|
|
6439
|
+
let i = 0;
|
|
6440
|
+
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
6441
|
+
const b = buf.subarray(i);
|
|
6442
|
+
if (b.length < 4) return false;
|
|
6443
|
+
if (b[0] === 127 && b[1] === 69 && b[2] === 76 && b[3] === 70) return true;
|
|
6444
|
+
const le = b.readUInt32LE(0);
|
|
6445
|
+
const be = b.readUInt32BE(0);
|
|
6446
|
+
const magics = [4277009102, 4277009103, 3405691582, 3199925962];
|
|
6447
|
+
return magics.some((m) => m === le || m === be);
|
|
6448
|
+
} catch {
|
|
6449
|
+
return false;
|
|
6450
|
+
}
|
|
6451
|
+
}
|
|
6452
|
+
function shSingleQuote(arg) {
|
|
6453
|
+
if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
|
|
6454
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
6455
|
+
}
|
|
6456
|
+
function parsePatternEntry(x) {
|
|
6457
|
+
if (x instanceof RegExp) return x;
|
|
6458
|
+
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
6459
|
+
try {
|
|
6460
|
+
const s = x;
|
|
6461
|
+
return new RegExp(s.source, s.flags || "");
|
|
6462
|
+
} catch {
|
|
6463
|
+
return null;
|
|
6464
|
+
}
|
|
6465
|
+
}
|
|
6466
|
+
return null;
|
|
6467
|
+
}
|
|
6468
|
+
function coercePatternArray(raw, fallbacks) {
|
|
6469
|
+
if (!Array.isArray(raw)) return [...fallbacks];
|
|
6470
|
+
const parsed = raw.map(parsePatternEntry).filter((r) => r != null);
|
|
6471
|
+
return parsed.length > 0 ? parsed : [...fallbacks];
|
|
6472
|
+
}
|
|
6473
|
+
var FALLBACK_PROMPT = [
|
|
6474
|
+
/Type your message/i,
|
|
6475
|
+
/>\s*$/,
|
|
6476
|
+
/[›➤]\s*$/,
|
|
6477
|
+
/for shortcuts/i,
|
|
6478
|
+
/\?\s*for help/i,
|
|
6479
|
+
/Press enter/i,
|
|
6480
|
+
/^[\s\u2500-\u257f]*>\s*$/m
|
|
6481
|
+
];
|
|
6482
|
+
var FALLBACK_GENERATING = [
|
|
6483
|
+
/thinking/i,
|
|
6484
|
+
/writing/i,
|
|
6485
|
+
/Claude is/i,
|
|
6486
|
+
/Opus|Sonnet|Haiku/i,
|
|
6487
|
+
/[\u2800-\u28ff]/
|
|
6488
|
+
// Braille spinner blocks
|
|
6489
|
+
];
|
|
6490
|
+
var FALLBACK_APPROVAL = [
|
|
6491
|
+
/approve/i,
|
|
6492
|
+
/Allow( once)?/i,
|
|
6493
|
+
/\(y\/n\)/i,
|
|
6494
|
+
/\[Y\/n\]/i,
|
|
6495
|
+
/continue\?/i,
|
|
6496
|
+
/Run this command/i
|
|
6497
|
+
];
|
|
6498
|
+
function defaultCleanOutput(raw, _lastUserInput) {
|
|
6499
|
+
return stripAnsi(raw).trim();
|
|
6500
|
+
}
|
|
6501
|
+
function normalizeCliProviderForRuntime(raw) {
|
|
6502
|
+
const patterns = raw?.patterns || {};
|
|
6503
|
+
return {
|
|
6504
|
+
...raw,
|
|
6505
|
+
patterns: {
|
|
6506
|
+
prompt: coercePatternArray(patterns.prompt, FALLBACK_PROMPT),
|
|
6507
|
+
generating: coercePatternArray(patterns.generating, FALLBACK_GENERATING),
|
|
6508
|
+
approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
|
|
6509
|
+
ready: coercePatternArray(patterns.ready, [])
|
|
6510
|
+
},
|
|
6511
|
+
cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
|
|
6512
|
+
};
|
|
6513
|
+
}
|
|
5934
6514
|
var ProviderCliAdapter = class {
|
|
5935
6515
|
constructor(provider, workingDir, extraArgs = []) {
|
|
5936
6516
|
this.extraArgs = extraArgs;
|
|
5937
|
-
this.provider = provider;
|
|
6517
|
+
this.provider = normalizeCliProviderForRuntime(provider);
|
|
5938
6518
|
this.cliType = provider.type;
|
|
5939
6519
|
this.cliName = provider.name;
|
|
5940
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
6520
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
|
|
5941
6521
|
const t = provider.timeouts || {};
|
|
5942
6522
|
this.timeouts = {
|
|
5943
6523
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -5995,20 +6575,25 @@ var ProviderCliAdapter = class {
|
|
|
5995
6575
|
if (!pty) throw new Error("node-pty is not installed");
|
|
5996
6576
|
const { spawn: spawnConfig } = this.provider;
|
|
5997
6577
|
const binaryPath = findBinary(spawnConfig.command);
|
|
5998
|
-
const isWin =
|
|
6578
|
+
const isWin = os11.platform() === "win32";
|
|
5999
6579
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
6000
6580
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
6001
6581
|
let shellCmd;
|
|
6002
6582
|
let shellArgs;
|
|
6003
|
-
|
|
6583
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
6584
|
+
const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
|
|
6585
|
+
if (useShell) {
|
|
6586
|
+
if (!spawnConfig.shell && !isWin) {
|
|
6587
|
+
LOG.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
|
|
6588
|
+
}
|
|
6004
6589
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
6005
|
-
const fullCmd = [binaryPath, ...allArgs].join(" ");
|
|
6590
|
+
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
6006
6591
|
shellArgs = isWin ? ["/c", fullCmd] : ["-l", "-c", fullCmd];
|
|
6007
6592
|
} else {
|
|
6008
6593
|
shellCmd = binaryPath;
|
|
6009
6594
|
shellArgs = allArgs;
|
|
6010
6595
|
}
|
|
6011
|
-
|
|
6596
|
+
const ptyOpts = {
|
|
6012
6597
|
name: "xterm-256color",
|
|
6013
6598
|
cols: 120,
|
|
6014
6599
|
rows: 40,
|
|
@@ -6017,7 +6602,21 @@ var ProviderCliAdapter = class {
|
|
|
6017
6602
|
...process.env,
|
|
6018
6603
|
...spawnConfig.env
|
|
6019
6604
|
}
|
|
6020
|
-
}
|
|
6605
|
+
};
|
|
6606
|
+
try {
|
|
6607
|
+
this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
|
|
6608
|
+
} catch (err) {
|
|
6609
|
+
const msg = err?.message || String(err);
|
|
6610
|
+
if (!isWin && !useShell && /posix_spawn|spawn/i.test(msg)) {
|
|
6611
|
+
LOG.warn("CLI", `[${this.cliType}] Direct spawn failed (${msg}), retrying via login shell`);
|
|
6612
|
+
shellCmd = process.env.SHELL || "/bin/zsh";
|
|
6613
|
+
const fullCmd = [binaryPath, ...allArgs].map(shSingleQuote).join(" ");
|
|
6614
|
+
shellArgs = ["-l", "-c", fullCmd];
|
|
6615
|
+
this.ptyProcess = pty.spawn(shellCmd, shellArgs, ptyOpts);
|
|
6616
|
+
} else {
|
|
6617
|
+
throw err;
|
|
6618
|
+
}
|
|
6619
|
+
}
|
|
6021
6620
|
this.ptyProcess.onData((data) => {
|
|
6022
6621
|
this.handleOutput(data);
|
|
6023
6622
|
if (this.onPtyDataCallback) {
|
|
@@ -6235,6 +6834,7 @@ var ProviderCliAdapter = class {
|
|
|
6235
6834
|
|
|
6236
6835
|
// src/commands/cli-manager.ts
|
|
6237
6836
|
init_config();
|
|
6837
|
+
init_workspaces();
|
|
6238
6838
|
|
|
6239
6839
|
// src/providers/cli-provider-instance.ts
|
|
6240
6840
|
var crypto3 = __toESM(require("crypto"));
|
|
@@ -6400,7 +7000,7 @@ var CliProviderInstance = class {
|
|
|
6400
7000
|
|
|
6401
7001
|
// src/providers/acp-provider-instance.ts
|
|
6402
7002
|
var import_stream = require("stream");
|
|
6403
|
-
var
|
|
7003
|
+
var import_child_process6 = require("child_process");
|
|
6404
7004
|
var import_sdk = require("@agentclientprotocol/sdk");
|
|
6405
7005
|
|
|
6406
7006
|
// src/providers/contracts.ts
|
|
@@ -6721,7 +7321,7 @@ var AcpProviderInstance = class {
|
|
|
6721
7321
|
this.errorMessage = null;
|
|
6722
7322
|
this.errorReason = null;
|
|
6723
7323
|
this.stderrBuffer = [];
|
|
6724
|
-
this.process = (0,
|
|
7324
|
+
this.process = (0, import_child_process6.spawn)(command, args, {
|
|
6725
7325
|
cwd: this.workingDir,
|
|
6726
7326
|
env,
|
|
6727
7327
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -6825,13 +7425,13 @@ var AcpProviderInstance = class {
|
|
|
6825
7425
|
}
|
|
6826
7426
|
this.currentStatus = "waiting_approval";
|
|
6827
7427
|
this.detectStatusTransition();
|
|
6828
|
-
const approved = await new Promise((
|
|
6829
|
-
this.permissionResolvers.push(
|
|
7428
|
+
const approved = await new Promise((resolve7) => {
|
|
7429
|
+
this.permissionResolvers.push(resolve7);
|
|
6830
7430
|
setTimeout(() => {
|
|
6831
|
-
const idx = this.permissionResolvers.indexOf(
|
|
7431
|
+
const idx = this.permissionResolvers.indexOf(resolve7);
|
|
6832
7432
|
if (idx >= 0) {
|
|
6833
7433
|
this.permissionResolvers.splice(idx, 1);
|
|
6834
|
-
|
|
7434
|
+
resolve7(false);
|
|
6835
7435
|
}
|
|
6836
7436
|
}, 3e5);
|
|
6837
7437
|
});
|
|
@@ -7301,6 +7901,24 @@ var DaemonCliManager = class {
|
|
|
7301
7901
|
const hash = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
|
|
7302
7902
|
return `${cliType}_${hash}`;
|
|
7303
7903
|
}
|
|
7904
|
+
persistRecentDir(cliType, dir) {
|
|
7905
|
+
try {
|
|
7906
|
+
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
7907
|
+
const provider = this.providerLoader.getByAlias(cliType);
|
|
7908
|
+
const actKind = provider?.category === "acp" ? "acp" : "cli";
|
|
7909
|
+
let next = loadConfig();
|
|
7910
|
+
console.log(import_chalk.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
7911
|
+
const recent = next.recentCliWorkspaces || [];
|
|
7912
|
+
if (!recent.includes(dir)) {
|
|
7913
|
+
next = { ...next, recentCliWorkspaces: [dir, ...recent].slice(0, 10) };
|
|
7914
|
+
}
|
|
7915
|
+
next = appendWorkspaceActivity(next, dir, { kind: actKind, agentType: normalizedType });
|
|
7916
|
+
saveConfig(next);
|
|
7917
|
+
console.log(import_chalk.default.green(` \u2713 Recent workspace saved: ${dir}`));
|
|
7918
|
+
} catch (e) {
|
|
7919
|
+
console.error(import_chalk.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
7920
|
+
}
|
|
7921
|
+
}
|
|
7304
7922
|
createAdapter(cliType, workingDir, cliArgs) {
|
|
7305
7923
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
7306
7924
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
@@ -7312,8 +7930,9 @@ var DaemonCliManager = class {
|
|
|
7312
7930
|
}
|
|
7313
7931
|
// ─── Session start/management ──────────────────────────────
|
|
7314
7932
|
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
7315
|
-
const trimmed = (workingDir ||
|
|
7316
|
-
|
|
7933
|
+
const trimmed = (workingDir || "").trim();
|
|
7934
|
+
if (!trimmed) throw new Error("working directory required");
|
|
7935
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path10.resolve(trimmed);
|
|
7317
7936
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
7318
7937
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
7319
7938
|
const key = crypto4.randomUUID();
|
|
@@ -7323,8 +7942,8 @@ var DaemonCliManager = class {
|
|
|
7323
7942
|
const spawnCmd = provider.spawn?.command;
|
|
7324
7943
|
if (spawnCmd) {
|
|
7325
7944
|
try {
|
|
7326
|
-
const { execSync:
|
|
7327
|
-
|
|
7945
|
+
const { execSync: execSync7 } = require("child_process");
|
|
7946
|
+
execSync7(`which ${spawnCmd}`, { stdio: "ignore" });
|
|
7328
7947
|
} catch {
|
|
7329
7948
|
const installInfo = provider.install || `Install: check ${provider.displayName || provider.name} documentation`;
|
|
7330
7949
|
throw new Error(
|
|
@@ -7391,18 +8010,52 @@ ${installInfo}`
|
|
|
7391
8010
|
const instanceManager = this.deps.getInstanceManager();
|
|
7392
8011
|
if (provider && instanceManager) {
|
|
7393
8012
|
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key);
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
8013
|
+
try {
|
|
8014
|
+
await instanceManager.addInstance(key, cliInstance, {
|
|
8015
|
+
serverConn: this.deps.getServerConn(),
|
|
8016
|
+
settings: {},
|
|
8017
|
+
onPtyData: (data) => {
|
|
8018
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
8019
|
+
}
|
|
8020
|
+
});
|
|
8021
|
+
} catch (spawnErr) {
|
|
8022
|
+
LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
8023
|
+
instanceManager.removeInstance(key);
|
|
8024
|
+
throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
|
|
8025
|
+
}
|
|
7401
8026
|
this.adapters.set(key, cliInstance.getAdapter());
|
|
7402
8027
|
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
8028
|
+
const checkStopped = setInterval(() => {
|
|
8029
|
+
try {
|
|
8030
|
+
const adapter = this.adapters.get(key);
|
|
8031
|
+
if (!adapter) {
|
|
8032
|
+
clearInterval(checkStopped);
|
|
8033
|
+
return;
|
|
8034
|
+
}
|
|
8035
|
+
const status = adapter.getStatus?.();
|
|
8036
|
+
if (status?.status === "stopped" || status?.status === "error") {
|
|
8037
|
+
clearInterval(checkStopped);
|
|
8038
|
+
setTimeout(() => {
|
|
8039
|
+
if (this.adapters.has(key)) {
|
|
8040
|
+
this.adapters.delete(key);
|
|
8041
|
+
this.deps.removeAgentTracking(key);
|
|
8042
|
+
instanceManager.removeInstance(key);
|
|
8043
|
+
LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
|
|
8044
|
+
this.deps.onStatusChange();
|
|
8045
|
+
}
|
|
8046
|
+
}, 5e3);
|
|
8047
|
+
}
|
|
8048
|
+
} catch {
|
|
8049
|
+
}
|
|
8050
|
+
}, 3e3);
|
|
7403
8051
|
} else {
|
|
7404
8052
|
const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
|
|
7405
|
-
|
|
8053
|
+
try {
|
|
8054
|
+
await adapter.spawn();
|
|
8055
|
+
} catch (spawnErr) {
|
|
8056
|
+
LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
|
|
8057
|
+
throw new Error(`Failed to start ${cliInfo.displayName}: ${spawnErr?.message}`);
|
|
8058
|
+
}
|
|
7406
8059
|
const serverConn = this.deps.getServerConn();
|
|
7407
8060
|
if (serverConn && typeof adapter.setServerConn === "function") {
|
|
7408
8061
|
adapter.setServerConn(serverConn);
|
|
@@ -7410,12 +8063,12 @@ ${installInfo}`
|
|
|
7410
8063
|
adapter.setOnStatusChange(() => {
|
|
7411
8064
|
this.deps.onStatusChange();
|
|
7412
8065
|
const status = adapter.getStatus?.();
|
|
7413
|
-
if (status?.status === "stopped") {
|
|
8066
|
+
if (status?.status === "stopped" || status?.status === "error") {
|
|
7414
8067
|
setTimeout(() => {
|
|
7415
8068
|
if (this.adapters.get(key) === adapter) {
|
|
7416
8069
|
this.adapters.delete(key);
|
|
7417
8070
|
this.deps.removeAgentTracking(key);
|
|
7418
|
-
|
|
8071
|
+
LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${adapter.cliType}`);
|
|
7419
8072
|
this.deps.onStatusChange();
|
|
7420
8073
|
}
|
|
7421
8074
|
}, 3e3);
|
|
@@ -7439,12 +8092,24 @@ ${installInfo}`
|
|
|
7439
8092
|
async stopSession(key) {
|
|
7440
8093
|
const adapter = this.adapters.get(key);
|
|
7441
8094
|
if (adapter) {
|
|
7442
|
-
|
|
8095
|
+
try {
|
|
8096
|
+
adapter.shutdown();
|
|
8097
|
+
} catch (e) {
|
|
8098
|
+
LOG.warn("CLI", `Shutdown error for ${adapter.cliType}: ${e?.message} (force-cleaning)`);
|
|
8099
|
+
}
|
|
7443
8100
|
this.adapters.delete(key);
|
|
7444
8101
|
this.deps.removeAgentTracking(key);
|
|
7445
8102
|
this.deps.getInstanceManager()?.removeInstance(key);
|
|
7446
|
-
|
|
8103
|
+
LOG.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
|
|
7447
8104
|
this.deps.onStatusChange();
|
|
8105
|
+
} else {
|
|
8106
|
+
const im = this.deps.getInstanceManager();
|
|
8107
|
+
if (im) {
|
|
8108
|
+
im.removeInstance(key);
|
|
8109
|
+
this.deps.removeAgentTracking(key);
|
|
8110
|
+
LOG.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
|
|
8111
|
+
this.deps.onStatusChange();
|
|
8112
|
+
}
|
|
7448
8113
|
}
|
|
7449
8114
|
}
|
|
7450
8115
|
shutdownAll() {
|
|
@@ -7485,8 +8150,28 @@ ${installInfo}`
|
|
|
7485
8150
|
switch (cmd) {
|
|
7486
8151
|
case "launch_cli": {
|
|
7487
8152
|
const cliType = args?.cliType;
|
|
7488
|
-
const
|
|
7489
|
-
const
|
|
8153
|
+
const config = loadConfig();
|
|
8154
|
+
const resolved = resolveLaunchDirectory(
|
|
8155
|
+
{
|
|
8156
|
+
dir: args?.dir,
|
|
8157
|
+
workspaceId: args?.workspaceId,
|
|
8158
|
+
useDefaultWorkspace: args?.useDefaultWorkspace === true,
|
|
8159
|
+
useHome: args?.useHome === true
|
|
8160
|
+
},
|
|
8161
|
+
config
|
|
8162
|
+
);
|
|
8163
|
+
if (!resolved.ok) {
|
|
8164
|
+
const ws = getWorkspaceState(config);
|
|
8165
|
+
return {
|
|
8166
|
+
success: false,
|
|
8167
|
+
error: resolved.message,
|
|
8168
|
+
code: resolved.code,
|
|
8169
|
+
workspaces: ws.workspaces,
|
|
8170
|
+
defaultWorkspacePath: ws.defaultWorkspacePath
|
|
8171
|
+
};
|
|
8172
|
+
}
|
|
8173
|
+
const dir = resolved.path;
|
|
8174
|
+
const launchSource = resolved.source;
|
|
7490
8175
|
if (!cliType) throw new Error("cliType required");
|
|
7491
8176
|
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
|
|
7492
8177
|
let newKey = null;
|
|
@@ -7495,19 +8180,8 @@ ${installInfo}`
|
|
|
7495
8180
|
newKey = k;
|
|
7496
8181
|
}
|
|
7497
8182
|
}
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
console.log(import_chalk.default.cyan(` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
7501
|
-
const recent = config.recentCliWorkspaces || [];
|
|
7502
|
-
if (!recent.includes(dir)) {
|
|
7503
|
-
const updated = [dir, ...recent].slice(0, 10);
|
|
7504
|
-
saveConfig({ ...config, recentCliWorkspaces: updated });
|
|
7505
|
-
console.log(import_chalk.default.green(` \u2713 Recent workspace saved: ${dir}`));
|
|
7506
|
-
}
|
|
7507
|
-
} catch (e) {
|
|
7508
|
-
console.error(import_chalk.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
7509
|
-
}
|
|
7510
|
-
return { success: true, cliType, dir, id: newKey, defaultedToHome };
|
|
8183
|
+
this.persistRecentDir(cliType, dir);
|
|
8184
|
+
return { success: true, cliType, dir, id: newKey, launchSource };
|
|
7511
8185
|
}
|
|
7512
8186
|
case "stop_cli": {
|
|
7513
8187
|
const cliType = args?.cliType;
|
|
@@ -7523,11 +8197,32 @@ ${installInfo}`
|
|
|
7523
8197
|
}
|
|
7524
8198
|
case "restart_session": {
|
|
7525
8199
|
const cliType = args?.cliType || args?.agentType || args?.ideType;
|
|
7526
|
-
const
|
|
8200
|
+
const cfg = loadConfig();
|
|
8201
|
+
const rdir = resolveLaunchDirectory(
|
|
8202
|
+
{
|
|
8203
|
+
dir: args?.dir,
|
|
8204
|
+
workspaceId: args?.workspaceId,
|
|
8205
|
+
useDefaultWorkspace: args?.useDefaultWorkspace === true,
|
|
8206
|
+
useHome: args?.useHome === true
|
|
8207
|
+
},
|
|
8208
|
+
cfg
|
|
8209
|
+
);
|
|
8210
|
+
if (!rdir.ok) {
|
|
8211
|
+
const ws = getWorkspaceState(cfg);
|
|
8212
|
+
return {
|
|
8213
|
+
success: false,
|
|
8214
|
+
error: rdir.message,
|
|
8215
|
+
code: rdir.code,
|
|
8216
|
+
workspaces: ws.workspaces,
|
|
8217
|
+
defaultWorkspacePath: ws.defaultWorkspacePath
|
|
8218
|
+
};
|
|
8219
|
+
}
|
|
8220
|
+
const dir = rdir.path;
|
|
7527
8221
|
if (!cliType) throw new Error("cliType required");
|
|
7528
8222
|
const found = this.findAdapter(cliType, { instanceKey: args?._targetInstance, dir });
|
|
7529
8223
|
if (found) await this.stopSession(found.key);
|
|
7530
8224
|
await this.startSession(cliType, dir);
|
|
8225
|
+
this.persistRecentDir(cliType, dir);
|
|
7531
8226
|
return { success: true, restarted: true };
|
|
7532
8227
|
}
|
|
7533
8228
|
case "agent_command": {
|
|
@@ -8167,12 +8862,12 @@ var ProviderInstanceManager = class {
|
|
|
8167
8862
|
};
|
|
8168
8863
|
|
|
8169
8864
|
// src/providers/version-archive.ts
|
|
8170
|
-
var
|
|
8171
|
-
var
|
|
8172
|
-
var
|
|
8173
|
-
var
|
|
8865
|
+
var fs8 = __toESM(require("fs"));
|
|
8866
|
+
var path11 = __toESM(require("path"));
|
|
8867
|
+
var os13 = __toESM(require("os"));
|
|
8868
|
+
var import_child_process7 = require("child_process");
|
|
8174
8869
|
var import_os3 = require("os");
|
|
8175
|
-
var ARCHIVE_PATH =
|
|
8870
|
+
var ARCHIVE_PATH = path11.join(os13.homedir(), ".adhdev", "version-history.json");
|
|
8176
8871
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
8177
8872
|
var VersionArchive = class {
|
|
8178
8873
|
history = {};
|
|
@@ -8181,8 +8876,8 @@ var VersionArchive = class {
|
|
|
8181
8876
|
}
|
|
8182
8877
|
load() {
|
|
8183
8878
|
try {
|
|
8184
|
-
if (
|
|
8185
|
-
this.history = JSON.parse(
|
|
8879
|
+
if (fs8.existsSync(ARCHIVE_PATH)) {
|
|
8880
|
+
this.history = JSON.parse(fs8.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
8186
8881
|
}
|
|
8187
8882
|
} catch {
|
|
8188
8883
|
this.history = {};
|
|
@@ -8219,15 +8914,15 @@ var VersionArchive = class {
|
|
|
8219
8914
|
}
|
|
8220
8915
|
save() {
|
|
8221
8916
|
try {
|
|
8222
|
-
|
|
8223
|
-
|
|
8917
|
+
fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
|
|
8918
|
+
fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
8224
8919
|
} catch {
|
|
8225
8920
|
}
|
|
8226
8921
|
}
|
|
8227
8922
|
};
|
|
8228
8923
|
function runCommand(cmd, timeout = 1e4) {
|
|
8229
8924
|
try {
|
|
8230
|
-
return (0,
|
|
8925
|
+
return (0, import_child_process7.execSync)(cmd, {
|
|
8231
8926
|
encoding: "utf-8",
|
|
8232
8927
|
timeout,
|
|
8233
8928
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -8259,19 +8954,19 @@ function getVersion(binary, versionCommand) {
|
|
|
8259
8954
|
function checkPathExists2(paths) {
|
|
8260
8955
|
for (const p of paths) {
|
|
8261
8956
|
if (p.includes("*")) {
|
|
8262
|
-
const home =
|
|
8263
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
8264
|
-
if (
|
|
8957
|
+
const home = os13.homedir();
|
|
8958
|
+
const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
|
|
8959
|
+
if (fs8.existsSync(resolved)) return resolved;
|
|
8265
8960
|
} else {
|
|
8266
|
-
if (
|
|
8961
|
+
if (fs8.existsSync(p)) return p;
|
|
8267
8962
|
}
|
|
8268
8963
|
}
|
|
8269
8964
|
return null;
|
|
8270
8965
|
}
|
|
8271
8966
|
function getMacAppVersion(appPath) {
|
|
8272
8967
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
8273
|
-
const plistPath =
|
|
8274
|
-
if (!
|
|
8968
|
+
const plistPath = path11.join(appPath, "Contents", "Info.plist");
|
|
8969
|
+
if (!fs8.existsSync(plistPath)) return null;
|
|
8275
8970
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
8276
8971
|
return raw || null;
|
|
8277
8972
|
}
|
|
@@ -8296,8 +8991,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
8296
8991
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
8297
8992
|
let resolvedBin = cliBin;
|
|
8298
8993
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
8299
|
-
const bundled =
|
|
8300
|
-
if (provider.cli &&
|
|
8994
|
+
const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
8995
|
+
if (provider.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
|
|
8301
8996
|
}
|
|
8302
8997
|
info.installed = !!(appPath || resolvedBin);
|
|
8303
8998
|
info.path = appPath || null;
|
|
@@ -8336,9 +9031,9 @@ async function detectAllVersions(loader, archive) {
|
|
|
8336
9031
|
|
|
8337
9032
|
// src/daemon/dev-server.ts
|
|
8338
9033
|
var http2 = __toESM(require("http"));
|
|
8339
|
-
var
|
|
8340
|
-
var
|
|
8341
|
-
var
|
|
9034
|
+
var fs9 = __toESM(require("fs"));
|
|
9035
|
+
var path12 = __toESM(require("path"));
|
|
9036
|
+
var os14 = __toESM(require("os"));
|
|
8342
9037
|
|
|
8343
9038
|
// src/daemon/scaffold-template.ts
|
|
8344
9039
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -8741,8 +9436,8 @@ var DevServer = class _DevServer {
|
|
|
8741
9436
|
}
|
|
8742
9437
|
getEndpointList() {
|
|
8743
9438
|
return this.routes.map((r) => {
|
|
8744
|
-
const
|
|
8745
|
-
return `${r.method.padEnd(5)} ${
|
|
9439
|
+
const path13 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
9440
|
+
return `${r.method.padEnd(5)} ${path13}`;
|
|
8746
9441
|
});
|
|
8747
9442
|
}
|
|
8748
9443
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -8773,15 +9468,15 @@ var DevServer = class _DevServer {
|
|
|
8773
9468
|
this.json(res, 500, { error: e.message });
|
|
8774
9469
|
}
|
|
8775
9470
|
});
|
|
8776
|
-
return new Promise((
|
|
9471
|
+
return new Promise((resolve7, reject) => {
|
|
8777
9472
|
this.server.listen(port, "127.0.0.1", () => {
|
|
8778
9473
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
8779
|
-
|
|
9474
|
+
resolve7();
|
|
8780
9475
|
});
|
|
8781
9476
|
this.server.on("error", (e) => {
|
|
8782
9477
|
if (e.code === "EADDRINUSE") {
|
|
8783
9478
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
8784
|
-
|
|
9479
|
+
resolve7();
|
|
8785
9480
|
} else {
|
|
8786
9481
|
reject(e);
|
|
8787
9482
|
}
|
|
@@ -8864,20 +9559,20 @@ var DevServer = class _DevServer {
|
|
|
8864
9559
|
child.stderr?.on("data", (d) => {
|
|
8865
9560
|
stderr += d.toString().slice(0, 2e3);
|
|
8866
9561
|
});
|
|
8867
|
-
await new Promise((
|
|
9562
|
+
await new Promise((resolve7) => {
|
|
8868
9563
|
const timer = setTimeout(() => {
|
|
8869
9564
|
child.kill();
|
|
8870
|
-
|
|
9565
|
+
resolve7();
|
|
8871
9566
|
}, 3e3);
|
|
8872
9567
|
child.on("exit", () => {
|
|
8873
9568
|
clearTimeout(timer);
|
|
8874
|
-
|
|
9569
|
+
resolve7();
|
|
8875
9570
|
});
|
|
8876
9571
|
child.stdout?.once("data", () => {
|
|
8877
9572
|
setTimeout(() => {
|
|
8878
9573
|
child.kill();
|
|
8879
9574
|
clearTimeout(timer);
|
|
8880
|
-
|
|
9575
|
+
resolve7();
|
|
8881
9576
|
}, 500);
|
|
8882
9577
|
});
|
|
8883
9578
|
});
|
|
@@ -9087,12 +9782,12 @@ var DevServer = class _DevServer {
|
|
|
9087
9782
|
// ─── DevConsole SPA ───
|
|
9088
9783
|
getConsoleDistDir() {
|
|
9089
9784
|
const candidates = [
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9785
|
+
path12.resolve(__dirname, "../../web-devconsole/dist"),
|
|
9786
|
+
path12.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
9787
|
+
path12.join(process.cwd(), "packages/web-devconsole/dist")
|
|
9093
9788
|
];
|
|
9094
9789
|
for (const dir of candidates) {
|
|
9095
|
-
if (
|
|
9790
|
+
if (fs9.existsSync(path12.join(dir, "index.html"))) return dir;
|
|
9096
9791
|
}
|
|
9097
9792
|
return null;
|
|
9098
9793
|
}
|
|
@@ -9102,9 +9797,9 @@ var DevServer = class _DevServer {
|
|
|
9102
9797
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
9103
9798
|
return;
|
|
9104
9799
|
}
|
|
9105
|
-
const htmlPath =
|
|
9800
|
+
const htmlPath = path12.join(distDir, "index.html");
|
|
9106
9801
|
try {
|
|
9107
|
-
const html =
|
|
9802
|
+
const html = fs9.readFileSync(htmlPath, "utf-8");
|
|
9108
9803
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
9109
9804
|
res.end(html);
|
|
9110
9805
|
} catch (e) {
|
|
@@ -9127,15 +9822,15 @@ var DevServer = class _DevServer {
|
|
|
9127
9822
|
this.json(res, 404, { error: "Not found" });
|
|
9128
9823
|
return;
|
|
9129
9824
|
}
|
|
9130
|
-
const safePath =
|
|
9131
|
-
const filePath =
|
|
9825
|
+
const safePath = path12.normalize(pathname).replace(/^\.\.\//, "");
|
|
9826
|
+
const filePath = path12.join(distDir, safePath);
|
|
9132
9827
|
if (!filePath.startsWith(distDir)) {
|
|
9133
9828
|
this.json(res, 403, { error: "Forbidden" });
|
|
9134
9829
|
return;
|
|
9135
9830
|
}
|
|
9136
9831
|
try {
|
|
9137
|
-
const content =
|
|
9138
|
-
const ext =
|
|
9832
|
+
const content = fs9.readFileSync(filePath);
|
|
9833
|
+
const ext = path12.extname(filePath);
|
|
9139
9834
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
9140
9835
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
9141
9836
|
res.end(content);
|
|
@@ -9234,26 +9929,26 @@ var DevServer = class _DevServer {
|
|
|
9234
9929
|
const provider = this.providerLoader.getMeta(type);
|
|
9235
9930
|
if (!provider) return null;
|
|
9236
9931
|
const cat = provider.category;
|
|
9237
|
-
const builtinDir = this.providerLoader.builtinDir ||
|
|
9238
|
-
const userDir =
|
|
9932
|
+
const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
|
|
9933
|
+
const userDir = path12.join(os14.homedir(), ".adhdev", "providers");
|
|
9239
9934
|
const directCandidates = [
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9935
|
+
path12.join(userDir, type),
|
|
9936
|
+
path12.join(builtinDir, cat, type),
|
|
9937
|
+
path12.join(builtinDir, type)
|
|
9243
9938
|
];
|
|
9244
9939
|
for (const d of directCandidates) {
|
|
9245
|
-
if (
|
|
9940
|
+
if (fs9.existsSync(path12.join(d, "provider.json"))) return d;
|
|
9246
9941
|
}
|
|
9247
|
-
const catDir =
|
|
9248
|
-
if (
|
|
9942
|
+
const catDir = path12.join(builtinDir, cat);
|
|
9943
|
+
if (fs9.existsSync(catDir)) {
|
|
9249
9944
|
try {
|
|
9250
|
-
for (const entry of
|
|
9945
|
+
for (const entry of fs9.readdirSync(catDir, { withFileTypes: true })) {
|
|
9251
9946
|
if (!entry.isDirectory()) continue;
|
|
9252
|
-
const jsonPath =
|
|
9253
|
-
if (
|
|
9947
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
9948
|
+
if (fs9.existsSync(jsonPath)) {
|
|
9254
9949
|
try {
|
|
9255
|
-
const data = JSON.parse(
|
|
9256
|
-
if (data.type === type) return
|
|
9950
|
+
const data = JSON.parse(fs9.readFileSync(jsonPath, "utf-8"));
|
|
9951
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
9257
9952
|
} catch {
|
|
9258
9953
|
}
|
|
9259
9954
|
}
|
|
@@ -9273,14 +9968,14 @@ var DevServer = class _DevServer {
|
|
|
9273
9968
|
const files = [];
|
|
9274
9969
|
const scan = (d, prefix) => {
|
|
9275
9970
|
try {
|
|
9276
|
-
for (const entry of
|
|
9971
|
+
for (const entry of fs9.readdirSync(d, { withFileTypes: true })) {
|
|
9277
9972
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
9278
9973
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
9279
9974
|
if (entry.isDirectory()) {
|
|
9280
9975
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
9281
|
-
scan(
|
|
9976
|
+
scan(path12.join(d, entry.name), rel);
|
|
9282
9977
|
} else {
|
|
9283
|
-
const stat =
|
|
9978
|
+
const stat = fs9.statSync(path12.join(d, entry.name));
|
|
9284
9979
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
9285
9980
|
}
|
|
9286
9981
|
}
|
|
@@ -9303,16 +9998,16 @@ var DevServer = class _DevServer {
|
|
|
9303
9998
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
9304
9999
|
return;
|
|
9305
10000
|
}
|
|
9306
|
-
const fullPath =
|
|
10001
|
+
const fullPath = path12.resolve(dir, path12.normalize(filePath));
|
|
9307
10002
|
if (!fullPath.startsWith(dir)) {
|
|
9308
10003
|
this.json(res, 403, { error: "Forbidden" });
|
|
9309
10004
|
return;
|
|
9310
10005
|
}
|
|
9311
|
-
if (!
|
|
10006
|
+
if (!fs9.existsSync(fullPath) || fs9.statSync(fullPath).isDirectory()) {
|
|
9312
10007
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
9313
10008
|
return;
|
|
9314
10009
|
}
|
|
9315
|
-
const content =
|
|
10010
|
+
const content = fs9.readFileSync(fullPath, "utf-8");
|
|
9316
10011
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
9317
10012
|
}
|
|
9318
10013
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -9328,15 +10023,15 @@ var DevServer = class _DevServer {
|
|
|
9328
10023
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
9329
10024
|
return;
|
|
9330
10025
|
}
|
|
9331
|
-
const fullPath =
|
|
10026
|
+
const fullPath = path12.resolve(dir, path12.normalize(filePath));
|
|
9332
10027
|
if (!fullPath.startsWith(dir)) {
|
|
9333
10028
|
this.json(res, 403, { error: "Forbidden" });
|
|
9334
10029
|
return;
|
|
9335
10030
|
}
|
|
9336
10031
|
try {
|
|
9337
|
-
if (
|
|
9338
|
-
|
|
9339
|
-
|
|
10032
|
+
if (fs9.existsSync(fullPath)) fs9.copyFileSync(fullPath, fullPath + ".bak");
|
|
10033
|
+
fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
|
|
10034
|
+
fs9.writeFileSync(fullPath, content, "utf-8");
|
|
9340
10035
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
9341
10036
|
this.providerLoader.reload();
|
|
9342
10037
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -9352,9 +10047,9 @@ var DevServer = class _DevServer {
|
|
|
9352
10047
|
return;
|
|
9353
10048
|
}
|
|
9354
10049
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
9355
|
-
const p =
|
|
9356
|
-
if (
|
|
9357
|
-
const source =
|
|
10050
|
+
const p = path12.join(dir, name);
|
|
10051
|
+
if (fs9.existsSync(p)) {
|
|
10052
|
+
const source = fs9.readFileSync(p, "utf-8");
|
|
9358
10053
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
9359
10054
|
return;
|
|
9360
10055
|
}
|
|
@@ -9373,11 +10068,11 @@ var DevServer = class _DevServer {
|
|
|
9373
10068
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
9374
10069
|
return;
|
|
9375
10070
|
}
|
|
9376
|
-
const target =
|
|
9377
|
-
const targetPath =
|
|
10071
|
+
const target = fs9.existsSync(path12.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
10072
|
+
const targetPath = path12.join(dir, target);
|
|
9378
10073
|
try {
|
|
9379
|
-
if (
|
|
9380
|
-
|
|
10074
|
+
if (fs9.existsSync(targetPath)) fs9.copyFileSync(targetPath, targetPath + ".bak");
|
|
10075
|
+
fs9.writeFileSync(targetPath, source, "utf-8");
|
|
9381
10076
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
9382
10077
|
this.providerLoader.reload();
|
|
9383
10078
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -9392,18 +10087,18 @@ var DevServer = class _DevServer {
|
|
|
9392
10087
|
return;
|
|
9393
10088
|
}
|
|
9394
10089
|
let scriptsPath = "";
|
|
9395
|
-
const directScripts =
|
|
9396
|
-
if (
|
|
10090
|
+
const directScripts = path12.join(dir, "scripts.js");
|
|
10091
|
+
if (fs9.existsSync(directScripts)) {
|
|
9397
10092
|
scriptsPath = directScripts;
|
|
9398
10093
|
} else {
|
|
9399
|
-
const scriptsDir =
|
|
9400
|
-
if (
|
|
9401
|
-
const versions =
|
|
9402
|
-
return
|
|
10094
|
+
const scriptsDir = path12.join(dir, "scripts");
|
|
10095
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
10096
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
10097
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
9403
10098
|
}).sort().reverse();
|
|
9404
10099
|
for (const ver of versions) {
|
|
9405
|
-
const p =
|
|
9406
|
-
if (
|
|
10100
|
+
const p = path12.join(scriptsDir, ver, "scripts.js");
|
|
10101
|
+
if (fs9.existsSync(p)) {
|
|
9407
10102
|
scriptsPath = p;
|
|
9408
10103
|
break;
|
|
9409
10104
|
}
|
|
@@ -9415,7 +10110,7 @@ var DevServer = class _DevServer {
|
|
|
9415
10110
|
return;
|
|
9416
10111
|
}
|
|
9417
10112
|
try {
|
|
9418
|
-
const source =
|
|
10113
|
+
const source = fs9.readFileSync(scriptsPath, "utf-8");
|
|
9419
10114
|
const hints = {};
|
|
9420
10115
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
9421
10116
|
let match;
|
|
@@ -9559,14 +10254,14 @@ var DevServer = class _DevServer {
|
|
|
9559
10254
|
child.stderr?.on("data", (d) => {
|
|
9560
10255
|
stderr += d.toString();
|
|
9561
10256
|
});
|
|
9562
|
-
await new Promise((
|
|
10257
|
+
await new Promise((resolve7) => {
|
|
9563
10258
|
const timer = setTimeout(() => {
|
|
9564
10259
|
child.kill();
|
|
9565
|
-
|
|
10260
|
+
resolve7();
|
|
9566
10261
|
}, timeout);
|
|
9567
10262
|
child.on("exit", () => {
|
|
9568
10263
|
clearTimeout(timer);
|
|
9569
|
-
|
|
10264
|
+
resolve7();
|
|
9570
10265
|
});
|
|
9571
10266
|
});
|
|
9572
10267
|
const elapsed = Date.now() - start;
|
|
@@ -9616,26 +10311,26 @@ var DevServer = class _DevServer {
|
|
|
9616
10311
|
}
|
|
9617
10312
|
let targetDir;
|
|
9618
10313
|
if (location === "user") {
|
|
9619
|
-
targetDir =
|
|
10314
|
+
targetDir = path12.join(os14.homedir(), ".adhdev", "providers", type);
|
|
9620
10315
|
} else {
|
|
9621
|
-
const builtinDir =
|
|
9622
|
-
targetDir =
|
|
10316
|
+
const builtinDir = path12.resolve(__dirname, "../providers/_builtin");
|
|
10317
|
+
targetDir = path12.join(builtinDir, category, type);
|
|
9623
10318
|
}
|
|
9624
|
-
const jsonPath =
|
|
9625
|
-
if (
|
|
10319
|
+
const jsonPath = path12.join(targetDir, "provider.json");
|
|
10320
|
+
if (fs9.existsSync(jsonPath)) {
|
|
9626
10321
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
9627
10322
|
return;
|
|
9628
10323
|
}
|
|
9629
10324
|
try {
|
|
9630
10325
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version });
|
|
9631
|
-
|
|
9632
|
-
|
|
10326
|
+
fs9.mkdirSync(targetDir, { recursive: true });
|
|
10327
|
+
fs9.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
9633
10328
|
const createdFiles = ["provider.json"];
|
|
9634
10329
|
if (result.files) {
|
|
9635
10330
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
9636
|
-
const fullPath =
|
|
9637
|
-
|
|
9638
|
-
|
|
10331
|
+
const fullPath = path12.join(targetDir, relPath);
|
|
10332
|
+
fs9.mkdirSync(path12.dirname(fullPath), { recursive: true });
|
|
10333
|
+
fs9.writeFileSync(fullPath, content, "utf-8");
|
|
9639
10334
|
createdFiles.push(relPath);
|
|
9640
10335
|
}
|
|
9641
10336
|
}
|
|
@@ -10470,24 +11165,24 @@ var DevServer = class _DevServer {
|
|
|
10470
11165
|
}
|
|
10471
11166
|
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
|
|
10472
11167
|
let referenceScripts = {};
|
|
10473
|
-
const builtinDir = this.providerLoader.builtinDir ||
|
|
10474
|
-
const refDir =
|
|
10475
|
-
if (
|
|
10476
|
-
const scriptsDir =
|
|
10477
|
-
if (
|
|
10478
|
-
const versions =
|
|
11168
|
+
const builtinDir = this.providerLoader.builtinDir || path12.resolve(__dirname, "../providers/_builtin");
|
|
11169
|
+
const refDir = path12.join(builtinDir, "ide", reference);
|
|
11170
|
+
if (fs9.existsSync(refDir)) {
|
|
11171
|
+
const scriptsDir = path12.join(refDir, "scripts");
|
|
11172
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
11173
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
10479
11174
|
try {
|
|
10480
|
-
return
|
|
11175
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
10481
11176
|
} catch {
|
|
10482
11177
|
return false;
|
|
10483
11178
|
}
|
|
10484
11179
|
}).sort().reverse();
|
|
10485
11180
|
if (versions.length > 0) {
|
|
10486
|
-
const latestDir =
|
|
10487
|
-
for (const file of
|
|
11181
|
+
const latestDir = path12.join(scriptsDir, versions[0]);
|
|
11182
|
+
for (const file of fs9.readdirSync(latestDir)) {
|
|
10488
11183
|
if (file.endsWith(".js")) {
|
|
10489
11184
|
try {
|
|
10490
|
-
referenceScripts[file] =
|
|
11185
|
+
referenceScripts[file] = fs9.readFileSync(path12.join(latestDir, file), "utf-8");
|
|
10491
11186
|
} catch {
|
|
10492
11187
|
}
|
|
10493
11188
|
}
|
|
@@ -10496,16 +11191,16 @@ var DevServer = class _DevServer {
|
|
|
10496
11191
|
}
|
|
10497
11192
|
}
|
|
10498
11193
|
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts);
|
|
10499
|
-
const tmpDir =
|
|
10500
|
-
if (!
|
|
10501
|
-
const promptFile =
|
|
10502
|
-
|
|
11194
|
+
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
11195
|
+
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
11196
|
+
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
11197
|
+
fs9.writeFileSync(promptFile, prompt, "utf-8");
|
|
10503
11198
|
this.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
10504
11199
|
const agentProvider = this.providerLoader.resolve(agent) || this.providerLoader.getMeta(agent);
|
|
10505
11200
|
const spawn3 = agentProvider?.spawn;
|
|
10506
11201
|
if (!spawn3?.command) {
|
|
10507
11202
|
try {
|
|
10508
|
-
|
|
11203
|
+
fs9.unlinkSync(promptFile);
|
|
10509
11204
|
} catch {
|
|
10510
11205
|
}
|
|
10511
11206
|
this.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -10606,7 +11301,7 @@ var DevServer = class _DevServer {
|
|
|
10606
11301
|
} catch {
|
|
10607
11302
|
}
|
|
10608
11303
|
try {
|
|
10609
|
-
|
|
11304
|
+
fs9.unlinkSync(promptFile);
|
|
10610
11305
|
} catch {
|
|
10611
11306
|
}
|
|
10612
11307
|
this.log(`Auto-implement (ACP) ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -10662,12 +11357,12 @@ var DevServer = class _DevServer {
|
|
|
10662
11357
|
} else {
|
|
10663
11358
|
args = [...baseArgs];
|
|
10664
11359
|
}
|
|
10665
|
-
const { execSync:
|
|
11360
|
+
const { execSync: execSync7 } = await import("child_process");
|
|
10666
11361
|
try {
|
|
10667
|
-
|
|
11362
|
+
execSync7(`which ${command}`, { stdio: "pipe" });
|
|
10668
11363
|
} catch {
|
|
10669
11364
|
try {
|
|
10670
|
-
|
|
11365
|
+
fs9.unlinkSync(promptFile);
|
|
10671
11366
|
} catch {
|
|
10672
11367
|
}
|
|
10673
11368
|
this.json(res, 400, { error: `Agent binary '${command}' not found on PATH. Install it first: ${agentProvider?.install || "check provider docs"}` });
|
|
@@ -10723,7 +11418,7 @@ var DevServer = class _DevServer {
|
|
|
10723
11418
|
} catch {
|
|
10724
11419
|
}
|
|
10725
11420
|
try {
|
|
10726
|
-
|
|
11421
|
+
fs9.unlinkSync(promptFile);
|
|
10727
11422
|
} catch {
|
|
10728
11423
|
}
|
|
10729
11424
|
this.log(`Auto-implement ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -10753,23 +11448,23 @@ var DevServer = class _DevServer {
|
|
|
10753
11448
|
lines.push("## Current Target Files");
|
|
10754
11449
|
lines.push("These are the files you need to EDIT. They contain TODO stubs \u2014 replace them with working implementations.");
|
|
10755
11450
|
lines.push("");
|
|
10756
|
-
const scriptsDir =
|
|
10757
|
-
if (
|
|
10758
|
-
const versions =
|
|
11451
|
+
const scriptsDir = path12.join(providerDir, "scripts");
|
|
11452
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
11453
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
10759
11454
|
try {
|
|
10760
|
-
return
|
|
11455
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
10761
11456
|
} catch {
|
|
10762
11457
|
return false;
|
|
10763
11458
|
}
|
|
10764
11459
|
}).sort().reverse();
|
|
10765
11460
|
if (versions.length > 0) {
|
|
10766
|
-
const vDir =
|
|
11461
|
+
const vDir = path12.join(scriptsDir, versions[0]);
|
|
10767
11462
|
lines.push(`Scripts version directory: \`${vDir}\``);
|
|
10768
11463
|
lines.push("");
|
|
10769
|
-
for (const file of
|
|
11464
|
+
for (const file of fs9.readdirSync(vDir)) {
|
|
10770
11465
|
if (file.endsWith(".js")) {
|
|
10771
11466
|
try {
|
|
10772
|
-
const content =
|
|
11467
|
+
const content = fs9.readFileSync(path12.join(vDir, file), "utf-8");
|
|
10773
11468
|
lines.push(`### \`${file}\``);
|
|
10774
11469
|
lines.push("```javascript");
|
|
10775
11470
|
lines.push(content);
|
|
@@ -10840,7 +11535,7 @@ var DevServer = class _DevServer {
|
|
|
10840
11535
|
lines.push("## Required Return Format");
|
|
10841
11536
|
lines.push("| Function | Return JSON |");
|
|
10842
11537
|
lines.push("|---|---|");
|
|
10843
|
-
lines.push("| readChat | `{ id, status, title, messages: [{role, content, index}], inputContent, activeModal }` |");
|
|
11538
|
+
lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal }` \u2014 optional `kind`: standard, thought, tool, terminal; optional `meta`: e.g. `{ label, isRunning }` for dashboard |");
|
|
10844
11539
|
lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
|
|
10845
11540
|
lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
|
|
10846
11541
|
lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
|
|
@@ -10964,14 +11659,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
10964
11659
|
res.end(JSON.stringify(data, null, 2));
|
|
10965
11660
|
}
|
|
10966
11661
|
async readBody(req) {
|
|
10967
|
-
return new Promise((
|
|
11662
|
+
return new Promise((resolve7) => {
|
|
10968
11663
|
let body = "";
|
|
10969
11664
|
req.on("data", (chunk) => body += chunk);
|
|
10970
11665
|
req.on("end", () => {
|
|
10971
11666
|
try {
|
|
10972
|
-
|
|
11667
|
+
resolve7(JSON.parse(body));
|
|
10973
11668
|
} catch {
|
|
10974
|
-
|
|
11669
|
+
resolve7({});
|
|
10975
11670
|
}
|
|
10976
11671
|
});
|
|
10977
11672
|
});
|
|
@@ -10979,7 +11674,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
10979
11674
|
};
|
|
10980
11675
|
|
|
10981
11676
|
// src/installer.ts
|
|
10982
|
-
var
|
|
11677
|
+
var import_child_process8 = require("child_process");
|
|
10983
11678
|
var EXTENSION_CATALOG = [
|
|
10984
11679
|
// AI Agent extensions
|
|
10985
11680
|
{
|
|
@@ -11056,7 +11751,7 @@ var EXTENSION_CATALOG = [
|
|
|
11056
11751
|
function isExtensionInstalled(ide, marketplaceId) {
|
|
11057
11752
|
if (!ide.cliCommand) return false;
|
|
11058
11753
|
try {
|
|
11059
|
-
const result = (0,
|
|
11754
|
+
const result = (0, import_child_process8.execSync)(`"${ide.cliCommand}" --list-extensions`, {
|
|
11060
11755
|
encoding: "utf-8",
|
|
11061
11756
|
timeout: 15e3,
|
|
11062
11757
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -11093,12 +11788,12 @@ async function installExtension(ide, extension) {
|
|
|
11093
11788
|
const res = await fetch(extension.vsixUrl);
|
|
11094
11789
|
if (res.ok) {
|
|
11095
11790
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
11096
|
-
const
|
|
11097
|
-
|
|
11098
|
-
return new Promise((
|
|
11791
|
+
const fs10 = await import("fs");
|
|
11792
|
+
fs10.writeFileSync(vsixPath, buffer);
|
|
11793
|
+
return new Promise((resolve7) => {
|
|
11099
11794
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
11100
|
-
(0,
|
|
11101
|
-
|
|
11795
|
+
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
11796
|
+
resolve7({
|
|
11102
11797
|
extensionId: extension.id,
|
|
11103
11798
|
marketplaceId: extension.marketplaceId,
|
|
11104
11799
|
success: !error,
|
|
@@ -11111,11 +11806,11 @@ async function installExtension(ide, extension) {
|
|
|
11111
11806
|
} catch (e) {
|
|
11112
11807
|
}
|
|
11113
11808
|
}
|
|
11114
|
-
return new Promise((
|
|
11809
|
+
return new Promise((resolve7) => {
|
|
11115
11810
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
11116
|
-
(0,
|
|
11811
|
+
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
11117
11812
|
if (error) {
|
|
11118
|
-
|
|
11813
|
+
resolve7({
|
|
11119
11814
|
extensionId: extension.id,
|
|
11120
11815
|
marketplaceId: extension.marketplaceId,
|
|
11121
11816
|
success: false,
|
|
@@ -11123,7 +11818,7 @@ async function installExtension(ide, extension) {
|
|
|
11123
11818
|
error: stderr || error.message
|
|
11124
11819
|
});
|
|
11125
11820
|
} else {
|
|
11126
|
-
|
|
11821
|
+
resolve7({
|
|
11127
11822
|
extensionId: extension.id,
|
|
11128
11823
|
marketplaceId: extension.marketplaceId,
|
|
11129
11824
|
success: true,
|
|
@@ -11150,7 +11845,7 @@ function launchIDE(ide, workspacePath) {
|
|
|
11150
11845
|
if (!ide.cliCommand) return false;
|
|
11151
11846
|
try {
|
|
11152
11847
|
const args = workspacePath ? `"${workspacePath}"` : "";
|
|
11153
|
-
(0,
|
|
11848
|
+
(0, import_child_process8.exec)(`"${ide.cliCommand}" ${args}`, { timeout: 1e4 });
|
|
11154
11849
|
return true;
|
|
11155
11850
|
} catch {
|
|
11156
11851
|
return false;
|
|
@@ -11315,9 +12010,12 @@ async function shutdownDaemonComponents(components) {
|
|
|
11315
12010
|
detectIDEs,
|
|
11316
12011
|
getAIExtensions,
|
|
11317
12012
|
getAvailableIdeIds,
|
|
12013
|
+
getHostMemorySnapshot,
|
|
11318
12014
|
getLogLevel,
|
|
11319
12015
|
getRecentCommands,
|
|
11320
12016
|
getRecentLogs,
|
|
12017
|
+
getWorkspaceActivity,
|
|
12018
|
+
getWorkspaceState,
|
|
11321
12019
|
initDaemonComponents,
|
|
11322
12020
|
installExtensions,
|
|
11323
12021
|
installGlobalInterceptor,
|