@adhdev/daemon-core 0.7.38 → 0.7.40
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/agent-stream/forward.d.ts +8 -0
- package/dist/agent-stream/index.d.ts +6 -0
- package/dist/agent-stream/manager.d.ts +59 -0
- package/dist/agent-stream/poller.d.ts +41 -0
- package/dist/agent-stream/provider-adapter.d.ts +29 -0
- package/dist/agent-stream/types.d.ts +62 -0
- package/dist/boot/daemon-lifecycle.d.ts +97 -0
- package/dist/cdp/devtools.d.ts +51 -0
- package/dist/cdp/initializer.d.ts +50 -0
- package/dist/cdp/manager.d.ts +145 -0
- package/dist/cdp/scanner.d.ts +58 -0
- package/dist/cdp/setup.d.ts +58 -0
- package/dist/cli-adapter-types.d.ts +25 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +229 -0
- package/dist/cli-adapters/pty-transport.d.ts +43 -0
- package/dist/cli-adapters/session-host-transport.d.ts +19 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +12 -0
- package/dist/cli-adapters/terminal-backends/types.d.ts +14 -0
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +13 -0
- package/dist/cli-adapters/terminal-screen.d.ts +27 -0
- package/dist/commands/cdp-commands.d.ts +15 -0
- package/dist/commands/chat-commands.d.ts +15 -0
- package/dist/commands/cli-manager.d.ts +82 -0
- package/dist/commands/handler.d.ts +101 -0
- package/dist/commands/router.d.ts +69 -0
- package/dist/commands/stream-commands.d.ts +13 -0
- package/dist/commands/workspace-commands.d.ts +11 -0
- package/dist/config/chat-history.d.ts +60 -0
- package/dist/config/config.d.ts +103 -0
- package/dist/config/recent-activity.d.ts +27 -0
- package/dist/config/workspaces.d.ts +82 -0
- package/dist/daemon/dev-auto-implement.d.ts +26 -0
- package/dist/daemon/dev-cdp-handlers.d.ts +22 -0
- package/dist/daemon/dev-cli-debug.d.ts +24 -0
- package/dist/daemon/dev-server-types.d.ts +43 -0
- package/dist/daemon/dev-server.d.ts +133 -0
- package/dist/daemon/scaffold-template.d.ts +32 -0
- package/dist/daemon-core.d.ts +36 -0
- package/dist/detection/cli-detector.d.ts +27 -0
- package/dist/detection/ide-detector.d.ts +34 -0
- package/dist/index.d.ts +72 -2499
- package/dist/index.js +673 -879
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +680 -884
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +50 -0
- package/dist/ipc-protocol.d.ts +111 -0
- package/dist/launch.d.ts +46 -0
- package/dist/logging/command-log.d.ts +31 -0
- package/dist/logging/logger.d.ts +87 -0
- package/dist/providers/acp-provider-instance.d.ts +101 -0
- package/dist/providers/cli-provider-instance.d.ts +43 -0
- package/dist/providers/contracts.d.ts +483 -0
- package/dist/providers/extension-provider-instance.d.ts +44 -0
- package/dist/providers/ide-provider-instance.d.ts +61 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/provider-instance-manager.d.ts +84 -0
- package/dist/providers/provider-instance.d.ts +148 -0
- package/dist/providers/provider-loader.d.ts +270 -0
- package/dist/providers/status-monitor.d.ts +48 -0
- package/dist/providers/version-archive.d.ts +52 -0
- package/dist/session-host/runtime-support.d.ts +8 -0
- package/dist/sessions/registry.d.ts +24 -0
- package/dist/shared-types-extra.d.ts +29 -0
- package/dist/shared-types.d.ts +205 -0
- package/dist/status/builders.d.ts +33 -0
- package/dist/status/normalize.d.ts +14 -1
- package/dist/status/reporter.d.ts +69 -0
- package/dist/status/snapshot.d.ts +51 -0
- package/dist/system/host-memory.d.ts +19 -0
- package/dist/types.d.ts +123 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -2
- package/src/commands/cli-manager.ts +1 -26
- package/src/commands/handler.ts +0 -31
- package/src/commands/router.ts +27 -34
- package/src/commands/stream-commands.ts +2 -4
- package/src/commands/workspace-commands.ts +9 -23
- package/src/config/config.ts +7 -81
- package/src/config/recent-activity.ts +24 -12
- package/src/config/workspaces.ts +0 -24
- package/src/index.ts +16 -15
- package/src/providers/provider-loader.ts +13 -5
- package/src/shared-types-extra.ts +34 -0
- package/src/shared-types.d.ts +4 -6
- package/src/shared-types.ts +17 -38
- package/src/status/builders.ts +12 -0
- package/src/status/reporter.ts +2 -1
- package/src/status/snapshot.ts +70 -87
- package/src/types.ts +3 -8
- package/dist/index.d.mts +0 -2504
- package/dist/normalize-DVI4Lo5I.d.mts +0 -947
- package/dist/normalize-DVI4Lo5I.d.ts +0 -947
- package/dist/status/normalize.d.mts +0 -1
- package/src/config/workspace-activity.ts +0 -65
package/dist/index.mjs
CHANGED
|
@@ -25,201 +25,9 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
25
25
|
};
|
|
26
26
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
27
|
|
|
28
|
-
// src/config/workspaces.ts
|
|
29
|
-
import * as fs from "fs";
|
|
30
|
-
import * as os from "os";
|
|
31
|
-
import * as path from "path";
|
|
32
|
-
import { randomUUID } from "crypto";
|
|
33
|
-
function expandPath(p) {
|
|
34
|
-
const t = (p || "").trim();
|
|
35
|
-
if (!t) return "";
|
|
36
|
-
if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
37
|
-
return path.resolve(t);
|
|
38
|
-
}
|
|
39
|
-
function validateWorkspacePath(absPath) {
|
|
40
|
-
try {
|
|
41
|
-
if (!absPath) return { ok: false, error: "Path required" };
|
|
42
|
-
if (!fs.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
|
|
43
|
-
const st = fs.statSync(absPath);
|
|
44
|
-
if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
|
|
45
|
-
return { ok: true };
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return { ok: false, error: e?.message || "Invalid path" };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function defaultWorkspaceLabel(absPath) {
|
|
51
|
-
const base = path.basename(absPath) || absPath;
|
|
52
|
-
return base;
|
|
53
|
-
}
|
|
54
|
-
function migrateWorkspacesFromRecent(config) {
|
|
55
|
-
if (!config.workspaces) config.workspaces = [];
|
|
56
|
-
if (config.workspaces.length > 0) return config;
|
|
57
|
-
const recent = config.recentCliWorkspaces || [];
|
|
58
|
-
const now = Date.now();
|
|
59
|
-
for (const raw of recent) {
|
|
60
|
-
const abs = expandPath(raw);
|
|
61
|
-
if (!abs || validateWorkspacePath(abs).ok !== true) continue;
|
|
62
|
-
if (config.workspaces.some((w) => path.resolve(w.path) === abs)) continue;
|
|
63
|
-
config.workspaces.push({
|
|
64
|
-
id: randomUUID(),
|
|
65
|
-
path: abs,
|
|
66
|
-
label: defaultWorkspaceLabel(abs),
|
|
67
|
-
addedAt: now
|
|
68
|
-
});
|
|
69
|
-
if (config.workspaces.length >= MAX_WORKSPACES) break;
|
|
70
|
-
}
|
|
71
|
-
return config;
|
|
72
|
-
}
|
|
73
|
-
function getDefaultWorkspacePath(config) {
|
|
74
|
-
const id = config.defaultWorkspaceId;
|
|
75
|
-
if (!id) return null;
|
|
76
|
-
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
77
|
-
if (!w) return null;
|
|
78
|
-
const abs = expandPath(w.path);
|
|
79
|
-
if (validateWorkspacePath(abs).ok !== true) return null;
|
|
80
|
-
return abs;
|
|
81
|
-
}
|
|
82
|
-
function getWorkspaceState(config) {
|
|
83
|
-
const workspaces = [...config.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
|
|
84
|
-
const defaultWorkspacePath = getDefaultWorkspacePath(config);
|
|
85
|
-
return {
|
|
86
|
-
workspaces,
|
|
87
|
-
defaultWorkspaceId: config.defaultWorkspaceId ?? null,
|
|
88
|
-
defaultWorkspacePath
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function resolveLaunchDirectory(args, config) {
|
|
92
|
-
const a = args || {};
|
|
93
|
-
if (a.dir != null && String(a.dir).trim()) {
|
|
94
|
-
const abs = expandPath(String(a.dir).trim());
|
|
95
|
-
if (abs && validateWorkspacePath(abs).ok === true) {
|
|
96
|
-
return { ok: true, path: abs, source: "dir" };
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
ok: false,
|
|
100
|
-
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
101
|
-
message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
if (a.workspaceId) {
|
|
105
|
-
const w = (config.workspaces || []).find((x) => x.id === a.workspaceId);
|
|
106
|
-
if (w) {
|
|
107
|
-
const abs = expandPath(w.path);
|
|
108
|
-
if (validateWorkspacePath(abs).ok === true) {
|
|
109
|
-
return { ok: true, path: abs, source: "workspaceId" };
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
ok: false,
|
|
114
|
-
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
115
|
-
message: "Saved workspace not found or path is no longer valid"
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
if (a.useDefaultWorkspace === true) {
|
|
119
|
-
const d = getDefaultWorkspacePath(config);
|
|
120
|
-
if (d) return { ok: true, path: d, source: "defaultWorkspace" };
|
|
121
|
-
return {
|
|
122
|
-
ok: false,
|
|
123
|
-
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
124
|
-
message: "No default workspace is set"
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
if (a.useHome === true) {
|
|
128
|
-
return { ok: true, path: os.homedir(), source: "home" };
|
|
129
|
-
}
|
|
130
|
-
return {
|
|
131
|
-
ok: false,
|
|
132
|
-
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
133
|
-
message: "Choose a directory, saved workspace, default workspace, or home before launching."
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
function resolveIdeWorkspaceFromArgs(args, config) {
|
|
137
|
-
const ar = args || {};
|
|
138
|
-
if (ar.workspace) {
|
|
139
|
-
const abs = expandPath(ar.workspace);
|
|
140
|
-
if (abs && validateWorkspacePath(abs).ok === true) return abs;
|
|
141
|
-
}
|
|
142
|
-
if (ar.workspaceId) {
|
|
143
|
-
const w = (config.workspaces || []).find((x) => x.id === ar.workspaceId);
|
|
144
|
-
if (w) {
|
|
145
|
-
const abs = expandPath(w.path);
|
|
146
|
-
if (validateWorkspacePath(abs).ok === true) return abs;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (ar.useDefaultWorkspace === true) {
|
|
150
|
-
return getDefaultWorkspacePath(config) || void 0;
|
|
151
|
-
}
|
|
152
|
-
return void 0;
|
|
153
|
-
}
|
|
154
|
-
function resolveIdeLaunchWorkspace(args, config) {
|
|
155
|
-
const direct = resolveIdeWorkspaceFromArgs(args, config);
|
|
156
|
-
if (direct) return direct;
|
|
157
|
-
if (args?.useDefaultWorkspace === false) return void 0;
|
|
158
|
-
return getDefaultWorkspacePath(config) || void 0;
|
|
159
|
-
}
|
|
160
|
-
function findWorkspaceByPath(config, rawPath) {
|
|
161
|
-
const abs = path.resolve(expandPath(rawPath));
|
|
162
|
-
if (!abs) return void 0;
|
|
163
|
-
return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
|
|
164
|
-
}
|
|
165
|
-
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
166
|
-
const abs = expandPath(rawPath);
|
|
167
|
-
const createIfMissing = options?.createIfMissing === true;
|
|
168
|
-
if (!abs) return { error: "Path required" };
|
|
169
|
-
if (!fs.existsSync(abs) && createIfMissing) {
|
|
170
|
-
try {
|
|
171
|
-
fs.mkdirSync(abs, { recursive: true });
|
|
172
|
-
} catch (e) {
|
|
173
|
-
return { error: e?.message || "Could not create directory" };
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
const v = validateWorkspacePath(abs);
|
|
177
|
-
if (!v.ok) return { error: v.error };
|
|
178
|
-
const list = [...config.workspaces || []];
|
|
179
|
-
if (list.some((w) => path.resolve(w.path) === abs)) {
|
|
180
|
-
return { error: "Workspace already in list" };
|
|
181
|
-
}
|
|
182
|
-
if (list.length >= MAX_WORKSPACES) {
|
|
183
|
-
return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
|
|
184
|
-
}
|
|
185
|
-
const entry = {
|
|
186
|
-
id: randomUUID(),
|
|
187
|
-
path: abs,
|
|
188
|
-
label: (label || "").trim() || defaultWorkspaceLabel(abs),
|
|
189
|
-
addedAt: Date.now()
|
|
190
|
-
};
|
|
191
|
-
list.push(entry);
|
|
192
|
-
return { config: { ...config, workspaces: list }, entry };
|
|
193
|
-
}
|
|
194
|
-
function removeWorkspaceEntry(config, id) {
|
|
195
|
-
const list = (config.workspaces || []).filter((w) => w.id !== id);
|
|
196
|
-
if (list.length === (config.workspaces || []).length) return { error: "Workspace not found" };
|
|
197
|
-
let defaultWorkspaceId = config.defaultWorkspaceId;
|
|
198
|
-
if (defaultWorkspaceId === id) defaultWorkspaceId = null;
|
|
199
|
-
return { config: { ...config, workspaces: list, defaultWorkspaceId } };
|
|
200
|
-
}
|
|
201
|
-
function setDefaultWorkspaceId(config, id) {
|
|
202
|
-
if (id === null) {
|
|
203
|
-
return { config: { ...config, defaultWorkspaceId: null } };
|
|
204
|
-
}
|
|
205
|
-
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
206
|
-
if (!w) return { error: "Workspace not found" };
|
|
207
|
-
const abs = expandPath(w.path);
|
|
208
|
-
if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
|
|
209
|
-
return { config: { ...config, defaultWorkspaceId: id } };
|
|
210
|
-
}
|
|
211
|
-
var MAX_WORKSPACES;
|
|
212
|
-
var init_workspaces = __esm({
|
|
213
|
-
"src/config/workspaces.ts"() {
|
|
214
|
-
"use strict";
|
|
215
|
-
MAX_WORKSPACES = 50;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
28
|
// src/config/config.ts
|
|
220
29
|
var config_exports = {};
|
|
221
30
|
__export(config_exports, {
|
|
222
|
-
addCliHistory: () => addCliHistory,
|
|
223
31
|
generateConnectionToken: () => generateConnectionToken,
|
|
224
32
|
generateMachineId: () => generateMachineId,
|
|
225
33
|
getConfigDir: () => getConfigDir,
|
|
@@ -231,12 +39,12 @@ __export(config_exports, {
|
|
|
231
39
|
saveConfig: () => saveConfig,
|
|
232
40
|
updateConfig: () => updateConfig
|
|
233
41
|
});
|
|
234
|
-
import { homedir
|
|
235
|
-
import { join
|
|
236
|
-
import { existsSync
|
|
237
|
-
import { randomUUID
|
|
42
|
+
import { homedir } from "os";
|
|
43
|
+
import { join } from "path";
|
|
44
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
45
|
+
import { randomUUID } from "crypto";
|
|
238
46
|
function generateMachineId() {
|
|
239
|
-
return `${MACHINE_ID_PREFIX}${
|
|
47
|
+
return `${MACHINE_ID_PREFIX}${randomUUID().replace(/-/g, "")}`;
|
|
240
48
|
}
|
|
241
49
|
function isStableMachineId(machineId) {
|
|
242
50
|
return typeof machineId === "string" && machineId.startsWith(MACHINE_ID_PREFIX);
|
|
@@ -256,18 +64,18 @@ function ensureMachineId(config) {
|
|
|
256
64
|
};
|
|
257
65
|
}
|
|
258
66
|
function getConfigDir() {
|
|
259
|
-
const dir =
|
|
260
|
-
if (!
|
|
261
|
-
|
|
67
|
+
const dir = join(homedir(), ".adhdev");
|
|
68
|
+
if (!existsSync(dir)) {
|
|
69
|
+
mkdirSync(dir, { recursive: true });
|
|
262
70
|
}
|
|
263
71
|
return dir;
|
|
264
72
|
}
|
|
265
73
|
function getConfigPath() {
|
|
266
|
-
return
|
|
74
|
+
return join(getConfigDir(), "config.json");
|
|
267
75
|
}
|
|
268
76
|
function loadConfig() {
|
|
269
77
|
const configPath = getConfigPath();
|
|
270
|
-
if (!
|
|
78
|
+
if (!existsSync(configPath)) {
|
|
271
79
|
const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
|
|
272
80
|
try {
|
|
273
81
|
saveConfig(initialized.config);
|
|
@@ -283,15 +91,9 @@ function loadConfig() {
|
|
|
283
91
|
merged.defaultWorkspaceId = merged.activeWorkspaceId;
|
|
284
92
|
}
|
|
285
93
|
delete merged.activeWorkspaceId;
|
|
286
|
-
const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
|
|
287
94
|
const ensured = ensureMachineId(merged);
|
|
288
95
|
const normalized = ensured.config;
|
|
289
|
-
|
|
290
|
-
let configChanged = ensured.changed;
|
|
291
|
-
if (!hadStoredWorkspaces && (normalized.workspaces?.length || 0) > 0) {
|
|
292
|
-
configChanged = true;
|
|
293
|
-
}
|
|
294
|
-
if (configChanged) {
|
|
96
|
+
if (ensured.changed) {
|
|
295
97
|
try {
|
|
296
98
|
saveConfig(normalized);
|
|
297
99
|
} catch {
|
|
@@ -306,8 +108,8 @@ function loadConfig() {
|
|
|
306
108
|
function saveConfig(config) {
|
|
307
109
|
const configPath = getConfigPath();
|
|
308
110
|
const dir = getConfigDir();
|
|
309
|
-
if (!
|
|
310
|
-
|
|
111
|
+
if (!existsSync(dir)) {
|
|
112
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
311
113
|
}
|
|
312
114
|
writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
313
115
|
try {
|
|
@@ -346,39 +148,10 @@ function generateConnectionToken() {
|
|
|
346
148
|
}
|
|
347
149
|
return token;
|
|
348
150
|
}
|
|
349
|
-
function addCliHistory(entry) {
|
|
350
|
-
const config = loadConfig();
|
|
351
|
-
const history = config.cliHistory || [];
|
|
352
|
-
const argsKey = (entry.cliArgs || []).join(" ");
|
|
353
|
-
const category = entry.category || "cli";
|
|
354
|
-
const workspaceKey = entry.workspace || "";
|
|
355
|
-
const modelKey = entry.model || "";
|
|
356
|
-
const filtered = history.filter((h) => {
|
|
357
|
-
const hArgsKey = (h.cliArgs || []).join(" ");
|
|
358
|
-
return !((h.category || "cli") === category && h.cliType === entry.cliType && h.dir === entry.dir && hArgsKey === argsKey && (h.workspace || "") === workspaceKey && (h.model || "") === modelKey);
|
|
359
|
-
});
|
|
360
|
-
filtered.unshift({
|
|
361
|
-
...entry,
|
|
362
|
-
category,
|
|
363
|
-
timestamp: Date.now(),
|
|
364
|
-
label: entry.label || (() => {
|
|
365
|
-
const base = `${entry.cliType} \xB7 ${entry.dir.split("/").filter(Boolean).pop() || "root"}`;
|
|
366
|
-
const suffix = [];
|
|
367
|
-
if (entry.workspace && entry.workspace !== entry.dir) suffix.push(entry.workspace.split("/").filter(Boolean).pop() || entry.workspace);
|
|
368
|
-
if (entry.model) suffix.push(`model=${entry.model}`);
|
|
369
|
-
if (argsKey) suffix.push(argsKey);
|
|
370
|
-
if (entry.newWindow) suffix.push("new window");
|
|
371
|
-
return suffix.length > 0 ? `${base} (${suffix.join(" \xB7 ")})` : base;
|
|
372
|
-
})()
|
|
373
|
-
});
|
|
374
|
-
config.cliHistory = filtered.slice(0, 20);
|
|
375
|
-
saveConfig(config);
|
|
376
|
-
}
|
|
377
151
|
var DEFAULT_CONFIG, MACHINE_ID_PREFIX;
|
|
378
152
|
var init_config = __esm({
|
|
379
153
|
"src/config/config.ts"() {
|
|
380
154
|
"use strict";
|
|
381
|
-
init_workspaces();
|
|
382
155
|
DEFAULT_CONFIG = {
|
|
383
156
|
serverUrl: "https://api.adhf.dev",
|
|
384
157
|
apiToken: null,
|
|
@@ -394,17 +167,15 @@ var init_config = __esm({
|
|
|
394
167
|
setupDate: null,
|
|
395
168
|
configuredCLIs: [],
|
|
396
169
|
enabledIdes: [],
|
|
397
|
-
recentCliWorkspaces: [],
|
|
398
170
|
workspaces: [],
|
|
399
171
|
defaultWorkspaceId: null,
|
|
400
|
-
recentWorkspaceActivity: [],
|
|
401
172
|
recentActivity: [],
|
|
402
|
-
|
|
173
|
+
sessionReads: {},
|
|
174
|
+
sessionReadMarkers: {},
|
|
403
175
|
machineNickname: null,
|
|
404
176
|
machineId: void 0,
|
|
405
177
|
machineSecret: null,
|
|
406
178
|
registeredMachineId: void 0,
|
|
407
|
-
cliHistory: [],
|
|
408
179
|
providerSettings: {},
|
|
409
180
|
ideSettings: {},
|
|
410
181
|
disableUpstream: false
|
|
@@ -415,7 +186,7 @@ var init_config = __esm({
|
|
|
415
186
|
|
|
416
187
|
// src/logging/logger.ts
|
|
417
188
|
import * as fs2 from "fs";
|
|
418
|
-
import * as
|
|
189
|
+
import * as path3 from "path";
|
|
419
190
|
import * as os4 from "os";
|
|
420
191
|
function setLogLevel(level) {
|
|
421
192
|
currentLevel = level;
|
|
@@ -431,7 +202,7 @@ function checkDateRotation() {
|
|
|
431
202
|
const today = getDateStr();
|
|
432
203
|
if (today !== currentDate) {
|
|
433
204
|
currentDate = today;
|
|
434
|
-
currentLogFile =
|
|
205
|
+
currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
435
206
|
cleanOldLogs();
|
|
436
207
|
}
|
|
437
208
|
}
|
|
@@ -445,7 +216,7 @@ function cleanOldLogs() {
|
|
|
445
216
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
446
217
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
447
218
|
try {
|
|
448
|
-
fs2.unlinkSync(
|
|
219
|
+
fs2.unlinkSync(path3.join(LOG_DIR, file));
|
|
449
220
|
} catch {
|
|
450
221
|
}
|
|
451
222
|
}
|
|
@@ -569,7 +340,7 @@ var init_logger = __esm({
|
|
|
569
340
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
570
341
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
571
342
|
currentLevel = "info";
|
|
572
|
-
LOG_DIR = process.platform === "win32" ?
|
|
343
|
+
LOG_DIR = process.platform === "win32" ? path3.join(process.env.LOCALAPPDATA || process.env.APPDATA || path3.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path3.join(os4.homedir(), "Library", "Logs", "adhdev") : path3.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
573
344
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
574
345
|
MAX_LOG_DAYS = 7;
|
|
575
346
|
try {
|
|
@@ -577,16 +348,16 @@ var init_logger = __esm({
|
|
|
577
348
|
} catch {
|
|
578
349
|
}
|
|
579
350
|
currentDate = getDateStr();
|
|
580
|
-
currentLogFile =
|
|
351
|
+
currentLogFile = path3.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
581
352
|
cleanOldLogs();
|
|
582
353
|
try {
|
|
583
|
-
const oldLog =
|
|
354
|
+
const oldLog = path3.join(LOG_DIR, "daemon.log");
|
|
584
355
|
if (fs2.existsSync(oldLog)) {
|
|
585
356
|
const stat = fs2.statSync(oldLog);
|
|
586
357
|
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
587
|
-
fs2.renameSync(oldLog,
|
|
358
|
+
fs2.renameSync(oldLog, path3.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
588
359
|
}
|
|
589
|
-
const oldLogBackup =
|
|
360
|
+
const oldLogBackup = path3.join(LOG_DIR, "daemon.log.old");
|
|
590
361
|
if (fs2.existsSync(oldLogBackup)) {
|
|
591
362
|
fs2.unlinkSync(oldLogBackup);
|
|
592
363
|
}
|
|
@@ -618,7 +389,7 @@ var init_logger = __esm({
|
|
|
618
389
|
}
|
|
619
390
|
};
|
|
620
391
|
interceptorInstalled = false;
|
|
621
|
-
LOG_PATH =
|
|
392
|
+
LOG_PATH = path3.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
622
393
|
}
|
|
623
394
|
});
|
|
624
395
|
|
|
@@ -928,7 +699,7 @@ __export(provider_cli_adapter_exports, {
|
|
|
928
699
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
929
700
|
});
|
|
930
701
|
import * as os12 from "os";
|
|
931
|
-
import * as
|
|
702
|
+
import * as path9 from "path";
|
|
932
703
|
import { execSync as execSync4 } from "child_process";
|
|
933
704
|
function stripAnsi(str) {
|
|
934
705
|
return str.replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "").replace(/ +/g, " ");
|
|
@@ -949,7 +720,7 @@ function findBinary(name) {
|
|
|
949
720
|
}
|
|
950
721
|
}
|
|
951
722
|
function isScriptBinary(binaryPath) {
|
|
952
|
-
if (!
|
|
723
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
953
724
|
try {
|
|
954
725
|
const fs12 = __require("fs");
|
|
955
726
|
const resolved = fs12.realpathSync(binaryPath);
|
|
@@ -965,7 +736,7 @@ function isScriptBinary(binaryPath) {
|
|
|
965
736
|
}
|
|
966
737
|
}
|
|
967
738
|
function looksLikeMachOOrElf(filePath) {
|
|
968
|
-
if (!
|
|
739
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
969
740
|
try {
|
|
970
741
|
const fs12 = __require("fs");
|
|
971
742
|
const resolved = fs12.realpathSync(filePath);
|
|
@@ -1091,9 +862,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1091
862
|
if (os12.platform() !== "win32") {
|
|
1092
863
|
try {
|
|
1093
864
|
const fs12 = __require("fs");
|
|
1094
|
-
const ptyDir =
|
|
865
|
+
const ptyDir = path9.resolve(path9.dirname(__require.resolve("node-pty")), "..");
|
|
1095
866
|
const platformArch = `${os12.platform()}-${os12.arch()}`;
|
|
1096
|
-
const helper =
|
|
867
|
+
const helper = path9.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
1097
868
|
if (fs12.existsSync(helper)) {
|
|
1098
869
|
const stat = fs12.statSync(helper);
|
|
1099
870
|
if (!(stat.mode & 73)) {
|
|
@@ -1282,7 +1053,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1282
1053
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1283
1054
|
let shellCmd;
|
|
1284
1055
|
let shellArgs;
|
|
1285
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1056
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1286
1057
|
const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
|
|
1287
1058
|
if (useShell) {
|
|
1288
1059
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -1707,7 +1478,7 @@ ${data.message || ""}`.trim();
|
|
|
1707
1478
|
if (this.startupParseGate) {
|
|
1708
1479
|
const deadline = Date.now() + 1e4;
|
|
1709
1480
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
1710
|
-
await new Promise((
|
|
1481
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1711
1482
|
}
|
|
1712
1483
|
}
|
|
1713
1484
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
@@ -1875,17 +1646,17 @@ ${data.message || ""}`.trim();
|
|
|
1875
1646
|
}
|
|
1876
1647
|
}
|
|
1877
1648
|
waitForStopped(timeoutMs) {
|
|
1878
|
-
return new Promise((
|
|
1649
|
+
return new Promise((resolve9) => {
|
|
1879
1650
|
const startedAt = Date.now();
|
|
1880
1651
|
const timer = setInterval(() => {
|
|
1881
1652
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
1882
1653
|
clearInterval(timer);
|
|
1883
|
-
|
|
1654
|
+
resolve9(true);
|
|
1884
1655
|
return;
|
|
1885
1656
|
}
|
|
1886
1657
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
1887
1658
|
clearInterval(timer);
|
|
1888
|
-
|
|
1659
|
+
resolve9(false);
|
|
1889
1660
|
}
|
|
1890
1661
|
}, 100);
|
|
1891
1662
|
});
|
|
@@ -2077,58 +1848,182 @@ ${data.message || ""}`.trim();
|
|
|
2077
1848
|
|
|
2078
1849
|
// src/index.ts
|
|
2079
1850
|
init_config();
|
|
2080
|
-
init_workspaces();
|
|
2081
1851
|
|
|
2082
|
-
// src/config/
|
|
2083
|
-
|
|
2084
|
-
import * as
|
|
2085
|
-
|
|
2086
|
-
|
|
1852
|
+
// src/config/workspaces.ts
|
|
1853
|
+
import * as fs from "fs";
|
|
1854
|
+
import * as os from "os";
|
|
1855
|
+
import * as path from "path";
|
|
1856
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1857
|
+
var MAX_WORKSPACES = 50;
|
|
1858
|
+
function expandPath(p) {
|
|
1859
|
+
const t = (p || "").trim();
|
|
1860
|
+
if (!t) return "";
|
|
1861
|
+
if (t.startsWith("~")) return path.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
1862
|
+
return path.resolve(t);
|
|
1863
|
+
}
|
|
1864
|
+
function validateWorkspacePath(absPath) {
|
|
2087
1865
|
try {
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
1866
|
+
if (!absPath) return { ok: false, error: "Path required" };
|
|
1867
|
+
if (!fs.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
|
|
1868
|
+
const st = fs.statSync(absPath);
|
|
1869
|
+
if (!st.isDirectory()) return { ok: false, error: "Not a directory" };
|
|
1870
|
+
return { ok: true };
|
|
1871
|
+
} catch (e) {
|
|
1872
|
+
return { ok: false, error: e?.message || "Invalid path" };
|
|
2091
1873
|
}
|
|
2092
1874
|
}
|
|
2093
|
-
function
|
|
2094
|
-
const
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
1875
|
+
function defaultWorkspaceLabel(absPath) {
|
|
1876
|
+
const base = path.basename(absPath) || absPath;
|
|
1877
|
+
return base;
|
|
1878
|
+
}
|
|
1879
|
+
function getDefaultWorkspacePath(config) {
|
|
1880
|
+
const id = config.defaultWorkspaceId;
|
|
1881
|
+
if (!id) return null;
|
|
1882
|
+
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
1883
|
+
if (!w) return null;
|
|
1884
|
+
const abs = expandPath(w.path);
|
|
1885
|
+
if (validateWorkspacePath(abs).ok !== true) return null;
|
|
1886
|
+
return abs;
|
|
1887
|
+
}
|
|
1888
|
+
function getWorkspaceState(config) {
|
|
1889
|
+
const workspaces = [...config.workspaces || []].sort((a, b) => b.addedAt - a.addedAt);
|
|
1890
|
+
const defaultWorkspacePath = getDefaultWorkspacePath(config);
|
|
1891
|
+
return {
|
|
1892
|
+
workspaces,
|
|
1893
|
+
defaultWorkspaceId: config.defaultWorkspaceId ?? null,
|
|
1894
|
+
defaultWorkspacePath
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
function resolveLaunchDirectory(args, config) {
|
|
1898
|
+
const a = args || {};
|
|
1899
|
+
if (a.dir != null && String(a.dir).trim()) {
|
|
1900
|
+
const abs = expandPath(String(a.dir).trim());
|
|
1901
|
+
if (abs && validateWorkspacePath(abs).ok === true) {
|
|
1902
|
+
return { ok: true, path: abs, source: "dir" };
|
|
1903
|
+
}
|
|
1904
|
+
return {
|
|
1905
|
+
ok: false,
|
|
1906
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
1907
|
+
message: abs ? "Directory path is not valid or does not exist" : "Invalid directory path"
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
if (a.workspaceId) {
|
|
1911
|
+
const w = (config.workspaces || []).find((x) => x.id === a.workspaceId);
|
|
1912
|
+
if (w) {
|
|
1913
|
+
const abs = expandPath(w.path);
|
|
1914
|
+
if (validateWorkspacePath(abs).ok === true) {
|
|
1915
|
+
return { ok: true, path: abs, source: "workspaceId" };
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
return {
|
|
1919
|
+
ok: false,
|
|
1920
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
1921
|
+
message: "Saved workspace not found or path is no longer valid"
|
|
1922
|
+
};
|
|
1923
|
+
}
|
|
1924
|
+
if (a.useDefaultWorkspace === true) {
|
|
1925
|
+
const d = getDefaultWorkspacePath(config);
|
|
1926
|
+
if (d) return { ok: true, path: d, source: "defaultWorkspace" };
|
|
1927
|
+
return {
|
|
1928
|
+
ok: false,
|
|
1929
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
1930
|
+
message: "No default workspace is set"
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
if (a.useHome === true) {
|
|
1934
|
+
return { ok: true, path: os.homedir(), source: "home" };
|
|
1935
|
+
}
|
|
1936
|
+
return {
|
|
1937
|
+
ok: false,
|
|
1938
|
+
code: "WORKSPACE_LAUNCH_CONTEXT_REQUIRED",
|
|
1939
|
+
message: "Choose a directory, saved workspace, default workspace, or home before launching."
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
function resolveIdeWorkspaceFromArgs(args, config) {
|
|
1943
|
+
const ar = args || {};
|
|
1944
|
+
if (ar.workspace) {
|
|
1945
|
+
const abs = expandPath(ar.workspace);
|
|
1946
|
+
if (abs && validateWorkspacePath(abs).ok === true) return abs;
|
|
1947
|
+
}
|
|
1948
|
+
if (ar.workspaceId) {
|
|
1949
|
+
const w = (config.workspaces || []).find((x) => x.id === ar.workspaceId);
|
|
1950
|
+
if (w) {
|
|
1951
|
+
const abs = expandPath(w.path);
|
|
1952
|
+
if (validateWorkspacePath(abs).ok === true) return abs;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
if (ar.useDefaultWorkspace === true) {
|
|
1956
|
+
return getDefaultWorkspacePath(config) || void 0;
|
|
1957
|
+
}
|
|
1958
|
+
return void 0;
|
|
1959
|
+
}
|
|
1960
|
+
function resolveIdeLaunchWorkspace(args, config) {
|
|
1961
|
+
const direct = resolveIdeWorkspaceFromArgs(args, config);
|
|
1962
|
+
if (direct) return direct;
|
|
1963
|
+
if (args?.useDefaultWorkspace === false) return void 0;
|
|
1964
|
+
return getDefaultWorkspacePath(config) || void 0;
|
|
1965
|
+
}
|
|
1966
|
+
function findWorkspaceByPath(config, rawPath) {
|
|
1967
|
+
const abs = path.resolve(expandPath(rawPath));
|
|
1968
|
+
if (!abs) return void 0;
|
|
1969
|
+
return (config.workspaces || []).find((w) => path.resolve(expandPath(w.path)) === abs);
|
|
1970
|
+
}
|
|
1971
|
+
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
1972
|
+
const abs = expandPath(rawPath);
|
|
1973
|
+
const createIfMissing = options?.createIfMissing === true;
|
|
1974
|
+
if (!abs) return { error: "Path required" };
|
|
1975
|
+
if (!fs.existsSync(abs) && createIfMissing) {
|
|
1976
|
+
try {
|
|
1977
|
+
fs.mkdirSync(abs, { recursive: true });
|
|
1978
|
+
} catch (e) {
|
|
1979
|
+
return { error: e?.message || "Could not create directory" };
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
const v = validateWorkspacePath(abs);
|
|
1983
|
+
if (!v.ok) return { error: v.error };
|
|
1984
|
+
const list = [...config.workspaces || []];
|
|
1985
|
+
if (list.some((w) => path.resolve(w.path) === abs)) {
|
|
1986
|
+
return { error: "Workspace already in list" };
|
|
1987
|
+
}
|
|
1988
|
+
if (list.length >= MAX_WORKSPACES) {
|
|
1989
|
+
return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
|
|
1990
|
+
}
|
|
2098
1991
|
const entry = {
|
|
1992
|
+
id: randomUUID2(),
|
|
2099
1993
|
path: abs,
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
agentType: meta?.agentType
|
|
1994
|
+
label: (label || "").trim() || defaultWorkspaceLabel(abs),
|
|
1995
|
+
addedAt: Date.now()
|
|
2103
1996
|
};
|
|
2104
|
-
|
|
2105
|
-
return { ...config,
|
|
1997
|
+
list.push(entry);
|
|
1998
|
+
return { config: { ...config, workspaces: list }, entry };
|
|
2106
1999
|
}
|
|
2107
|
-
function
|
|
2108
|
-
const list =
|
|
2109
|
-
list.
|
|
2110
|
-
|
|
2000
|
+
function removeWorkspaceEntry(config, id) {
|
|
2001
|
+
const list = (config.workspaces || []).filter((w) => w.id !== id);
|
|
2002
|
+
if (list.length === (config.workspaces || []).length) return { error: "Workspace not found" };
|
|
2003
|
+
let defaultWorkspaceId = config.defaultWorkspaceId;
|
|
2004
|
+
if (defaultWorkspaceId === id) defaultWorkspaceId = null;
|
|
2005
|
+
return { config: { ...config, workspaces: list, defaultWorkspaceId } };
|
|
2111
2006
|
}
|
|
2112
|
-
function
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
};
|
|
2007
|
+
function setDefaultWorkspaceId(config, id) {
|
|
2008
|
+
if (id === null) {
|
|
2009
|
+
return { config: { ...config, defaultWorkspaceId: null } };
|
|
2010
|
+
}
|
|
2011
|
+
const w = (config.workspaces || []).find((x) => x.id === id);
|
|
2012
|
+
if (!w) return { error: "Workspace not found" };
|
|
2013
|
+
const abs = expandPath(w.path);
|
|
2014
|
+
if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
|
|
2015
|
+
return { config: { ...config, defaultWorkspaceId: id } };
|
|
2120
2016
|
}
|
|
2121
2017
|
|
|
2122
2018
|
// src/config/recent-activity.ts
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
var MAX_ACTIVITY2 = 30;
|
|
2019
|
+
import * as path2 from "path";
|
|
2020
|
+
var MAX_ACTIVITY = 30;
|
|
2126
2021
|
function normalizeWorkspace(workspace) {
|
|
2127
2022
|
if (!workspace) return "";
|
|
2128
2023
|
try {
|
|
2129
|
-
return
|
|
2024
|
+
return path2.resolve(expandPath(workspace));
|
|
2130
2025
|
} catch {
|
|
2131
|
-
return
|
|
2026
|
+
return path2.resolve(workspace);
|
|
2132
2027
|
}
|
|
2133
2028
|
}
|
|
2134
2029
|
function buildRecentActivityKey(entry) {
|
|
@@ -2144,24 +2039,33 @@ function appendRecentActivity(config, entry) {
|
|
|
2144
2039
|
const filtered = (config.recentActivity || []).filter((item) => item.id !== nextEntry.id);
|
|
2145
2040
|
return {
|
|
2146
2041
|
...config,
|
|
2147
|
-
recentActivity: [nextEntry, ...filtered].slice(0,
|
|
2042
|
+
recentActivity: [nextEntry, ...filtered].slice(0, MAX_ACTIVITY)
|
|
2148
2043
|
};
|
|
2149
2044
|
}
|
|
2150
2045
|
function getRecentActivity(config, limit = 20) {
|
|
2151
2046
|
return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
|
|
2152
2047
|
}
|
|
2153
|
-
function
|
|
2154
|
-
return config.
|
|
2048
|
+
function getSessionSeenAt(config, sessionId) {
|
|
2049
|
+
return config.sessionReads?.[sessionId] || 0;
|
|
2050
|
+
}
|
|
2051
|
+
function getSessionSeenMarker(config, sessionId) {
|
|
2052
|
+
return config.sessionReadMarkers?.[sessionId] || "";
|
|
2155
2053
|
}
|
|
2156
|
-
function
|
|
2157
|
-
const prev = config.
|
|
2158
|
-
const nextSeenAt = Math.max(prev[
|
|
2054
|
+
function markSessionSeen(config, sessionId, seenAt = Date.now(), completionMarker) {
|
|
2055
|
+
const prev = config.sessionReads || {};
|
|
2056
|
+
const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
|
|
2057
|
+
const prevMarkers = config.sessionReadMarkers || {};
|
|
2058
|
+
const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
|
|
2159
2059
|
return {
|
|
2160
2060
|
...config,
|
|
2161
|
-
|
|
2061
|
+
sessionReads: {
|
|
2162
2062
|
...prev,
|
|
2163
|
-
[
|
|
2164
|
-
}
|
|
2063
|
+
[sessionId]: nextSeenAt
|
|
2064
|
+
},
|
|
2065
|
+
sessionReadMarkers: nextMarker ? {
|
|
2066
|
+
...prevMarkers,
|
|
2067
|
+
[sessionId]: nextMarker
|
|
2068
|
+
} : prevMarkers
|
|
2165
2069
|
};
|
|
2166
2070
|
}
|
|
2167
2071
|
|
|
@@ -2272,15 +2176,15 @@ function parseVersion(raw) {
|
|
|
2272
2176
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
2273
2177
|
}
|
|
2274
2178
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
2275
|
-
return new Promise((
|
|
2179
|
+
return new Promise((resolve9) => {
|
|
2276
2180
|
const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
2277
2181
|
if (err || !stdout?.trim()) {
|
|
2278
|
-
|
|
2182
|
+
resolve9(null);
|
|
2279
2183
|
} else {
|
|
2280
|
-
|
|
2184
|
+
resolve9(stdout.trim());
|
|
2281
2185
|
}
|
|
2282
2186
|
});
|
|
2283
|
-
child.on("error", () =>
|
|
2187
|
+
child.on("error", () => resolve9(null));
|
|
2284
2188
|
});
|
|
2285
2189
|
}
|
|
2286
2190
|
async function detectCLIs(providerLoader) {
|
|
@@ -2447,7 +2351,7 @@ var DaemonCdpManager = class {
|
|
|
2447
2351
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
2448
2352
|
*/
|
|
2449
2353
|
static listAllTargets(port) {
|
|
2450
|
-
return new Promise((
|
|
2354
|
+
return new Promise((resolve9) => {
|
|
2451
2355
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2452
2356
|
let data = "";
|
|
2453
2357
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2463,16 +2367,16 @@ var DaemonCdpManager = class {
|
|
|
2463
2367
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
2464
2368
|
);
|
|
2465
2369
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
2466
|
-
|
|
2370
|
+
resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
2467
2371
|
} catch {
|
|
2468
|
-
|
|
2372
|
+
resolve9([]);
|
|
2469
2373
|
}
|
|
2470
2374
|
});
|
|
2471
2375
|
});
|
|
2472
|
-
req.on("error", () =>
|
|
2376
|
+
req.on("error", () => resolve9([]));
|
|
2473
2377
|
req.setTimeout(2e3, () => {
|
|
2474
2378
|
req.destroy();
|
|
2475
|
-
|
|
2379
|
+
resolve9([]);
|
|
2476
2380
|
});
|
|
2477
2381
|
});
|
|
2478
2382
|
}
|
|
@@ -2512,7 +2416,7 @@ var DaemonCdpManager = class {
|
|
|
2512
2416
|
}
|
|
2513
2417
|
}
|
|
2514
2418
|
findTargetOnPort(port) {
|
|
2515
|
-
return new Promise((
|
|
2419
|
+
return new Promise((resolve9) => {
|
|
2516
2420
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2517
2421
|
let data = "";
|
|
2518
2422
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2523,7 +2427,7 @@ var DaemonCdpManager = class {
|
|
|
2523
2427
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
2524
2428
|
);
|
|
2525
2429
|
if (pages.length === 0) {
|
|
2526
|
-
|
|
2430
|
+
resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
2527
2431
|
return;
|
|
2528
2432
|
}
|
|
2529
2433
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -2533,24 +2437,24 @@ var DaemonCdpManager = class {
|
|
|
2533
2437
|
const specific = list.find((t) => t.id === this._targetId);
|
|
2534
2438
|
if (specific) {
|
|
2535
2439
|
this._pageTitle = specific.title || "";
|
|
2536
|
-
|
|
2440
|
+
resolve9(specific);
|
|
2537
2441
|
} else {
|
|
2538
2442
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
2539
|
-
|
|
2443
|
+
resolve9(null);
|
|
2540
2444
|
}
|
|
2541
2445
|
return;
|
|
2542
2446
|
}
|
|
2543
2447
|
this._pageTitle = list[0]?.title || "";
|
|
2544
|
-
|
|
2448
|
+
resolve9(list[0]);
|
|
2545
2449
|
} catch {
|
|
2546
|
-
|
|
2450
|
+
resolve9(null);
|
|
2547
2451
|
}
|
|
2548
2452
|
});
|
|
2549
2453
|
});
|
|
2550
|
-
req.on("error", () =>
|
|
2454
|
+
req.on("error", () => resolve9(null));
|
|
2551
2455
|
req.setTimeout(2e3, () => {
|
|
2552
2456
|
req.destroy();
|
|
2553
|
-
|
|
2457
|
+
resolve9(null);
|
|
2554
2458
|
});
|
|
2555
2459
|
});
|
|
2556
2460
|
}
|
|
@@ -2561,7 +2465,7 @@ var DaemonCdpManager = class {
|
|
|
2561
2465
|
this.extensionProviders = providers;
|
|
2562
2466
|
}
|
|
2563
2467
|
connectToTarget(wsUrl) {
|
|
2564
|
-
return new Promise((
|
|
2468
|
+
return new Promise((resolve9) => {
|
|
2565
2469
|
this.ws = new WebSocket(wsUrl);
|
|
2566
2470
|
this.ws.on("open", async () => {
|
|
2567
2471
|
this._connected = true;
|
|
@@ -2571,17 +2475,17 @@ var DaemonCdpManager = class {
|
|
|
2571
2475
|
}
|
|
2572
2476
|
this.connectBrowserWs().catch(() => {
|
|
2573
2477
|
});
|
|
2574
|
-
|
|
2478
|
+
resolve9(true);
|
|
2575
2479
|
});
|
|
2576
2480
|
this.ws.on("message", (data) => {
|
|
2577
2481
|
try {
|
|
2578
2482
|
const msg = JSON.parse(data.toString());
|
|
2579
2483
|
if (msg.id && this.pending.has(msg.id)) {
|
|
2580
|
-
const { resolve:
|
|
2484
|
+
const { resolve: resolve10, reject } = this.pending.get(msg.id);
|
|
2581
2485
|
this.pending.delete(msg.id);
|
|
2582
2486
|
this.failureCount = 0;
|
|
2583
2487
|
if (msg.error) reject(new Error(msg.error.message));
|
|
2584
|
-
else
|
|
2488
|
+
else resolve10(msg.result);
|
|
2585
2489
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
2586
2490
|
this.contexts.add(msg.params.context.id);
|
|
2587
2491
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -2604,7 +2508,7 @@ var DaemonCdpManager = class {
|
|
|
2604
2508
|
this.ws.on("error", (err) => {
|
|
2605
2509
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
2606
2510
|
this._connected = false;
|
|
2607
|
-
|
|
2511
|
+
resolve9(false);
|
|
2608
2512
|
});
|
|
2609
2513
|
});
|
|
2610
2514
|
}
|
|
@@ -2618,7 +2522,7 @@ var DaemonCdpManager = class {
|
|
|
2618
2522
|
return;
|
|
2619
2523
|
}
|
|
2620
2524
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
2621
|
-
await new Promise((
|
|
2525
|
+
await new Promise((resolve9, reject) => {
|
|
2622
2526
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
2623
2527
|
this.browserWs.on("open", async () => {
|
|
2624
2528
|
this._browserConnected = true;
|
|
@@ -2628,16 +2532,16 @@ var DaemonCdpManager = class {
|
|
|
2628
2532
|
} catch (e) {
|
|
2629
2533
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
2630
2534
|
}
|
|
2631
|
-
|
|
2535
|
+
resolve9();
|
|
2632
2536
|
});
|
|
2633
2537
|
this.browserWs.on("message", (data) => {
|
|
2634
2538
|
try {
|
|
2635
2539
|
const msg = JSON.parse(data.toString());
|
|
2636
2540
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
2637
|
-
const { resolve:
|
|
2541
|
+
const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
|
|
2638
2542
|
this.browserPending.delete(msg.id);
|
|
2639
2543
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
2640
|
-
else
|
|
2544
|
+
else resolve10(msg.result);
|
|
2641
2545
|
}
|
|
2642
2546
|
} catch {
|
|
2643
2547
|
}
|
|
@@ -2657,31 +2561,31 @@ var DaemonCdpManager = class {
|
|
|
2657
2561
|
}
|
|
2658
2562
|
}
|
|
2659
2563
|
getBrowserWsUrl() {
|
|
2660
|
-
return new Promise((
|
|
2564
|
+
return new Promise((resolve9) => {
|
|
2661
2565
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
2662
2566
|
let data = "";
|
|
2663
2567
|
res.on("data", (chunk) => data += chunk.toString());
|
|
2664
2568
|
res.on("end", () => {
|
|
2665
2569
|
try {
|
|
2666
2570
|
const info = JSON.parse(data);
|
|
2667
|
-
|
|
2571
|
+
resolve9(info.webSocketDebuggerUrl || null);
|
|
2668
2572
|
} catch {
|
|
2669
|
-
|
|
2573
|
+
resolve9(null);
|
|
2670
2574
|
}
|
|
2671
2575
|
});
|
|
2672
2576
|
});
|
|
2673
|
-
req.on("error", () =>
|
|
2577
|
+
req.on("error", () => resolve9(null));
|
|
2674
2578
|
req.setTimeout(3e3, () => {
|
|
2675
2579
|
req.destroy();
|
|
2676
|
-
|
|
2580
|
+
resolve9(null);
|
|
2677
2581
|
});
|
|
2678
2582
|
});
|
|
2679
2583
|
}
|
|
2680
2584
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
2681
|
-
return new Promise((
|
|
2585
|
+
return new Promise((resolve9, reject) => {
|
|
2682
2586
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
2683
2587
|
const id = this.browserMsgId++;
|
|
2684
|
-
this.browserPending.set(id, { resolve:
|
|
2588
|
+
this.browserPending.set(id, { resolve: resolve9, reject });
|
|
2685
2589
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
2686
2590
|
setTimeout(() => {
|
|
2687
2591
|
if (this.browserPending.has(id)) {
|
|
@@ -2721,11 +2625,11 @@ var DaemonCdpManager = class {
|
|
|
2721
2625
|
}
|
|
2722
2626
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
2723
2627
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
2724
|
-
return new Promise((
|
|
2628
|
+
return new Promise((resolve9, reject) => {
|
|
2725
2629
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
2726
2630
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
2727
2631
|
const id = this.msgId++;
|
|
2728
|
-
this.pending.set(id, { resolve:
|
|
2632
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
2729
2633
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
2730
2634
|
setTimeout(() => {
|
|
2731
2635
|
if (this.pending.has(id)) {
|
|
@@ -2974,7 +2878,7 @@ var DaemonCdpManager = class {
|
|
|
2974
2878
|
const browserWs = this.browserWs;
|
|
2975
2879
|
let msgId = this.browserMsgId;
|
|
2976
2880
|
const sendWs = (method, params = {}, sessionId) => {
|
|
2977
|
-
return new Promise((
|
|
2881
|
+
return new Promise((resolve9, reject) => {
|
|
2978
2882
|
const mid = msgId++;
|
|
2979
2883
|
this.browserMsgId = msgId;
|
|
2980
2884
|
const handler = (raw) => {
|
|
@@ -2983,7 +2887,7 @@ var DaemonCdpManager = class {
|
|
|
2983
2887
|
if (msg.id === mid) {
|
|
2984
2888
|
browserWs.removeListener("message", handler);
|
|
2985
2889
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
2986
|
-
else
|
|
2890
|
+
else resolve9(msg.result);
|
|
2987
2891
|
}
|
|
2988
2892
|
} catch {
|
|
2989
2893
|
}
|
|
@@ -3174,14 +3078,14 @@ var DaemonCdpManager = class {
|
|
|
3174
3078
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
3175
3079
|
throw new Error("CDP not connected");
|
|
3176
3080
|
}
|
|
3177
|
-
return new Promise((
|
|
3081
|
+
return new Promise((resolve9, reject) => {
|
|
3178
3082
|
const id = getNextId();
|
|
3179
3083
|
pendingMap.set(id, {
|
|
3180
3084
|
resolve: (result) => {
|
|
3181
3085
|
if (result?.result?.subtype === "error") {
|
|
3182
3086
|
reject(new Error(result.result.description));
|
|
3183
3087
|
} else {
|
|
3184
|
-
|
|
3088
|
+
resolve9(result?.result?.value);
|
|
3185
3089
|
}
|
|
3186
3090
|
},
|
|
3187
3091
|
reject
|
|
@@ -3213,10 +3117,10 @@ var DaemonCdpManager = class {
|
|
|
3213
3117
|
throw new Error("CDP not connected");
|
|
3214
3118
|
}
|
|
3215
3119
|
const sendViaSession = (method, params = {}) => {
|
|
3216
|
-
return new Promise((
|
|
3120
|
+
return new Promise((resolve9, reject) => {
|
|
3217
3121
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
3218
3122
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
3219
|
-
pendingMap.set(id, { resolve:
|
|
3123
|
+
pendingMap.set(id, { resolve: resolve9, reject });
|
|
3220
3124
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
3221
3125
|
setTimeout(() => {
|
|
3222
3126
|
if (pendingMap.has(id)) {
|
|
@@ -3923,9 +3827,9 @@ var ExtensionProviderInstance = class {
|
|
|
3923
3827
|
|
|
3924
3828
|
// src/config/chat-history.ts
|
|
3925
3829
|
import * as fs3 from "fs";
|
|
3926
|
-
import * as
|
|
3830
|
+
import * as path4 from "path";
|
|
3927
3831
|
import * as os5 from "os";
|
|
3928
|
-
var HISTORY_DIR =
|
|
3832
|
+
var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
|
|
3929
3833
|
var RETAIN_DAYS = 30;
|
|
3930
3834
|
var ChatHistoryWriter = class {
|
|
3931
3835
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -3968,11 +3872,11 @@ var ChatHistoryWriter = class {
|
|
|
3968
3872
|
});
|
|
3969
3873
|
}
|
|
3970
3874
|
if (newMessages.length === 0) return;
|
|
3971
|
-
const dir =
|
|
3875
|
+
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
3972
3876
|
fs3.mkdirSync(dir, { recursive: true });
|
|
3973
3877
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3974
3878
|
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
3975
|
-
const filePath =
|
|
3879
|
+
const filePath = path4.join(dir, `${filePrefix}${date}.jsonl`);
|
|
3976
3880
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
3977
3881
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
3978
3882
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
@@ -4016,11 +3920,11 @@ ${next}`;
|
|
|
4016
3920
|
this.lastSeenTerminal.set(dedupKey, next);
|
|
4017
3921
|
return;
|
|
4018
3922
|
}
|
|
4019
|
-
const dir =
|
|
3923
|
+
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4020
3924
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4021
3925
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4022
3926
|
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
4023
|
-
const filePath =
|
|
3927
|
+
const filePath = path4.join(dir, `${filePrefix}${date}.terminal.log`);
|
|
4024
3928
|
fs3.appendFileSync(filePath, delta, "utf-8");
|
|
4025
3929
|
this.lastSeenTerminal.set(dedupKey, next);
|
|
4026
3930
|
if (!this.rotated) {
|
|
@@ -4044,10 +3948,10 @@ ${next}`;
|
|
|
4044
3948
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
4045
3949
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
4046
3950
|
for (const dir of agentDirs) {
|
|
4047
|
-
const dirPath =
|
|
3951
|
+
const dirPath = path4.join(HISTORY_DIR, dir.name);
|
|
4048
3952
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
4049
3953
|
for (const file of files) {
|
|
4050
|
-
const filePath =
|
|
3954
|
+
const filePath = path4.join(dirPath, file);
|
|
4051
3955
|
const stat = fs3.statSync(filePath);
|
|
4052
3956
|
if (stat.mtimeMs < cutoff) {
|
|
4053
3957
|
fs3.unlinkSync(filePath);
|
|
@@ -4065,7 +3969,7 @@ ${next}`;
|
|
|
4065
3969
|
function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
|
|
4066
3970
|
try {
|
|
4067
3971
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4068
|
-
const dir =
|
|
3972
|
+
const dir = path4.join(HISTORY_DIR, sanitized);
|
|
4069
3973
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
4070
3974
|
const sanitizedInstance = instanceId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4071
3975
|
const files = fs3.readdirSync(dir).filter((f) => {
|
|
@@ -4079,7 +3983,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, instanceId) {
|
|
|
4079
3983
|
const needed = offset + limit + 1;
|
|
4080
3984
|
for (const file of files) {
|
|
4081
3985
|
if (allMessages.length >= needed) break;
|
|
4082
|
-
const filePath =
|
|
3986
|
+
const filePath = path4.join(dir, file);
|
|
4083
3987
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
4084
3988
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
4085
3989
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -5147,11 +5051,18 @@ function buildSessionEntries(allStates, cdpManagers) {
|
|
|
5147
5051
|
for (const state of acpStates) {
|
|
5148
5052
|
sessions.push(buildAcpSession(state));
|
|
5149
5053
|
}
|
|
5054
|
+
const extensionParentIds = new Set(
|
|
5055
|
+
sessions.filter((session) => session.transport === "cdp-webview" && !!session.parentId).map((session) => session.parentId)
|
|
5056
|
+
);
|
|
5057
|
+
for (const session of sessions) {
|
|
5058
|
+
if (session.transport === "cdp-page" && extensionParentIds.has(session.id)) {
|
|
5059
|
+
session.surfaceHidden = true;
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5150
5062
|
return sessions;
|
|
5151
5063
|
}
|
|
5152
5064
|
|
|
5153
5065
|
// src/commands/handler.ts
|
|
5154
|
-
init_config();
|
|
5155
5066
|
init_logger();
|
|
5156
5067
|
|
|
5157
5068
|
// src/commands/chat-commands.ts
|
|
@@ -5976,7 +5887,7 @@ async function handleResolveAction(h, args) {
|
|
|
5976
5887
|
|
|
5977
5888
|
// src/commands/cdp-commands.ts
|
|
5978
5889
|
import * as fs4 from "fs";
|
|
5979
|
-
import * as
|
|
5890
|
+
import * as path5 from "path";
|
|
5980
5891
|
import * as os6 from "os";
|
|
5981
5892
|
var KEY_TO_VK = {
|
|
5982
5893
|
Backspace: 8,
|
|
@@ -6207,11 +6118,11 @@ function resolveSafePath(requestedPath) {
|
|
|
6207
6118
|
const home = os6.homedir();
|
|
6208
6119
|
let resolved;
|
|
6209
6120
|
if (requestedPath.startsWith("~")) {
|
|
6210
|
-
resolved =
|
|
6211
|
-
} else if (
|
|
6121
|
+
resolved = path5.join(home, requestedPath.slice(1));
|
|
6122
|
+
} else if (path5.isAbsolute(requestedPath)) {
|
|
6212
6123
|
resolved = requestedPath;
|
|
6213
6124
|
} else {
|
|
6214
|
-
resolved =
|
|
6125
|
+
resolved = path5.resolve(requestedPath);
|
|
6215
6126
|
}
|
|
6216
6127
|
return resolved;
|
|
6217
6128
|
}
|
|
@@ -6227,7 +6138,7 @@ async function handleFileRead(h, args) {
|
|
|
6227
6138
|
async function handleFileWrite(h, args) {
|
|
6228
6139
|
try {
|
|
6229
6140
|
const filePath = resolveSafePath(args?.path);
|
|
6230
|
-
fs4.mkdirSync(
|
|
6141
|
+
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
6231
6142
|
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
6232
6143
|
return { success: true, path: filePath };
|
|
6233
6144
|
} catch (e) {
|
|
@@ -6241,7 +6152,7 @@ async function handleFileList(h, args) {
|
|
|
6241
6152
|
const files = entries.map((e) => ({
|
|
6242
6153
|
name: e.name,
|
|
6243
6154
|
type: e.isDirectory() ? "directory" : "file",
|
|
6244
|
-
size: e.isFile() ? fs4.statSync(
|
|
6155
|
+
size: e.isFile() ? fs4.statSync(path5.join(dirPath, e.name)).size : void 0
|
|
6245
6156
|
}));
|
|
6246
6157
|
return { success: true, files, path: dirPath };
|
|
6247
6158
|
} catch (e) {
|
|
@@ -6253,7 +6164,6 @@ async function handleFileListBrowse(h, args) {
|
|
|
6253
6164
|
}
|
|
6254
6165
|
|
|
6255
6166
|
// src/commands/stream-commands.ts
|
|
6256
|
-
init_config();
|
|
6257
6167
|
init_logger();
|
|
6258
6168
|
async function handleFocusSession(h, args) {
|
|
6259
6169
|
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
@@ -6407,13 +6317,12 @@ function handleGetIdeExtensions(h, args) {
|
|
|
6407
6317
|
const loader = h.ctx.providerLoader;
|
|
6408
6318
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
6409
6319
|
const allExtProviders = loader.getByCategory?.("extension") || [];
|
|
6410
|
-
const config = loadConfig();
|
|
6411
6320
|
if (ideType) {
|
|
6412
6321
|
const extensions = allExtProviders.map((p) => ({
|
|
6413
6322
|
type: p.type,
|
|
6414
6323
|
name: p.name,
|
|
6415
6324
|
extensionId: p.extensionId,
|
|
6416
|
-
enabled:
|
|
6325
|
+
enabled: loader.getIdeExtensionEnabledState?.(ideType, p.type) === true
|
|
6417
6326
|
}));
|
|
6418
6327
|
return { success: true, ideType, extensions };
|
|
6419
6328
|
}
|
|
@@ -6424,7 +6333,7 @@ function handleGetIdeExtensions(h, args) {
|
|
|
6424
6333
|
type: p.type,
|
|
6425
6334
|
name: p.name,
|
|
6426
6335
|
extensionId: p.extensionId,
|
|
6427
|
-
enabled:
|
|
6336
|
+
enabled: loader.getIdeExtensionEnabledState?.(ide, p.type) === true
|
|
6428
6337
|
}));
|
|
6429
6338
|
}
|
|
6430
6339
|
return { success: true, ideExtensions: result };
|
|
@@ -6447,7 +6356,6 @@ function handleSetIdeExtension(h, args) {
|
|
|
6447
6356
|
|
|
6448
6357
|
// src/commands/workspace-commands.ts
|
|
6449
6358
|
init_config();
|
|
6450
|
-
init_workspaces();
|
|
6451
6359
|
function handleWorkspaceList() {
|
|
6452
6360
|
const config = loadConfig();
|
|
6453
6361
|
const state = getWorkspaceState(config);
|
|
@@ -6455,9 +6363,7 @@ function handleWorkspaceList() {
|
|
|
6455
6363
|
success: true,
|
|
6456
6364
|
workspaces: state.workspaces,
|
|
6457
6365
|
defaultWorkspaceId: state.defaultWorkspaceId,
|
|
6458
|
-
defaultWorkspacePath: state.defaultWorkspacePath
|
|
6459
|
-
legacyRecentPaths: config.recentCliWorkspaces || [],
|
|
6460
|
-
activity: getWorkspaceActivity(config, 25)
|
|
6366
|
+
defaultWorkspacePath: state.defaultWorkspacePath
|
|
6461
6367
|
};
|
|
6462
6368
|
}
|
|
6463
6369
|
function handleWorkspaceAdd(args) {
|
|
@@ -6468,10 +6374,9 @@ function handleWorkspaceAdd(args) {
|
|
|
6468
6374
|
const config = loadConfig();
|
|
6469
6375
|
const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
|
|
6470
6376
|
if ("error" in result) return { success: false, error: result.error };
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
6377
|
+
saveConfig(result.config);
|
|
6378
|
+
const state = getWorkspaceState(result.config);
|
|
6379
|
+
return { success: true, entry: result.entry, ...state };
|
|
6475
6380
|
}
|
|
6476
6381
|
function handleWorkspaceRemove(args) {
|
|
6477
6382
|
const id = (args?.id || "").trim();
|
|
@@ -6480,13 +6385,9 @@ function handleWorkspaceRemove(args) {
|
|
|
6480
6385
|
const removed = (config.workspaces || []).find((w) => w.id === id);
|
|
6481
6386
|
const result = removeWorkspaceEntry(config, id);
|
|
6482
6387
|
if ("error" in result) return { success: false, error: result.error };
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
}
|
|
6487
|
-
saveConfig(cfg);
|
|
6488
|
-
const state = getWorkspaceState(cfg);
|
|
6489
|
-
return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
|
|
6388
|
+
saveConfig(result.config);
|
|
6389
|
+
const state = getWorkspaceState(result.config);
|
|
6390
|
+
return { success: true, removedId: id, ...state };
|
|
6490
6391
|
}
|
|
6491
6392
|
function handleWorkspaceSetDefault(args) {
|
|
6492
6393
|
const clear = args?.clear === true || args?.id === null || args?.id === "";
|
|
@@ -6498,8 +6399,7 @@ function handleWorkspaceSetDefault(args) {
|
|
|
6498
6399
|
const state2 = getWorkspaceState(result2.config);
|
|
6499
6400
|
return {
|
|
6500
6401
|
success: true,
|
|
6501
|
-
...state2
|
|
6502
|
-
activity: getWorkspaceActivity(result2.config, 25)
|
|
6402
|
+
...state2
|
|
6503
6403
|
};
|
|
6504
6404
|
}
|
|
6505
6405
|
const pathArg = args?.path != null && String(args.path).trim() ? String(args.path).trim() : "";
|
|
@@ -6523,18 +6423,12 @@ function handleWorkspaceSetDefault(args) {
|
|
|
6523
6423
|
}
|
|
6524
6424
|
const result = setDefaultWorkspaceId(config, nextId);
|
|
6525
6425
|
if ("error" in result) return { success: false, error: result.error };
|
|
6526
|
-
|
|
6527
|
-
const
|
|
6528
|
-
|
|
6529
|
-
out = appendWorkspaceActivity(out, ap, { kind: "default" });
|
|
6530
|
-
}
|
|
6531
|
-
saveConfig(out);
|
|
6532
|
-
const state = getWorkspaceState(out);
|
|
6533
|
-
return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
|
|
6426
|
+
saveConfig(result.config);
|
|
6427
|
+
const state = getWorkspaceState(result.config);
|
|
6428
|
+
return { success: true, ...state };
|
|
6534
6429
|
}
|
|
6535
6430
|
|
|
6536
6431
|
// src/commands/handler.ts
|
|
6537
|
-
init_workspaces();
|
|
6538
6432
|
var COMMAND_DEBUG_LEVELS = /* @__PURE__ */ new Set([
|
|
6539
6433
|
"pty_input",
|
|
6540
6434
|
"pty_resize",
|
|
@@ -6861,22 +6755,7 @@ var DaemonCommandHandler = class {
|
|
|
6861
6755
|
return handleFileList(this, args);
|
|
6862
6756
|
case "file_list_browse":
|
|
6863
6757
|
return handleFileListBrowse(this, args);
|
|
6864
|
-
// ─── VSCode API commands (not available) ────
|
|
6865
|
-
case "vscode_command_exec":
|
|
6866
|
-
case "execute_vscode_command": {
|
|
6867
|
-
const resolvedCmd = args?.commandId || args?.command;
|
|
6868
|
-
if (resolvedCmd === "adhdev.captureCdpScreenshot") {
|
|
6869
|
-
return handleScreenshot(this, args);
|
|
6870
|
-
}
|
|
6871
|
-
return { success: false, error: `VSCode command not available: ${resolvedCmd || cmd}` };
|
|
6872
|
-
}
|
|
6873
6758
|
// ─── Workspace cmds ──────────────
|
|
6874
|
-
case "get_recent_workspaces":
|
|
6875
|
-
return this.handleGetRecentWorkspaces(args);
|
|
6876
|
-
case "get_cli_history": {
|
|
6877
|
-
const config = loadConfig();
|
|
6878
|
-
return { success: true, history: config.cliHistory || [] };
|
|
6879
|
-
}
|
|
6880
6759
|
case "workspace_list":
|
|
6881
6760
|
return handleWorkspaceList();
|
|
6882
6761
|
case "workspace_add":
|
|
@@ -6884,7 +6763,6 @@ var DaemonCommandHandler = class {
|
|
|
6884
6763
|
case "workspace_remove":
|
|
6885
6764
|
return handleWorkspaceRemove(args);
|
|
6886
6765
|
case "workspace_set_default":
|
|
6887
|
-
case "workspace_set_active":
|
|
6888
6766
|
return handleWorkspaceSetDefault(args);
|
|
6889
6767
|
// ─── Script manage ───────────────────
|
|
6890
6768
|
case "refresh_scripts":
|
|
@@ -6930,19 +6808,6 @@ var DaemonCommandHandler = class {
|
|
|
6930
6808
|
}
|
|
6931
6809
|
}
|
|
6932
6810
|
// ─── Misc (kept in handler — too small to extract) ───────
|
|
6933
|
-
async handleGetRecentWorkspaces(_args) {
|
|
6934
|
-
const config = loadConfig();
|
|
6935
|
-
const cliRecent = config.recentCliWorkspaces || [];
|
|
6936
|
-
const ws = getWorkspaceState(config);
|
|
6937
|
-
return {
|
|
6938
|
-
success: true,
|
|
6939
|
-
result: cliRecent,
|
|
6940
|
-
workspaces: ws.workspaces,
|
|
6941
|
-
defaultWorkspaceId: ws.defaultWorkspaceId,
|
|
6942
|
-
defaultWorkspacePath: ws.defaultWorkspacePath,
|
|
6943
|
-
activity: getWorkspaceActivity(config, 25)
|
|
6944
|
-
};
|
|
6945
|
-
}
|
|
6946
6811
|
async handleRefreshScripts(_args) {
|
|
6947
6812
|
if (this._ctx.providerLoader) {
|
|
6948
6813
|
await this._ctx.providerLoader.fetchLatest().catch(() => {
|
|
@@ -6960,7 +6825,7 @@ var DaemonCommandHandler = class {
|
|
|
6960
6825
|
try {
|
|
6961
6826
|
const http3 = await import("http");
|
|
6962
6827
|
const postData = JSON.stringify(body);
|
|
6963
|
-
const result = await new Promise((
|
|
6828
|
+
const result = await new Promise((resolve9, reject) => {
|
|
6964
6829
|
const req = http3.request({
|
|
6965
6830
|
hostname: "127.0.0.1",
|
|
6966
6831
|
port: 19280,
|
|
@@ -6972,9 +6837,9 @@ var DaemonCommandHandler = class {
|
|
|
6972
6837
|
res.on("data", (chunk) => data += chunk);
|
|
6973
6838
|
res.on("end", () => {
|
|
6974
6839
|
try {
|
|
6975
|
-
|
|
6840
|
+
resolve9(JSON.parse(data));
|
|
6976
6841
|
} catch {
|
|
6977
|
-
|
|
6842
|
+
resolve9({ raw: data });
|
|
6978
6843
|
}
|
|
6979
6844
|
});
|
|
6980
6845
|
});
|
|
@@ -6992,15 +6857,15 @@ var DaemonCommandHandler = class {
|
|
|
6992
6857
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
6993
6858
|
try {
|
|
6994
6859
|
const http3 = await import("http");
|
|
6995
|
-
const result = await new Promise((
|
|
6860
|
+
const result = await new Promise((resolve9, reject) => {
|
|
6996
6861
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
6997
6862
|
let data = "";
|
|
6998
6863
|
res.on("data", (chunk) => data += chunk);
|
|
6999
6864
|
res.on("end", () => {
|
|
7000
6865
|
try {
|
|
7001
|
-
|
|
6866
|
+
resolve9(JSON.parse(data));
|
|
7002
6867
|
} catch {
|
|
7003
|
-
|
|
6868
|
+
resolve9({ raw: data });
|
|
7004
6869
|
}
|
|
7005
6870
|
});
|
|
7006
6871
|
}).on("error", reject);
|
|
@@ -7014,7 +6879,7 @@ var DaemonCommandHandler = class {
|
|
|
7014
6879
|
try {
|
|
7015
6880
|
const http3 = await import("http");
|
|
7016
6881
|
const postData = JSON.stringify(args || {});
|
|
7017
|
-
const result = await new Promise((
|
|
6882
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7018
6883
|
const req = http3.request({
|
|
7019
6884
|
hostname: "127.0.0.1",
|
|
7020
6885
|
port: 19280,
|
|
@@ -7026,9 +6891,9 @@ var DaemonCommandHandler = class {
|
|
|
7026
6891
|
res.on("data", (chunk) => data += chunk);
|
|
7027
6892
|
res.on("end", () => {
|
|
7028
6893
|
try {
|
|
7029
|
-
|
|
6894
|
+
resolve9(JSON.parse(data));
|
|
7030
6895
|
} catch {
|
|
7031
|
-
|
|
6896
|
+
resolve9({ raw: data });
|
|
7032
6897
|
}
|
|
7033
6898
|
});
|
|
7034
6899
|
});
|
|
@@ -7047,11 +6912,11 @@ var DaemonCommandHandler = class {
|
|
|
7047
6912
|
import { execSync as execSync3, spawn } from "child_process";
|
|
7048
6913
|
import * as net from "net";
|
|
7049
6914
|
import * as os8 from "os";
|
|
7050
|
-
import * as
|
|
6915
|
+
import * as path7 from "path";
|
|
7051
6916
|
|
|
7052
6917
|
// src/providers/provider-loader.ts
|
|
7053
6918
|
import * as fs5 from "fs";
|
|
7054
|
-
import * as
|
|
6919
|
+
import * as path6 from "path";
|
|
7055
6920
|
import * as os7 from "os";
|
|
7056
6921
|
import * as chokidar from "chokidar";
|
|
7057
6922
|
init_logger();
|
|
@@ -7072,12 +6937,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7072
6937
|
static META_FILE = ".meta.json";
|
|
7073
6938
|
constructor(options) {
|
|
7074
6939
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
7075
|
-
const defaultProvidersDir =
|
|
6940
|
+
const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
|
|
7076
6941
|
if (options?.userDir) {
|
|
7077
6942
|
this.userDir = options.userDir;
|
|
7078
6943
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
7079
6944
|
} else {
|
|
7080
|
-
const localRepoPath =
|
|
6945
|
+
const localRepoPath = path6.resolve(__dirname, "../../../../../adhdev-providers");
|
|
7081
6946
|
if (fs5.existsSync(localRepoPath)) {
|
|
7082
6947
|
this.userDir = localRepoPath;
|
|
7083
6948
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -7086,7 +6951,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7086
6951
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
7087
6952
|
}
|
|
7088
6953
|
}
|
|
7089
|
-
this.upstreamDir =
|
|
6954
|
+
this.upstreamDir = path6.join(defaultProvidersDir, ".upstream");
|
|
7090
6955
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
7091
6956
|
}
|
|
7092
6957
|
log(msg) {
|
|
@@ -7116,7 +6981,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7116
6981
|
* Canonical provider directory shape for a given root.
|
|
7117
6982
|
*/
|
|
7118
6983
|
getProviderDir(root, category, type) {
|
|
7119
|
-
return
|
|
6984
|
+
return path6.join(root, category, type);
|
|
7120
6985
|
}
|
|
7121
6986
|
/**
|
|
7122
6987
|
* Canonical user override directory for a provider.
|
|
@@ -7143,7 +7008,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7143
7008
|
resolveProviderFile(type, ...segments) {
|
|
7144
7009
|
const dir = this.findProviderDirInternal(type);
|
|
7145
7010
|
if (!dir) return null;
|
|
7146
|
-
return
|
|
7011
|
+
return path6.join(dir, ...segments);
|
|
7147
7012
|
}
|
|
7148
7013
|
/**
|
|
7149
7014
|
* Load all providers (3-tier priority)
|
|
@@ -7181,7 +7046,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7181
7046
|
if (!fs5.existsSync(this.upstreamDir)) return false;
|
|
7182
7047
|
try {
|
|
7183
7048
|
return fs5.readdirSync(this.upstreamDir).some(
|
|
7184
|
-
(d) => fs5.statSync(
|
|
7049
|
+
(d) => fs5.statSync(path6.join(this.upstreamDir, d)).isDirectory()
|
|
7185
7050
|
);
|
|
7186
7051
|
} catch {
|
|
7187
7052
|
return false;
|
|
@@ -7266,16 +7131,23 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7266
7131
|
isEnabled(type, ideType) {
|
|
7267
7132
|
if (!ideType) return true;
|
|
7268
7133
|
try {
|
|
7269
|
-
|
|
7270
|
-
const config = loadConfig2();
|
|
7271
|
-
const baseIdeType = ideType.split("_")[0];
|
|
7272
|
-
const val = config.ideSettings?.[baseIdeType]?.extensions?.[type]?.enabled;
|
|
7273
|
-
return val === true;
|
|
7134
|
+
return this.getIdeExtensionEnabledState(ideType, type);
|
|
7274
7135
|
} catch {
|
|
7275
7136
|
return false;
|
|
7276
7137
|
}
|
|
7277
7138
|
}
|
|
7278
7139
|
/**
|
|
7140
|
+
* Resolve per-IDE extension enabled state using the same normalization
|
|
7141
|
+
* that runtime attach/remove uses.
|
|
7142
|
+
*/
|
|
7143
|
+
getIdeExtensionEnabledState(ideType, extensionType) {
|
|
7144
|
+
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
7145
|
+
const config = loadConfig2();
|
|
7146
|
+
const baseIdeType = ideType.split("_")[0];
|
|
7147
|
+
const val = config.ideSettings?.[baseIdeType]?.extensions?.[extensionType]?.enabled;
|
|
7148
|
+
return val === true;
|
|
7149
|
+
}
|
|
7150
|
+
/**
|
|
7279
7151
|
* Save IDE extension enabled setting
|
|
7280
7152
|
*/
|
|
7281
7153
|
setIdeExtensionEnabled(ideType, extensionType, enabled) {
|
|
@@ -7473,14 +7345,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7473
7345
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
7474
7346
|
return null;
|
|
7475
7347
|
}
|
|
7476
|
-
const dir =
|
|
7348
|
+
const dir = path6.join(providerDir, scriptDir);
|
|
7477
7349
|
if (!fs5.existsSync(dir)) {
|
|
7478
7350
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
7479
7351
|
return null;
|
|
7480
7352
|
}
|
|
7481
7353
|
const cached = this.scriptsCache.get(dir);
|
|
7482
7354
|
if (cached) return cached;
|
|
7483
|
-
const scriptsJs =
|
|
7355
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
7484
7356
|
if (fs5.existsSync(scriptsJs)) {
|
|
7485
7357
|
try {
|
|
7486
7358
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -7519,7 +7391,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7519
7391
|
});
|
|
7520
7392
|
const handleChange = (filePath) => {
|
|
7521
7393
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
7522
|
-
this.log(`File changed: ${
|
|
7394
|
+
this.log(`File changed: ${path6.basename(filePath)}, reloading...`);
|
|
7523
7395
|
this.reload();
|
|
7524
7396
|
}
|
|
7525
7397
|
};
|
|
@@ -7574,7 +7446,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7574
7446
|
}
|
|
7575
7447
|
const https = __require("https");
|
|
7576
7448
|
const { execSync: execSync7 } = __require("child_process");
|
|
7577
|
-
const metaPath =
|
|
7449
|
+
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
7578
7450
|
let prevEtag = "";
|
|
7579
7451
|
let prevTimestamp = 0;
|
|
7580
7452
|
try {
|
|
@@ -7591,7 +7463,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7591
7463
|
return { updated: false };
|
|
7592
7464
|
}
|
|
7593
7465
|
try {
|
|
7594
|
-
const etag = await new Promise((
|
|
7466
|
+
const etag = await new Promise((resolve9, reject) => {
|
|
7595
7467
|
const options = {
|
|
7596
7468
|
method: "HEAD",
|
|
7597
7469
|
hostname: "github.com",
|
|
@@ -7609,7 +7481,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7609
7481
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
7610
7482
|
timeout: 1e4
|
|
7611
7483
|
}, (res2) => {
|
|
7612
|
-
|
|
7484
|
+
resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
7613
7485
|
});
|
|
7614
7486
|
req2.on("error", reject);
|
|
7615
7487
|
req2.on("timeout", () => {
|
|
@@ -7618,7 +7490,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7618
7490
|
});
|
|
7619
7491
|
req2.end();
|
|
7620
7492
|
} else {
|
|
7621
|
-
|
|
7493
|
+
resolve9(res.headers.etag || res.headers["last-modified"] || "");
|
|
7622
7494
|
}
|
|
7623
7495
|
});
|
|
7624
7496
|
req.on("error", reject);
|
|
@@ -7634,17 +7506,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7634
7506
|
return { updated: false };
|
|
7635
7507
|
}
|
|
7636
7508
|
this.log("Downloading latest providers from GitHub...");
|
|
7637
|
-
const tmpTar =
|
|
7638
|
-
const tmpExtract =
|
|
7509
|
+
const tmpTar = path6.join(os7.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
7510
|
+
const tmpExtract = path6.join(os7.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
7639
7511
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
7640
7512
|
fs5.mkdirSync(tmpExtract, { recursive: true });
|
|
7641
7513
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
7642
7514
|
const extracted = fs5.readdirSync(tmpExtract);
|
|
7643
7515
|
const rootDir = extracted.find(
|
|
7644
|
-
(d) => fs5.statSync(
|
|
7516
|
+
(d) => fs5.statSync(path6.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
7645
7517
|
);
|
|
7646
7518
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
7647
|
-
const sourceDir =
|
|
7519
|
+
const sourceDir = path6.join(tmpExtract, rootDir);
|
|
7648
7520
|
const backupDir = this.upstreamDir + ".bak";
|
|
7649
7521
|
if (fs5.existsSync(this.upstreamDir)) {
|
|
7650
7522
|
if (fs5.existsSync(backupDir)) fs5.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -7682,7 +7554,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7682
7554
|
downloadFile(url, destPath) {
|
|
7683
7555
|
const https = __require("https");
|
|
7684
7556
|
const http3 = __require("http");
|
|
7685
|
-
return new Promise((
|
|
7557
|
+
return new Promise((resolve9, reject) => {
|
|
7686
7558
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
7687
7559
|
if (redirectCount > 5) {
|
|
7688
7560
|
reject(new Error("Too many redirects"));
|
|
@@ -7702,7 +7574,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7702
7574
|
res.pipe(ws);
|
|
7703
7575
|
ws.on("finish", () => {
|
|
7704
7576
|
ws.close();
|
|
7705
|
-
|
|
7577
|
+
resolve9();
|
|
7706
7578
|
});
|
|
7707
7579
|
ws.on("error", reject);
|
|
7708
7580
|
});
|
|
@@ -7719,8 +7591,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7719
7591
|
copyDirRecursive(src, dest) {
|
|
7720
7592
|
fs5.mkdirSync(dest, { recursive: true });
|
|
7721
7593
|
for (const entry of fs5.readdirSync(src, { withFileTypes: true })) {
|
|
7722
|
-
const srcPath =
|
|
7723
|
-
const destPath =
|
|
7594
|
+
const srcPath = path6.join(src, entry.name);
|
|
7595
|
+
const destPath = path6.join(dest, entry.name);
|
|
7724
7596
|
if (entry.isDirectory()) {
|
|
7725
7597
|
this.copyDirRecursive(srcPath, destPath);
|
|
7726
7598
|
} else {
|
|
@@ -7731,7 +7603,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7731
7603
|
/** .meta.json save */
|
|
7732
7604
|
writeMeta(metaPath, etag, timestamp) {
|
|
7733
7605
|
try {
|
|
7734
|
-
fs5.mkdirSync(
|
|
7606
|
+
fs5.mkdirSync(path6.dirname(metaPath), { recursive: true });
|
|
7735
7607
|
fs5.writeFileSync(metaPath, JSON.stringify({
|
|
7736
7608
|
etag,
|
|
7737
7609
|
timestamp,
|
|
@@ -7748,7 +7620,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7748
7620
|
const scan = (d) => {
|
|
7749
7621
|
try {
|
|
7750
7622
|
for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
|
|
7751
|
-
if (entry.isDirectory()) scan(
|
|
7623
|
+
if (entry.isDirectory()) scan(path6.join(d, entry.name));
|
|
7752
7624
|
else if (entry.name === "provider.json") count++;
|
|
7753
7625
|
}
|
|
7754
7626
|
} catch {
|
|
@@ -7847,17 +7719,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7847
7719
|
for (const root of searchRoots) {
|
|
7848
7720
|
if (!fs5.existsSync(root)) continue;
|
|
7849
7721
|
const candidate = this.getProviderDir(root, cat, type);
|
|
7850
|
-
if (fs5.existsSync(
|
|
7851
|
-
const catDir =
|
|
7722
|
+
if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
|
|
7723
|
+
const catDir = path6.join(root, cat);
|
|
7852
7724
|
if (fs5.existsSync(catDir)) {
|
|
7853
7725
|
try {
|
|
7854
7726
|
for (const entry of fs5.readdirSync(catDir, { withFileTypes: true })) {
|
|
7855
7727
|
if (!entry.isDirectory()) continue;
|
|
7856
|
-
const jsonPath =
|
|
7728
|
+
const jsonPath = path6.join(catDir, entry.name, "provider.json");
|
|
7857
7729
|
if (fs5.existsSync(jsonPath)) {
|
|
7858
7730
|
try {
|
|
7859
7731
|
const data = JSON.parse(fs5.readFileSync(jsonPath, "utf-8"));
|
|
7860
|
-
if (data.type === type) return
|
|
7732
|
+
if (data.type === type) return path6.join(catDir, entry.name);
|
|
7861
7733
|
} catch {
|
|
7862
7734
|
}
|
|
7863
7735
|
}
|
|
@@ -7874,7 +7746,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7874
7746
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
7875
7747
|
*/
|
|
7876
7748
|
buildScriptWrappersFromDir(dir) {
|
|
7877
|
-
const scriptsJs =
|
|
7749
|
+
const scriptsJs = path6.join(dir, "scripts.js");
|
|
7878
7750
|
if (fs5.existsSync(scriptsJs)) {
|
|
7879
7751
|
try {
|
|
7880
7752
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -7888,7 +7760,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7888
7760
|
for (const file of fs5.readdirSync(dir)) {
|
|
7889
7761
|
if (!file.endsWith(".js")) continue;
|
|
7890
7762
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
7891
|
-
const filePath =
|
|
7763
|
+
const filePath = path6.join(dir, file);
|
|
7892
7764
|
result[scriptName] = (...args) => {
|
|
7893
7765
|
try {
|
|
7894
7766
|
let content = fs5.readFileSync(filePath, "utf-8");
|
|
@@ -7948,7 +7820,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7948
7820
|
}
|
|
7949
7821
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
7950
7822
|
if (hasJson) {
|
|
7951
|
-
const jsonPath =
|
|
7823
|
+
const jsonPath = path6.join(d, "provider.json");
|
|
7952
7824
|
try {
|
|
7953
7825
|
const raw = fs5.readFileSync(jsonPath, "utf-8");
|
|
7954
7826
|
const mod = JSON.parse(raw);
|
|
@@ -7961,7 +7833,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7961
7833
|
delete mod.extensionIdPattern_flags;
|
|
7962
7834
|
}
|
|
7963
7835
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
7964
|
-
const scriptsPath =
|
|
7836
|
+
const scriptsPath = path6.join(d, "scripts.js");
|
|
7965
7837
|
if (!hasCompatibility && fs5.existsSync(scriptsPath)) {
|
|
7966
7838
|
try {
|
|
7967
7839
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -7987,7 +7859,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7987
7859
|
if (!entry.isDirectory()) continue;
|
|
7988
7860
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
7989
7861
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
7990
|
-
scan(
|
|
7862
|
+
scan(path6.join(d, entry.name));
|
|
7991
7863
|
}
|
|
7992
7864
|
}
|
|
7993
7865
|
};
|
|
@@ -8067,17 +7939,17 @@ async function findFreePort(ports) {
|
|
|
8067
7939
|
throw new Error("No free port found");
|
|
8068
7940
|
}
|
|
8069
7941
|
function checkPortFree(port) {
|
|
8070
|
-
return new Promise((
|
|
7942
|
+
return new Promise((resolve9) => {
|
|
8071
7943
|
const server = net.createServer();
|
|
8072
7944
|
server.unref();
|
|
8073
|
-
server.on("error", () =>
|
|
7945
|
+
server.on("error", () => resolve9(false));
|
|
8074
7946
|
server.listen(port, "127.0.0.1", () => {
|
|
8075
|
-
server.close(() =>
|
|
7947
|
+
server.close(() => resolve9(true));
|
|
8076
7948
|
});
|
|
8077
7949
|
});
|
|
8078
7950
|
}
|
|
8079
7951
|
async function isCdpActive(port) {
|
|
8080
|
-
return new Promise((
|
|
7952
|
+
return new Promise((resolve9) => {
|
|
8081
7953
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
8082
7954
|
timeout: 2e3
|
|
8083
7955
|
}, (res) => {
|
|
@@ -8086,16 +7958,16 @@ async function isCdpActive(port) {
|
|
|
8086
7958
|
res.on("end", () => {
|
|
8087
7959
|
try {
|
|
8088
7960
|
const info = JSON.parse(data);
|
|
8089
|
-
|
|
7961
|
+
resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
8090
7962
|
} catch {
|
|
8091
|
-
|
|
7963
|
+
resolve9(false);
|
|
8092
7964
|
}
|
|
8093
7965
|
});
|
|
8094
7966
|
});
|
|
8095
|
-
req.on("error", () =>
|
|
7967
|
+
req.on("error", () => resolve9(false));
|
|
8096
7968
|
req.on("timeout", () => {
|
|
8097
7969
|
req.destroy();
|
|
8098
|
-
|
|
7970
|
+
resolve9(false);
|
|
8099
7971
|
});
|
|
8100
7972
|
});
|
|
8101
7973
|
}
|
|
@@ -8214,8 +8086,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
8214
8086
|
const appNameMap = getMacAppIdentifiers();
|
|
8215
8087
|
const appName = appNameMap[ideId];
|
|
8216
8088
|
if (appName) {
|
|
8217
|
-
const storagePath =
|
|
8218
|
-
process.env.APPDATA ||
|
|
8089
|
+
const storagePath = path7.join(
|
|
8090
|
+
process.env.APPDATA || path7.join(os8.homedir(), "AppData", "Roaming"),
|
|
8219
8091
|
appName,
|
|
8220
8092
|
"storage.json"
|
|
8221
8093
|
);
|
|
@@ -8384,15 +8256,13 @@ function getAvailableIdeIds() {
|
|
|
8384
8256
|
|
|
8385
8257
|
// src/commands/router.ts
|
|
8386
8258
|
init_config();
|
|
8387
|
-
init_workspaces();
|
|
8388
|
-
init_config();
|
|
8389
8259
|
init_logger();
|
|
8390
8260
|
|
|
8391
8261
|
// src/logging/command-log.ts
|
|
8392
8262
|
import * as fs6 from "fs";
|
|
8393
|
-
import * as
|
|
8263
|
+
import * as path8 from "path";
|
|
8394
8264
|
import * as os9 from "os";
|
|
8395
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
8265
|
+
var LOG_DIR2 = process.platform === "win32" ? path8.join(process.env.LOCALAPPDATA || process.env.APPDATA || path8.join(os9.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path8.join(os9.homedir(), "Library", "Logs", "adhdev") : path8.join(os9.homedir(), ".local", "share", "adhdev", "logs");
|
|
8396
8266
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
8397
8267
|
var MAX_DAYS = 7;
|
|
8398
8268
|
try {
|
|
@@ -8430,13 +8300,13 @@ function getDateStr2() {
|
|
|
8430
8300
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8431
8301
|
}
|
|
8432
8302
|
var currentDate2 = getDateStr2();
|
|
8433
|
-
var currentFile =
|
|
8303
|
+
var currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
8434
8304
|
var writeCount2 = 0;
|
|
8435
8305
|
function checkRotation() {
|
|
8436
8306
|
const today = getDateStr2();
|
|
8437
8307
|
if (today !== currentDate2) {
|
|
8438
8308
|
currentDate2 = today;
|
|
8439
|
-
currentFile =
|
|
8309
|
+
currentFile = path8.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
8440
8310
|
cleanOldFiles();
|
|
8441
8311
|
}
|
|
8442
8312
|
}
|
|
@@ -8450,7 +8320,7 @@ function cleanOldFiles() {
|
|
|
8450
8320
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
8451
8321
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
8452
8322
|
try {
|
|
8453
|
-
fs6.unlinkSync(
|
|
8323
|
+
fs6.unlinkSync(path8.join(LOG_DIR2, file));
|
|
8454
8324
|
} catch {
|
|
8455
8325
|
}
|
|
8456
8326
|
}
|
|
@@ -8472,59 +8342,202 @@ function checkSize() {
|
|
|
8472
8342
|
} catch {
|
|
8473
8343
|
}
|
|
8474
8344
|
}
|
|
8475
|
-
var SKIP_COMMANDS = /* @__PURE__ */ new Set([
|
|
8476
|
-
"heartbeat",
|
|
8477
|
-
"status_report"
|
|
8478
|
-
]);
|
|
8479
|
-
function logCommand(entry) {
|
|
8480
|
-
if (SKIP_COMMANDS.has(entry.cmd)) return;
|
|
8481
|
-
try {
|
|
8482
|
-
if (++writeCount2 % 500 === 0) {
|
|
8483
|
-
checkRotation();
|
|
8484
|
-
checkSize();
|
|
8485
|
-
}
|
|
8486
|
-
const line = JSON.stringify({
|
|
8487
|
-
ts: entry.ts,
|
|
8488
|
-
cmd: entry.cmd,
|
|
8489
|
-
src: entry.source,
|
|
8490
|
-
...entry.args ? { args: maskArgs(entry.args) } : {},
|
|
8491
|
-
...entry.success !== void 0 ? { ok: entry.success } : {},
|
|
8492
|
-
...entry.error ? { err: entry.error } : {},
|
|
8493
|
-
...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
|
|
8494
|
-
});
|
|
8495
|
-
fs6.appendFileSync(currentFile, line + "\n");
|
|
8496
|
-
} catch {
|
|
8345
|
+
var SKIP_COMMANDS = /* @__PURE__ */ new Set([
|
|
8346
|
+
"heartbeat",
|
|
8347
|
+
"status_report"
|
|
8348
|
+
]);
|
|
8349
|
+
function logCommand(entry) {
|
|
8350
|
+
if (SKIP_COMMANDS.has(entry.cmd)) return;
|
|
8351
|
+
try {
|
|
8352
|
+
if (++writeCount2 % 500 === 0) {
|
|
8353
|
+
checkRotation();
|
|
8354
|
+
checkSize();
|
|
8355
|
+
}
|
|
8356
|
+
const line = JSON.stringify({
|
|
8357
|
+
ts: entry.ts,
|
|
8358
|
+
cmd: entry.cmd,
|
|
8359
|
+
src: entry.source,
|
|
8360
|
+
...entry.args ? { args: maskArgs(entry.args) } : {},
|
|
8361
|
+
...entry.success !== void 0 ? { ok: entry.success } : {},
|
|
8362
|
+
...entry.error ? { err: entry.error } : {},
|
|
8363
|
+
...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
|
|
8364
|
+
});
|
|
8365
|
+
fs6.appendFileSync(currentFile, line + "\n");
|
|
8366
|
+
} catch {
|
|
8367
|
+
}
|
|
8368
|
+
}
|
|
8369
|
+
function getRecentCommands(count = 50) {
|
|
8370
|
+
try {
|
|
8371
|
+
if (!fs6.existsSync(currentFile)) return [];
|
|
8372
|
+
const content = fs6.readFileSync(currentFile, "utf-8");
|
|
8373
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
8374
|
+
return lines.slice(-count).map((line) => {
|
|
8375
|
+
try {
|
|
8376
|
+
const parsed = JSON.parse(line);
|
|
8377
|
+
return {
|
|
8378
|
+
ts: parsed.ts,
|
|
8379
|
+
cmd: parsed.cmd,
|
|
8380
|
+
source: parsed.src,
|
|
8381
|
+
args: parsed.args,
|
|
8382
|
+
success: parsed.ok,
|
|
8383
|
+
error: parsed.err,
|
|
8384
|
+
durationMs: parsed.ms
|
|
8385
|
+
};
|
|
8386
|
+
} catch {
|
|
8387
|
+
return { ts: "", cmd: "parse_error", source: "unknown" };
|
|
8388
|
+
}
|
|
8389
|
+
});
|
|
8390
|
+
} catch {
|
|
8391
|
+
return [];
|
|
8392
|
+
}
|
|
8393
|
+
}
|
|
8394
|
+
cleanOldFiles();
|
|
8395
|
+
|
|
8396
|
+
// src/commands/router.ts
|
|
8397
|
+
init_logger();
|
|
8398
|
+
|
|
8399
|
+
// src/status/snapshot.ts
|
|
8400
|
+
init_config();
|
|
8401
|
+
import * as os10 from "os";
|
|
8402
|
+
init_terminal_screen();
|
|
8403
|
+
init_logger();
|
|
8404
|
+
var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8405
|
+
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8406
|
+
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8407
|
+
id: ide.id,
|
|
8408
|
+
type: ide.id,
|
|
8409
|
+
name: ide.displayName || ide.name || ide.id,
|
|
8410
|
+
running: isCdpConnected(cdpManagers, ide.id),
|
|
8411
|
+
...ide.path ? { path: ide.path } : {}
|
|
8412
|
+
}));
|
|
8413
|
+
}
|
|
8414
|
+
function buildAvailableProviders(providerLoader) {
|
|
8415
|
+
return providerLoader.getAll().map((provider) => ({
|
|
8416
|
+
type: provider.type,
|
|
8417
|
+
name: provider.displayName || provider.type,
|
|
8418
|
+
displayName: provider.displayName || provider.type,
|
|
8419
|
+
icon: provider.icon || "\u{1F4BB}",
|
|
8420
|
+
category: provider.category
|
|
8421
|
+
}));
|
|
8422
|
+
}
|
|
8423
|
+
function parseMessageTime(value) {
|
|
8424
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8425
|
+
if (typeof value === "string") {
|
|
8426
|
+
const parsed = Date.parse(value);
|
|
8427
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
8428
|
+
}
|
|
8429
|
+
return 0;
|
|
8430
|
+
}
|
|
8431
|
+
function getSessionMessageUpdatedAt(session) {
|
|
8432
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8433
|
+
if (!lastMessage) return 0;
|
|
8434
|
+
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8435
|
+
}
|
|
8436
|
+
function getSessionCompletionMarker(session) {
|
|
8437
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8438
|
+
if (!lastMessage) return "";
|
|
8439
|
+
const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
|
|
8440
|
+
if (role === "user" || role === "human") return "";
|
|
8441
|
+
if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
|
|
8442
|
+
if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
|
|
8443
|
+
if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
|
|
8444
|
+
const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
|
|
8445
|
+
return timestamp > 0 ? `ts:${timestamp}` : "";
|
|
8446
|
+
}
|
|
8447
|
+
function getSessionLastUsedAt(session) {
|
|
8448
|
+
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8449
|
+
}
|
|
8450
|
+
function getLastMessageRole(session) {
|
|
8451
|
+
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8452
|
+
return typeof role === "string" ? role : "";
|
|
8453
|
+
}
|
|
8454
|
+
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
|
|
8455
|
+
if (status === "waiting_approval") {
|
|
8456
|
+
return { unread: false, inboxBucket: "needs_attention" };
|
|
8457
|
+
}
|
|
8458
|
+
if (status === "generating" || status === "starting") {
|
|
8459
|
+
return { unread: false, inboxBucket: "working" };
|
|
8497
8460
|
}
|
|
8461
|
+
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8462
|
+
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8498
8463
|
}
|
|
8499
|
-
function
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8464
|
+
function buildRecentLaunches(recentActivity) {
|
|
8465
|
+
return recentActivity.map((item) => ({
|
|
8466
|
+
id: item.id,
|
|
8467
|
+
providerType: item.providerType,
|
|
8468
|
+
providerName: item.providerName,
|
|
8469
|
+
kind: item.kind,
|
|
8470
|
+
title: item.title || item.providerName,
|
|
8471
|
+
workspace: item.workspace,
|
|
8472
|
+
currentModel: item.currentModel,
|
|
8473
|
+
lastLaunchedAt: item.lastUsedAt
|
|
8474
|
+
})).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
|
|
8475
|
+
}
|
|
8476
|
+
function buildStatusSnapshot(options) {
|
|
8477
|
+
const cfg = loadConfig();
|
|
8478
|
+
const wsState = getWorkspaceState(cfg);
|
|
8479
|
+
const memSnap = getHostMemorySnapshot();
|
|
8480
|
+
const recentActivity = getRecentActivity(cfg, 20);
|
|
8481
|
+
const sessions = buildSessionEntries(
|
|
8482
|
+
options.allStates,
|
|
8483
|
+
options.cdpManagers
|
|
8484
|
+
);
|
|
8485
|
+
for (const session of sessions) {
|
|
8486
|
+
const lastSeenAt = getSessionSeenAt(cfg, session.id);
|
|
8487
|
+
const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
|
|
8488
|
+
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8489
|
+
const completionMarker = getSessionCompletionMarker(session);
|
|
8490
|
+
const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
|
|
8491
|
+
getSessionMessageUpdatedAt(session) > 0,
|
|
8492
|
+
session.status,
|
|
8493
|
+
lastUsedAt,
|
|
8494
|
+
lastSeenAt,
|
|
8495
|
+
getLastMessageRole(session),
|
|
8496
|
+
completionMarker,
|
|
8497
|
+
seenCompletionMarker
|
|
8498
|
+
);
|
|
8499
|
+
session.lastSeenAt = lastSeenAt;
|
|
8500
|
+
session.unread = unread;
|
|
8501
|
+
session.inboxBucket = inboxBucket;
|
|
8502
|
+
if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
|
|
8503
|
+
LOG.info(
|
|
8504
|
+
"RecentRead",
|
|
8505
|
+
`snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(session)} msgUpdatedAt=${getSessionMessageUpdatedAt(session)}`
|
|
8506
|
+
);
|
|
8507
|
+
}
|
|
8522
8508
|
}
|
|
8509
|
+
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
8510
|
+
return {
|
|
8511
|
+
instanceId: options.instanceId,
|
|
8512
|
+
version: options.version,
|
|
8513
|
+
daemonMode: options.daemonMode,
|
|
8514
|
+
machine: {
|
|
8515
|
+
hostname: os10.hostname(),
|
|
8516
|
+
platform: os10.platform(),
|
|
8517
|
+
arch: os10.arch(),
|
|
8518
|
+
cpus: os10.cpus().length,
|
|
8519
|
+
totalMem: memSnap.totalMem,
|
|
8520
|
+
freeMem: memSnap.freeMem,
|
|
8521
|
+
availableMem: memSnap.availableMem,
|
|
8522
|
+
loadavg: os10.loadavg(),
|
|
8523
|
+
uptime: os10.uptime(),
|
|
8524
|
+
release: os10.release()
|
|
8525
|
+
},
|
|
8526
|
+
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
8527
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
8528
|
+
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8529
|
+
...options.p2p ? { p2p: options.p2p } : {},
|
|
8530
|
+
sessions,
|
|
8531
|
+
workspaces: wsState.workspaces,
|
|
8532
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8533
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
8534
|
+
recentLaunches: buildRecentLaunches(recentActivity),
|
|
8535
|
+
terminalBackend,
|
|
8536
|
+
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
8537
|
+
};
|
|
8523
8538
|
}
|
|
8524
|
-
cleanOldFiles();
|
|
8525
8539
|
|
|
8526
8540
|
// src/commands/router.ts
|
|
8527
|
-
init_logger();
|
|
8528
8541
|
import * as fs7 from "fs";
|
|
8529
8542
|
var CHAT_COMMANDS = [
|
|
8530
8543
|
"send_chat",
|
|
@@ -8533,6 +8546,7 @@ var CHAT_COMMANDS = [
|
|
|
8533
8546
|
"set_mode",
|
|
8534
8547
|
"change_model"
|
|
8535
8548
|
];
|
|
8549
|
+
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8536
8550
|
var DaemonCommandRouter = class {
|
|
8537
8551
|
deps;
|
|
8538
8552
|
constructor(deps) {
|
|
@@ -8651,18 +8665,6 @@ var DaemonCommandRouter = class {
|
|
|
8651
8665
|
};
|
|
8652
8666
|
LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
8653
8667
|
const result = await launchWithCdp(launchArgs);
|
|
8654
|
-
if (result.success && (result.ideId || ideKey)) {
|
|
8655
|
-
try {
|
|
8656
|
-
addCliHistory({
|
|
8657
|
-
category: "ide",
|
|
8658
|
-
cliType: result.ideId || ideKey,
|
|
8659
|
-
dir: resolvedWorkspace || "",
|
|
8660
|
-
workspace: resolvedWorkspace || "",
|
|
8661
|
-
newWindow: args?.newWindow === true
|
|
8662
|
-
});
|
|
8663
|
-
} catch {
|
|
8664
|
-
}
|
|
8665
|
-
}
|
|
8666
8668
|
if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
|
|
8667
8669
|
const logFn = this.deps.getCdpLogFn ? this.deps.getCdpLogFn(result.ideId) : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
|
|
8668
8670
|
const provider = this.deps.providerLoader.getMeta(result.ideId);
|
|
@@ -8679,11 +8681,7 @@ var DaemonCommandRouter = class {
|
|
|
8679
8681
|
this.deps.onIdeConnected?.();
|
|
8680
8682
|
if (result.success && resolvedWorkspace) {
|
|
8681
8683
|
try {
|
|
8682
|
-
|
|
8683
|
-
kind: "ide",
|
|
8684
|
-
agentType: result.ideId
|
|
8685
|
-
});
|
|
8686
|
-
next = appendRecentActivity(next, {
|
|
8684
|
+
const next = appendRecentActivity(loadConfig(), {
|
|
8687
8685
|
kind: "ide",
|
|
8688
8686
|
providerType: result.ideId || ideKey,
|
|
8689
8687
|
providerName: result.ideId || ideKey,
|
|
@@ -8719,28 +8717,35 @@ var DaemonCommandRouter = class {
|
|
|
8719
8717
|
updateConfig({ userName: name });
|
|
8720
8718
|
return { success: true, userName: name };
|
|
8721
8719
|
}
|
|
8722
|
-
case "
|
|
8723
|
-
const
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
return { success: false, error: "kind and providerType are required" };
|
|
8720
|
+
case "mark_session_seen": {
|
|
8721
|
+
const sessionId = args?.sessionId;
|
|
8722
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
8723
|
+
return { success: false, error: "sessionId is required" };
|
|
8727
8724
|
}
|
|
8728
|
-
const
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
const next = markRecentSessionSeen(
|
|
8734
|
-
loadConfig(),
|
|
8735
|
-
recentKey,
|
|
8736
|
-
typeof args?.seenAt === "number" ? args.seenAt : Date.now()
|
|
8725
|
+
const currentConfig = loadConfig();
|
|
8726
|
+
const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
|
|
8727
|
+
const sessionEntries = buildSessionEntries(
|
|
8728
|
+
this.deps.instanceManager.collectAllStates(),
|
|
8729
|
+
this.deps.cdpManagers
|
|
8737
8730
|
);
|
|
8731
|
+
const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
|
|
8732
|
+
const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
|
|
8733
|
+
const next = markSessionSeen(
|
|
8734
|
+
currentConfig,
|
|
8735
|
+
sessionId,
|
|
8736
|
+
typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
|
|
8737
|
+
completionMarker
|
|
8738
|
+
);
|
|
8739
|
+
if (READ_DEBUG_ENABLED2) {
|
|
8740
|
+
LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
|
|
8741
|
+
}
|
|
8738
8742
|
saveConfig(next);
|
|
8739
8743
|
this.deps.onStatusChange?.();
|
|
8740
8744
|
return {
|
|
8741
8745
|
success: true,
|
|
8742
|
-
|
|
8743
|
-
seenAt: next.
|
|
8746
|
+
sessionId,
|
|
8747
|
+
seenAt: next.sessionReads?.[sessionId] || Date.now(),
|
|
8748
|
+
completionMarker
|
|
8744
8749
|
};
|
|
8745
8750
|
}
|
|
8746
8751
|
// ─── Daemon Self-Upgrade ───
|
|
@@ -8761,9 +8766,9 @@ var DaemonCommandRouter = class {
|
|
|
8761
8766
|
setTimeout(() => {
|
|
8762
8767
|
LOG.info("Upgrade", "Restarting daemon with new version...");
|
|
8763
8768
|
try {
|
|
8764
|
-
const
|
|
8769
|
+
const path15 = __require("path");
|
|
8765
8770
|
const fs12 = __require("fs");
|
|
8766
|
-
const pidFile =
|
|
8771
|
+
const pidFile = path15.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "daemon.pid");
|
|
8767
8772
|
if (fs12.existsSync(pidFile)) fs12.unlinkSync(pidFile);
|
|
8768
8773
|
} catch {
|
|
8769
8774
|
}
|
|
@@ -8857,183 +8862,6 @@ var DaemonCommandRouter = class {
|
|
|
8857
8862
|
|
|
8858
8863
|
// src/status/reporter.ts
|
|
8859
8864
|
init_logger();
|
|
8860
|
-
|
|
8861
|
-
// src/status/snapshot.ts
|
|
8862
|
-
init_config();
|
|
8863
|
-
import * as os10 from "os";
|
|
8864
|
-
init_workspaces();
|
|
8865
|
-
init_terminal_screen();
|
|
8866
|
-
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8867
|
-
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8868
|
-
id: ide.id,
|
|
8869
|
-
type: ide.id,
|
|
8870
|
-
name: ide.displayName || ide.name || ide.id,
|
|
8871
|
-
running: isCdpConnected(cdpManagers, ide.id),
|
|
8872
|
-
...ide.path ? { path: ide.path } : {}
|
|
8873
|
-
}));
|
|
8874
|
-
}
|
|
8875
|
-
function buildAvailableProviders(providerLoader) {
|
|
8876
|
-
return providerLoader.getAll().map((provider) => ({
|
|
8877
|
-
type: provider.type,
|
|
8878
|
-
name: provider.displayName || provider.type,
|
|
8879
|
-
displayName: provider.displayName || provider.type,
|
|
8880
|
-
icon: provider.icon || "\u{1F4BB}",
|
|
8881
|
-
category: provider.category
|
|
8882
|
-
}));
|
|
8883
|
-
}
|
|
8884
|
-
function parseMessageTime(value) {
|
|
8885
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8886
|
-
if (typeof value === "string") {
|
|
8887
|
-
const parsed = Date.parse(value);
|
|
8888
|
-
if (Number.isFinite(parsed)) return parsed;
|
|
8889
|
-
}
|
|
8890
|
-
return 0;
|
|
8891
|
-
}
|
|
8892
|
-
function getSessionMessageUpdatedAt(session) {
|
|
8893
|
-
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8894
|
-
if (!lastMessage) return 0;
|
|
8895
|
-
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8896
|
-
}
|
|
8897
|
-
function getSessionLastUsedAt(session) {
|
|
8898
|
-
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8899
|
-
}
|
|
8900
|
-
function getSessionKind(session) {
|
|
8901
|
-
return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
|
|
8902
|
-
}
|
|
8903
|
-
function getLastMessageRole(session) {
|
|
8904
|
-
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8905
|
-
return typeof role === "string" ? role : "";
|
|
8906
|
-
}
|
|
8907
|
-
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
|
|
8908
|
-
if (status === "waiting_approval") {
|
|
8909
|
-
return { unread: false, inboxBucket: "needs_attention" };
|
|
8910
|
-
}
|
|
8911
|
-
if (status === "generating" || status === "starting") {
|
|
8912
|
-
return { unread: false, inboxBucket: "working" };
|
|
8913
|
-
}
|
|
8914
|
-
const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8915
|
-
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8916
|
-
}
|
|
8917
|
-
function buildRecentSessions(sessions, recentActivity, readState) {
|
|
8918
|
-
const live = sessions.filter((session) => !session.parentId && session.status !== "stopped").map((session) => {
|
|
8919
|
-
const kind = getSessionKind(session);
|
|
8920
|
-
const recentKey = buildRecentActivityKey({
|
|
8921
|
-
kind,
|
|
8922
|
-
providerType: session.providerType,
|
|
8923
|
-
workspace: session.workspace
|
|
8924
|
-
});
|
|
8925
|
-
const lastSeenAt = readState[recentKey] || 0;
|
|
8926
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8927
|
-
const { unread, inboxBucket } = getUnreadState(
|
|
8928
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8929
|
-
session.status,
|
|
8930
|
-
lastUsedAt,
|
|
8931
|
-
lastSeenAt,
|
|
8932
|
-
getLastMessageRole(session)
|
|
8933
|
-
);
|
|
8934
|
-
return {
|
|
8935
|
-
id: session.id,
|
|
8936
|
-
recentKey,
|
|
8937
|
-
sessionId: session.id,
|
|
8938
|
-
providerType: session.providerType,
|
|
8939
|
-
providerName: session.providerName,
|
|
8940
|
-
kind,
|
|
8941
|
-
title: session.activeChat?.title || session.title || session.providerName,
|
|
8942
|
-
workspace: session.workspace,
|
|
8943
|
-
currentModel: session.currentModel,
|
|
8944
|
-
status: session.status,
|
|
8945
|
-
lastUsedAt,
|
|
8946
|
-
unread,
|
|
8947
|
-
lastSeenAt,
|
|
8948
|
-
inboxBucket
|
|
8949
|
-
};
|
|
8950
|
-
});
|
|
8951
|
-
const seen = new Set(live.map((item) => `${item.kind}:${item.providerType}:${item.workspace || ""}`));
|
|
8952
|
-
const persisted = recentActivity.filter((item) => !seen.has(`${item.kind}:${item.providerType}:${item.workspace || ""}`)).map((item) => {
|
|
8953
|
-
const lastSeenAt = readState[item.id] || 0;
|
|
8954
|
-
const unread = item.lastUsedAt > lastSeenAt;
|
|
8955
|
-
return {
|
|
8956
|
-
id: item.id,
|
|
8957
|
-
recentKey: item.id,
|
|
8958
|
-
sessionId: item.sessionId || null,
|
|
8959
|
-
providerType: item.providerType,
|
|
8960
|
-
providerName: item.providerName,
|
|
8961
|
-
kind: item.kind,
|
|
8962
|
-
title: item.title || item.providerName,
|
|
8963
|
-
workspace: item.workspace,
|
|
8964
|
-
currentModel: item.currentModel,
|
|
8965
|
-
lastUsedAt: item.lastUsedAt,
|
|
8966
|
-
unread,
|
|
8967
|
-
lastSeenAt,
|
|
8968
|
-
inboxBucket: unread ? "task_complete" : "idle"
|
|
8969
|
-
};
|
|
8970
|
-
});
|
|
8971
|
-
return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
|
|
8972
|
-
}
|
|
8973
|
-
function buildStatusSnapshot(options) {
|
|
8974
|
-
const cfg = loadConfig();
|
|
8975
|
-
const wsState = getWorkspaceState(cfg);
|
|
8976
|
-
const memSnap = getHostMemorySnapshot();
|
|
8977
|
-
const recentActivity = getRecentActivity(cfg, 20);
|
|
8978
|
-
const sessions = buildSessionEntries(
|
|
8979
|
-
options.allStates,
|
|
8980
|
-
options.cdpManagers
|
|
8981
|
-
);
|
|
8982
|
-
const readState = cfg.recentSessionReads || {};
|
|
8983
|
-
for (const session of sessions) {
|
|
8984
|
-
const kind = getSessionKind(session);
|
|
8985
|
-
const recentKey = buildRecentActivityKey({
|
|
8986
|
-
kind,
|
|
8987
|
-
providerType: session.providerType,
|
|
8988
|
-
workspace: session.workspace
|
|
8989
|
-
});
|
|
8990
|
-
const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
|
|
8991
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8992
|
-
const { unread, inboxBucket } = getUnreadState(
|
|
8993
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8994
|
-
session.status,
|
|
8995
|
-
lastUsedAt,
|
|
8996
|
-
lastSeenAt,
|
|
8997
|
-
getLastMessageRole(session)
|
|
8998
|
-
);
|
|
8999
|
-
session.recentKey = recentKey;
|
|
9000
|
-
session.lastSeenAt = lastSeenAt;
|
|
9001
|
-
session.unread = unread;
|
|
9002
|
-
session.inboxBucket = inboxBucket;
|
|
9003
|
-
}
|
|
9004
|
-
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
9005
|
-
return {
|
|
9006
|
-
instanceId: options.instanceId,
|
|
9007
|
-
version: options.version,
|
|
9008
|
-
daemonMode: options.daemonMode,
|
|
9009
|
-
machine: {
|
|
9010
|
-
hostname: os10.hostname(),
|
|
9011
|
-
platform: os10.platform(),
|
|
9012
|
-
arch: os10.arch(),
|
|
9013
|
-
cpus: os10.cpus().length,
|
|
9014
|
-
totalMem: memSnap.totalMem,
|
|
9015
|
-
freeMem: memSnap.freeMem,
|
|
9016
|
-
availableMem: memSnap.availableMem,
|
|
9017
|
-
loadavg: os10.loadavg(),
|
|
9018
|
-
uptime: os10.uptime(),
|
|
9019
|
-
release: os10.release()
|
|
9020
|
-
},
|
|
9021
|
-
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
9022
|
-
timestamp: options.timestamp ?? Date.now(),
|
|
9023
|
-
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
9024
|
-
...options.p2p ? { p2p: options.p2p } : {},
|
|
9025
|
-
sessions,
|
|
9026
|
-
workspaces: wsState.workspaces,
|
|
9027
|
-
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
9028
|
-
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
9029
|
-
workspaceActivity: getWorkspaceActivity(cfg, 15),
|
|
9030
|
-
recentSessions: buildRecentSessions(sessions, recentActivity, readState),
|
|
9031
|
-
terminalBackend,
|
|
9032
|
-
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
9033
|
-
};
|
|
9034
|
-
}
|
|
9035
|
-
|
|
9036
|
-
// src/status/reporter.ts
|
|
9037
8865
|
var DaemonStatusReporter = class {
|
|
9038
8866
|
deps;
|
|
9039
8867
|
log;
|
|
@@ -9181,10 +9009,11 @@ var DaemonStatusReporter = class {
|
|
|
9181
9009
|
currentModel: session.currentModel,
|
|
9182
9010
|
currentPlan: session.currentPlan,
|
|
9183
9011
|
currentAutoApprove: session.currentAutoApprove,
|
|
9184
|
-
|
|
9012
|
+
lastUpdated: session.lastUpdated,
|
|
9185
9013
|
unread: session.unread,
|
|
9186
9014
|
lastSeenAt: session.lastSeenAt,
|
|
9187
9015
|
inboxBucket: session.inboxBucket,
|
|
9016
|
+
surfaceHidden: session.surfaceHidden,
|
|
9188
9017
|
controlValues: session.controlValues,
|
|
9189
9018
|
providerControls: session.providerControls,
|
|
9190
9019
|
acpConfigOptions: session.acpConfigOptions,
|
|
@@ -9227,11 +9056,10 @@ init_logger();
|
|
|
9227
9056
|
// src/commands/cli-manager.ts
|
|
9228
9057
|
init_provider_cli_adapter();
|
|
9229
9058
|
import * as os13 from "os";
|
|
9230
|
-
import * as
|
|
9059
|
+
import * as path10 from "path";
|
|
9231
9060
|
import * as crypto4 from "crypto";
|
|
9232
9061
|
import chalk from "chalk";
|
|
9233
9062
|
init_config();
|
|
9234
|
-
init_workspaces();
|
|
9235
9063
|
|
|
9236
9064
|
// src/providers/cli-provider-instance.ts
|
|
9237
9065
|
init_provider_cli_adapter();
|
|
@@ -9912,13 +9740,13 @@ var AcpProviderInstance = class {
|
|
|
9912
9740
|
}
|
|
9913
9741
|
this.currentStatus = "waiting_approval";
|
|
9914
9742
|
this.detectStatusTransition();
|
|
9915
|
-
const approved = await new Promise((
|
|
9916
|
-
this.permissionResolvers.push(
|
|
9743
|
+
const approved = await new Promise((resolve9) => {
|
|
9744
|
+
this.permissionResolvers.push(resolve9);
|
|
9917
9745
|
setTimeout(() => {
|
|
9918
|
-
const idx = this.permissionResolvers.indexOf(
|
|
9746
|
+
const idx = this.permissionResolvers.indexOf(resolve9);
|
|
9919
9747
|
if (idx >= 0) {
|
|
9920
9748
|
this.permissionResolvers.splice(idx, 1);
|
|
9921
|
-
|
|
9749
|
+
resolve9(false);
|
|
9922
9750
|
}
|
|
9923
9751
|
}, 3e5);
|
|
9924
9752
|
});
|
|
@@ -10393,24 +10221,6 @@ var DaemonCliManager = class {
|
|
|
10393
10221
|
const hash = __require("crypto").createHash("md5").update(__require("path").resolve(dir)).digest("hex").slice(0, 8);
|
|
10394
10222
|
return `${cliType}_${hash}`;
|
|
10395
10223
|
}
|
|
10396
|
-
persistRecentDir(cliType, dir) {
|
|
10397
|
-
try {
|
|
10398
|
-
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10399
|
-
const provider = this.providerLoader.getByAlias(cliType);
|
|
10400
|
-
const actKind = provider?.category === "acp" ? "acp" : "cli";
|
|
10401
|
-
let next = loadConfig();
|
|
10402
|
-
console.log(colorize("cyan", ` \u{1F4C2} Saving recent workspace: ${dir}`));
|
|
10403
|
-
const recent = next.recentCliWorkspaces || [];
|
|
10404
|
-
if (!recent.includes(dir)) {
|
|
10405
|
-
next = { ...next, recentCliWorkspaces: [dir, ...recent].slice(0, 10) };
|
|
10406
|
-
}
|
|
10407
|
-
next = appendWorkspaceActivity(next, dir, { kind: actKind, agentType: normalizedType });
|
|
10408
|
-
saveConfig(next);
|
|
10409
|
-
console.log(colorize("green", ` \u2713 Recent workspace saved: ${dir}`));
|
|
10410
|
-
} catch (e) {
|
|
10411
|
-
console.error(colorize("red", ` \u2717 Failed to save recent workspace: ${e}`));
|
|
10412
|
-
}
|
|
10413
|
-
}
|
|
10414
10224
|
persistRecentActivity(entry) {
|
|
10415
10225
|
try {
|
|
10416
10226
|
saveConfig(appendRecentActivity(loadConfig(), entry));
|
|
@@ -10500,7 +10310,7 @@ var DaemonCliManager = class {
|
|
|
10500
10310
|
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
10501
10311
|
const trimmed = (workingDir || "").trim();
|
|
10502
10312
|
if (!trimmed) throw new Error("working directory required");
|
|
10503
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
10313
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
|
|
10504
10314
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10505
10315
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10506
10316
|
const key = crypto4.randomUUID();
|
|
@@ -10571,11 +10381,6 @@ ${installInfo}`
|
|
|
10571
10381
|
LOG.warn("CLI", `[ACP] Initial model set failed: ${e?.message}`);
|
|
10572
10382
|
}
|
|
10573
10383
|
}
|
|
10574
|
-
try {
|
|
10575
|
-
addCliHistory({ category: "acp", cliType: normalizedType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel });
|
|
10576
|
-
} catch (e) {
|
|
10577
|
-
LOG.warn("CLI", `ACP history save failed: ${e?.message}`);
|
|
10578
|
-
}
|
|
10579
10384
|
this.persistRecentActivity({
|
|
10580
10385
|
kind: "acp",
|
|
10581
10386
|
providerType: normalizedType,
|
|
@@ -10642,11 +10447,6 @@ ${installInfo}`
|
|
|
10642
10447
|
this.adapters.set(key, adapter);
|
|
10643
10448
|
console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
10644
10449
|
}
|
|
10645
|
-
try {
|
|
10646
|
-
addCliHistory({ category: "cli", cliType, dir: resolvedDir, workspace: resolvedDir, cliArgs, model: initialModel });
|
|
10647
|
-
} catch (e) {
|
|
10648
|
-
LOG.warn("CLI", `CLI history save failed: ${e?.message}`);
|
|
10649
|
-
}
|
|
10650
10450
|
this.persistRecentActivity({
|
|
10651
10451
|
kind: "cli",
|
|
10652
10452
|
providerType: normalizedType,
|
|
@@ -10799,7 +10599,6 @@ ${installInfo}`
|
|
|
10799
10599
|
newKey = k;
|
|
10800
10600
|
}
|
|
10801
10601
|
}
|
|
10802
|
-
this.persistRecentDir(cliType, dir);
|
|
10803
10602
|
return { success: true, cliType, dir, id: newKey, launchSource };
|
|
10804
10603
|
}
|
|
10805
10604
|
case "stop_cli": {
|
|
@@ -10842,7 +10641,6 @@ ${installInfo}`
|
|
|
10842
10641
|
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
10843
10642
|
if (found) await this.stopSession(found.key);
|
|
10844
10643
|
await this.startSession(cliType, dir);
|
|
10845
|
-
this.persistRecentDir(cliType, dir);
|
|
10846
10644
|
return { success: true, restarted: true };
|
|
10847
10645
|
}
|
|
10848
10646
|
case "agent_command": {
|
|
@@ -11665,11 +11463,11 @@ var ProviderInstanceManager = class {
|
|
|
11665
11463
|
|
|
11666
11464
|
// src/providers/version-archive.ts
|
|
11667
11465
|
import * as fs8 from "fs";
|
|
11668
|
-
import * as
|
|
11466
|
+
import * as path11 from "path";
|
|
11669
11467
|
import * as os14 from "os";
|
|
11670
11468
|
import { execSync as execSync5 } from "child_process";
|
|
11671
11469
|
import { platform as platform8 } from "os";
|
|
11672
|
-
var ARCHIVE_PATH =
|
|
11470
|
+
var ARCHIVE_PATH = path11.join(os14.homedir(), ".adhdev", "version-history.json");
|
|
11673
11471
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
11674
11472
|
var VersionArchive = class {
|
|
11675
11473
|
history = {};
|
|
@@ -11716,7 +11514,7 @@ var VersionArchive = class {
|
|
|
11716
11514
|
}
|
|
11717
11515
|
save() {
|
|
11718
11516
|
try {
|
|
11719
|
-
fs8.mkdirSync(
|
|
11517
|
+
fs8.mkdirSync(path11.dirname(ARCHIVE_PATH), { recursive: true });
|
|
11720
11518
|
fs8.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
11721
11519
|
} catch {
|
|
11722
11520
|
}
|
|
@@ -11757,7 +11555,7 @@ function checkPathExists2(paths) {
|
|
|
11757
11555
|
for (const p of paths) {
|
|
11758
11556
|
if (p.includes("*")) {
|
|
11759
11557
|
const home = os14.homedir();
|
|
11760
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
11558
|
+
const resolved = p.replace(/\*/g, home.split(path11.sep).pop() || "");
|
|
11761
11559
|
if (fs8.existsSync(resolved)) return resolved;
|
|
11762
11560
|
} else {
|
|
11763
11561
|
if (fs8.existsSync(p)) return p;
|
|
@@ -11767,7 +11565,7 @@ function checkPathExists2(paths) {
|
|
|
11767
11565
|
}
|
|
11768
11566
|
function getMacAppVersion(appPath) {
|
|
11769
11567
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
11770
|
-
const plistPath =
|
|
11568
|
+
const plistPath = path11.join(appPath, "Contents", "Info.plist");
|
|
11771
11569
|
if (!fs8.existsSync(plistPath)) return null;
|
|
11772
11570
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
11773
11571
|
return raw || null;
|
|
@@ -11794,7 +11592,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
11794
11592
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
11795
11593
|
let resolvedBin = cliBin;
|
|
11796
11594
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
11797
|
-
const bundled =
|
|
11595
|
+
const bundled = path11.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
11798
11596
|
if (provider.cli && fs8.existsSync(bundled)) resolvedBin = bundled;
|
|
11799
11597
|
}
|
|
11800
11598
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -11835,7 +11633,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
11835
11633
|
// src/daemon/dev-server.ts
|
|
11836
11634
|
import * as http2 from "http";
|
|
11837
11635
|
import * as fs11 from "fs";
|
|
11838
|
-
import * as
|
|
11636
|
+
import * as path14 from "path";
|
|
11839
11637
|
|
|
11840
11638
|
// src/daemon/scaffold-template.ts
|
|
11841
11639
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -12172,7 +11970,7 @@ init_logger();
|
|
|
12172
11970
|
// src/daemon/dev-cdp-handlers.ts
|
|
12173
11971
|
init_logger();
|
|
12174
11972
|
import * as fs9 from "fs";
|
|
12175
|
-
import * as
|
|
11973
|
+
import * as path12 from "path";
|
|
12176
11974
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
12177
11975
|
const body = await ctx.readBody(req);
|
|
12178
11976
|
const { expression, timeout, ideType } = body;
|
|
@@ -12350,17 +12148,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
12350
12148
|
return;
|
|
12351
12149
|
}
|
|
12352
12150
|
let scriptsPath = "";
|
|
12353
|
-
const directScripts =
|
|
12151
|
+
const directScripts = path12.join(dir, "scripts.js");
|
|
12354
12152
|
if (fs9.existsSync(directScripts)) {
|
|
12355
12153
|
scriptsPath = directScripts;
|
|
12356
12154
|
} else {
|
|
12357
|
-
const scriptsDir =
|
|
12155
|
+
const scriptsDir = path12.join(dir, "scripts");
|
|
12358
12156
|
if (fs9.existsSync(scriptsDir)) {
|
|
12359
12157
|
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
12360
|
-
return fs9.statSync(
|
|
12158
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
12361
12159
|
}).sort().reverse();
|
|
12362
12160
|
for (const ver of versions) {
|
|
12363
|
-
const p =
|
|
12161
|
+
const p = path12.join(scriptsDir, ver, "scripts.js");
|
|
12364
12162
|
if (fs9.existsSync(p)) {
|
|
12365
12163
|
scriptsPath = p;
|
|
12366
12164
|
break;
|
|
@@ -13415,7 +13213,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
13415
13213
|
|
|
13416
13214
|
// src/daemon/dev-auto-implement.ts
|
|
13417
13215
|
import * as fs10 from "fs";
|
|
13418
|
-
import * as
|
|
13216
|
+
import * as path13 from "path";
|
|
13419
13217
|
import * as os15 from "os";
|
|
13420
13218
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
13421
13219
|
if (category === "cli") {
|
|
@@ -13435,22 +13233,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
13435
13233
|
if (!fs10.existsSync(scriptsDir)) return null;
|
|
13436
13234
|
const versions = fs10.readdirSync(scriptsDir).filter((d) => {
|
|
13437
13235
|
try {
|
|
13438
|
-
return fs10.statSync(
|
|
13236
|
+
return fs10.statSync(path13.join(scriptsDir, d)).isDirectory();
|
|
13439
13237
|
} catch {
|
|
13440
13238
|
return false;
|
|
13441
13239
|
}
|
|
13442
13240
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
13443
13241
|
if (versions.length === 0) return null;
|
|
13444
|
-
return
|
|
13242
|
+
return path13.join(scriptsDir, versions[0]);
|
|
13445
13243
|
}
|
|
13446
13244
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
13447
|
-
const canonicalUserDir =
|
|
13448
|
-
const desiredDir = requestedDir ?
|
|
13449
|
-
const upstreamRoot =
|
|
13450
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
13245
|
+
const canonicalUserDir = path13.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
13246
|
+
const desiredDir = requestedDir ? path13.resolve(requestedDir) : canonicalUserDir;
|
|
13247
|
+
const upstreamRoot = path13.resolve(ctx.providerLoader.getUpstreamDir());
|
|
13248
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path13.sep}`)) {
|
|
13451
13249
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
13452
13250
|
}
|
|
13453
|
-
if (
|
|
13251
|
+
if (path13.basename(desiredDir) !== type) {
|
|
13454
13252
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
13455
13253
|
}
|
|
13456
13254
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -13458,11 +13256,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
13458
13256
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
13459
13257
|
}
|
|
13460
13258
|
if (!fs10.existsSync(desiredDir)) {
|
|
13461
|
-
fs10.mkdirSync(
|
|
13259
|
+
fs10.mkdirSync(path13.dirname(desiredDir), { recursive: true });
|
|
13462
13260
|
fs10.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
13463
13261
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
13464
13262
|
}
|
|
13465
|
-
const providerJson =
|
|
13263
|
+
const providerJson = path13.join(desiredDir, "provider.json");
|
|
13466
13264
|
if (!fs10.existsSync(providerJson)) {
|
|
13467
13265
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
13468
13266
|
}
|
|
@@ -13485,13 +13283,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
13485
13283
|
const refDir = ctx.findProviderDir(referenceType);
|
|
13486
13284
|
if (!refDir || !fs10.existsSync(refDir)) return {};
|
|
13487
13285
|
const referenceScripts = {};
|
|
13488
|
-
const scriptsDir =
|
|
13286
|
+
const scriptsDir = path13.join(refDir, "scripts");
|
|
13489
13287
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
13490
13288
|
if (!latestDir) return referenceScripts;
|
|
13491
13289
|
for (const file of fs10.readdirSync(latestDir)) {
|
|
13492
13290
|
if (!file.endsWith(".js")) continue;
|
|
13493
13291
|
try {
|
|
13494
|
-
referenceScripts[file] = fs10.readFileSync(
|
|
13292
|
+
referenceScripts[file] = fs10.readFileSync(path13.join(latestDir, file), "utf-8");
|
|
13495
13293
|
} catch {
|
|
13496
13294
|
}
|
|
13497
13295
|
}
|
|
@@ -13542,9 +13340,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
13542
13340
|
});
|
|
13543
13341
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
13544
13342
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
13545
|
-
const tmpDir =
|
|
13343
|
+
const tmpDir = path13.join(os15.tmpdir(), "adhdev-autoimpl");
|
|
13546
13344
|
if (!fs10.existsSync(tmpDir)) fs10.mkdirSync(tmpDir, { recursive: true });
|
|
13547
|
-
const promptFile =
|
|
13345
|
+
const promptFile = path13.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
13548
13346
|
fs10.writeFileSync(promptFile, prompt, "utf-8");
|
|
13549
13347
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
13550
13348
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -13915,7 +13713,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13915
13713
|
setMode: "set_mode.js"
|
|
13916
13714
|
};
|
|
13917
13715
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
13918
|
-
const scriptsDir =
|
|
13716
|
+
const scriptsDir = path13.join(providerDir, "scripts");
|
|
13919
13717
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
13920
13718
|
if (latestScriptsDir) {
|
|
13921
13719
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -13926,7 +13724,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13926
13724
|
for (const file of fs10.readdirSync(latestScriptsDir)) {
|
|
13927
13725
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
13928
13726
|
try {
|
|
13929
|
-
const content = fs10.readFileSync(
|
|
13727
|
+
const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
|
|
13930
13728
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
13931
13729
|
lines.push("```javascript");
|
|
13932
13730
|
lines.push(content);
|
|
@@ -13943,7 +13741,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13943
13741
|
lines.push("");
|
|
13944
13742
|
for (const file of refFiles) {
|
|
13945
13743
|
try {
|
|
13946
|
-
const content = fs10.readFileSync(
|
|
13744
|
+
const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
|
|
13947
13745
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
13948
13746
|
lines.push("```javascript");
|
|
13949
13747
|
lines.push(content);
|
|
@@ -13984,10 +13782,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
13984
13782
|
lines.push("");
|
|
13985
13783
|
}
|
|
13986
13784
|
}
|
|
13987
|
-
const docsDir =
|
|
13785
|
+
const docsDir = path13.join(providerDir, "../../docs");
|
|
13988
13786
|
const loadGuide = (name) => {
|
|
13989
13787
|
try {
|
|
13990
|
-
const p =
|
|
13788
|
+
const p = path13.join(docsDir, name);
|
|
13991
13789
|
if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
|
|
13992
13790
|
} catch {
|
|
13993
13791
|
}
|
|
@@ -14161,7 +13959,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14161
13959
|
parseApproval: "parse_approval.js"
|
|
14162
13960
|
};
|
|
14163
13961
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
14164
|
-
const scriptsDir =
|
|
13962
|
+
const scriptsDir = path13.join(providerDir, "scripts");
|
|
14165
13963
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
14166
13964
|
if (latestScriptsDir) {
|
|
14167
13965
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -14173,7 +13971,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14173
13971
|
if (!file.endsWith(".js")) continue;
|
|
14174
13972
|
if (!targetFileNames.has(file)) continue;
|
|
14175
13973
|
try {
|
|
14176
|
-
const content = fs10.readFileSync(
|
|
13974
|
+
const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
|
|
14177
13975
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
14178
13976
|
lines.push("```javascript");
|
|
14179
13977
|
lines.push(content);
|
|
@@ -14189,7 +13987,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14189
13987
|
lines.push("");
|
|
14190
13988
|
for (const file of refFiles) {
|
|
14191
13989
|
try {
|
|
14192
|
-
const content = fs10.readFileSync(
|
|
13990
|
+
const content = fs10.readFileSync(path13.join(latestScriptsDir, file), "utf-8");
|
|
14193
13991
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
14194
13992
|
lines.push("```javascript");
|
|
14195
13993
|
lines.push(content);
|
|
@@ -14222,10 +14020,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
14222
14020
|
lines.push("");
|
|
14223
14021
|
}
|
|
14224
14022
|
}
|
|
14225
|
-
const docsDir =
|
|
14023
|
+
const docsDir = path13.join(providerDir, "../../docs");
|
|
14226
14024
|
const loadGuide = (name) => {
|
|
14227
14025
|
try {
|
|
14228
|
-
const p =
|
|
14026
|
+
const p = path13.join(docsDir, name);
|
|
14229
14027
|
if (fs10.existsSync(p)) return fs10.readFileSync(p, "utf-8");
|
|
14230
14028
|
} catch {
|
|
14231
14029
|
}
|
|
@@ -14483,8 +14281,8 @@ var DevServer = class _DevServer {
|
|
|
14483
14281
|
}
|
|
14484
14282
|
getEndpointList() {
|
|
14485
14283
|
return this.routes.map((r) => {
|
|
14486
|
-
const
|
|
14487
|
-
return `${r.method.padEnd(5)} ${
|
|
14284
|
+
const path15 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
14285
|
+
return `${r.method.padEnd(5)} ${path15}`;
|
|
14488
14286
|
});
|
|
14489
14287
|
}
|
|
14490
14288
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -14515,15 +14313,15 @@ var DevServer = class _DevServer {
|
|
|
14515
14313
|
this.json(res, 500, { error: e.message });
|
|
14516
14314
|
}
|
|
14517
14315
|
});
|
|
14518
|
-
return new Promise((
|
|
14316
|
+
return new Promise((resolve9, reject) => {
|
|
14519
14317
|
this.server.listen(port, "127.0.0.1", () => {
|
|
14520
14318
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
14521
|
-
|
|
14319
|
+
resolve9();
|
|
14522
14320
|
});
|
|
14523
14321
|
this.server.on("error", (e) => {
|
|
14524
14322
|
if (e.code === "EADDRINUSE") {
|
|
14525
14323
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
14526
|
-
|
|
14324
|
+
resolve9();
|
|
14527
14325
|
} else {
|
|
14528
14326
|
reject(e);
|
|
14529
14327
|
}
|
|
@@ -14606,20 +14404,20 @@ var DevServer = class _DevServer {
|
|
|
14606
14404
|
child.stderr?.on("data", (d) => {
|
|
14607
14405
|
stderr += d.toString().slice(0, 2e3);
|
|
14608
14406
|
});
|
|
14609
|
-
await new Promise((
|
|
14407
|
+
await new Promise((resolve9) => {
|
|
14610
14408
|
const timer = setTimeout(() => {
|
|
14611
14409
|
child.kill();
|
|
14612
|
-
|
|
14410
|
+
resolve9();
|
|
14613
14411
|
}, 3e3);
|
|
14614
14412
|
child.on("exit", () => {
|
|
14615
14413
|
clearTimeout(timer);
|
|
14616
|
-
|
|
14414
|
+
resolve9();
|
|
14617
14415
|
});
|
|
14618
14416
|
child.stdout?.once("data", () => {
|
|
14619
14417
|
setTimeout(() => {
|
|
14620
14418
|
child.kill();
|
|
14621
14419
|
clearTimeout(timer);
|
|
14622
|
-
|
|
14420
|
+
resolve9();
|
|
14623
14421
|
}, 500);
|
|
14624
14422
|
});
|
|
14625
14423
|
});
|
|
@@ -14766,12 +14564,12 @@ var DevServer = class _DevServer {
|
|
|
14766
14564
|
// ─── DevConsole SPA ───
|
|
14767
14565
|
getConsoleDistDir() {
|
|
14768
14566
|
const candidates = [
|
|
14769
|
-
|
|
14770
|
-
|
|
14771
|
-
|
|
14567
|
+
path14.resolve(__dirname, "../../web-devconsole/dist"),
|
|
14568
|
+
path14.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
14569
|
+
path14.join(process.cwd(), "packages/web-devconsole/dist")
|
|
14772
14570
|
];
|
|
14773
14571
|
for (const dir of candidates) {
|
|
14774
|
-
if (fs11.existsSync(
|
|
14572
|
+
if (fs11.existsSync(path14.join(dir, "index.html"))) return dir;
|
|
14775
14573
|
}
|
|
14776
14574
|
return null;
|
|
14777
14575
|
}
|
|
@@ -14781,7 +14579,7 @@ var DevServer = class _DevServer {
|
|
|
14781
14579
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
14782
14580
|
return;
|
|
14783
14581
|
}
|
|
14784
|
-
const htmlPath =
|
|
14582
|
+
const htmlPath = path14.join(distDir, "index.html");
|
|
14785
14583
|
try {
|
|
14786
14584
|
const html = fs11.readFileSync(htmlPath, "utf-8");
|
|
14787
14585
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -14806,15 +14604,15 @@ var DevServer = class _DevServer {
|
|
|
14806
14604
|
this.json(res, 404, { error: "Not found" });
|
|
14807
14605
|
return;
|
|
14808
14606
|
}
|
|
14809
|
-
const safePath =
|
|
14810
|
-
const filePath =
|
|
14607
|
+
const safePath = path14.normalize(pathname).replace(/^\.\.\//, "");
|
|
14608
|
+
const filePath = path14.join(distDir, safePath);
|
|
14811
14609
|
if (!filePath.startsWith(distDir)) {
|
|
14812
14610
|
this.json(res, 403, { error: "Forbidden" });
|
|
14813
14611
|
return;
|
|
14814
14612
|
}
|
|
14815
14613
|
try {
|
|
14816
14614
|
const content = fs11.readFileSync(filePath);
|
|
14817
|
-
const ext =
|
|
14615
|
+
const ext = path14.extname(filePath);
|
|
14818
14616
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
14819
14617
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
14820
14618
|
res.end(content);
|
|
@@ -14927,9 +14725,9 @@ var DevServer = class _DevServer {
|
|
|
14927
14725
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
14928
14726
|
if (entry.isDirectory()) {
|
|
14929
14727
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
14930
|
-
scan(
|
|
14728
|
+
scan(path14.join(d, entry.name), rel);
|
|
14931
14729
|
} else {
|
|
14932
|
-
const stat = fs11.statSync(
|
|
14730
|
+
const stat = fs11.statSync(path14.join(d, entry.name));
|
|
14933
14731
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
14934
14732
|
}
|
|
14935
14733
|
}
|
|
@@ -14952,7 +14750,7 @@ var DevServer = class _DevServer {
|
|
|
14952
14750
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
14953
14751
|
return;
|
|
14954
14752
|
}
|
|
14955
|
-
const fullPath =
|
|
14753
|
+
const fullPath = path14.resolve(dir, path14.normalize(filePath));
|
|
14956
14754
|
if (!fullPath.startsWith(dir)) {
|
|
14957
14755
|
this.json(res, 403, { error: "Forbidden" });
|
|
14958
14756
|
return;
|
|
@@ -14977,14 +14775,14 @@ var DevServer = class _DevServer {
|
|
|
14977
14775
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
14978
14776
|
return;
|
|
14979
14777
|
}
|
|
14980
|
-
const fullPath =
|
|
14778
|
+
const fullPath = path14.resolve(dir, path14.normalize(filePath));
|
|
14981
14779
|
if (!fullPath.startsWith(dir)) {
|
|
14982
14780
|
this.json(res, 403, { error: "Forbidden" });
|
|
14983
14781
|
return;
|
|
14984
14782
|
}
|
|
14985
14783
|
try {
|
|
14986
14784
|
if (fs11.existsSync(fullPath)) fs11.copyFileSync(fullPath, fullPath + ".bak");
|
|
14987
|
-
fs11.mkdirSync(
|
|
14785
|
+
fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
|
|
14988
14786
|
fs11.writeFileSync(fullPath, content, "utf-8");
|
|
14989
14787
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
14990
14788
|
this.providerLoader.reload();
|
|
@@ -15001,7 +14799,7 @@ var DevServer = class _DevServer {
|
|
|
15001
14799
|
return;
|
|
15002
14800
|
}
|
|
15003
14801
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
15004
|
-
const p =
|
|
14802
|
+
const p = path14.join(dir, name);
|
|
15005
14803
|
if (fs11.existsSync(p)) {
|
|
15006
14804
|
const source = fs11.readFileSync(p, "utf-8");
|
|
15007
14805
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -15022,8 +14820,8 @@ var DevServer = class _DevServer {
|
|
|
15022
14820
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
15023
14821
|
return;
|
|
15024
14822
|
}
|
|
15025
|
-
const target = fs11.existsSync(
|
|
15026
|
-
const targetPath =
|
|
14823
|
+
const target = fs11.existsSync(path14.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
14824
|
+
const targetPath = path14.join(dir, target);
|
|
15027
14825
|
try {
|
|
15028
14826
|
if (fs11.existsSync(targetPath)) fs11.copyFileSync(targetPath, targetPath + ".bak");
|
|
15029
14827
|
fs11.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -15128,14 +14926,14 @@ var DevServer = class _DevServer {
|
|
|
15128
14926
|
child.stderr?.on("data", (d) => {
|
|
15129
14927
|
stderr += d.toString();
|
|
15130
14928
|
});
|
|
15131
|
-
await new Promise((
|
|
14929
|
+
await new Promise((resolve9) => {
|
|
15132
14930
|
const timer = setTimeout(() => {
|
|
15133
14931
|
child.kill();
|
|
15134
|
-
|
|
14932
|
+
resolve9();
|
|
15135
14933
|
}, timeout);
|
|
15136
14934
|
child.on("exit", () => {
|
|
15137
14935
|
clearTimeout(timer);
|
|
15138
|
-
|
|
14936
|
+
resolve9();
|
|
15139
14937
|
});
|
|
15140
14938
|
});
|
|
15141
14939
|
const elapsed = Date.now() - start;
|
|
@@ -15183,7 +14981,7 @@ var DevServer = class _DevServer {
|
|
|
15183
14981
|
}
|
|
15184
14982
|
let targetDir;
|
|
15185
14983
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
15186
|
-
const jsonPath =
|
|
14984
|
+
const jsonPath = path14.join(targetDir, "provider.json");
|
|
15187
14985
|
if (fs11.existsSync(jsonPath)) {
|
|
15188
14986
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
15189
14987
|
return;
|
|
@@ -15195,8 +14993,8 @@ var DevServer = class _DevServer {
|
|
|
15195
14993
|
const createdFiles = ["provider.json"];
|
|
15196
14994
|
if (result.files) {
|
|
15197
14995
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
15198
|
-
const fullPath =
|
|
15199
|
-
fs11.mkdirSync(
|
|
14996
|
+
const fullPath = path14.join(targetDir, relPath);
|
|
14997
|
+
fs11.mkdirSync(path14.dirname(fullPath), { recursive: true });
|
|
15200
14998
|
fs11.writeFileSync(fullPath, content, "utf-8");
|
|
15201
14999
|
createdFiles.push(relPath);
|
|
15202
15000
|
}
|
|
@@ -15249,22 +15047,22 @@ var DevServer = class _DevServer {
|
|
|
15249
15047
|
if (!fs11.existsSync(scriptsDir)) return null;
|
|
15250
15048
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
15251
15049
|
try {
|
|
15252
|
-
return fs11.statSync(
|
|
15050
|
+
return fs11.statSync(path14.join(scriptsDir, d)).isDirectory();
|
|
15253
15051
|
} catch {
|
|
15254
15052
|
return false;
|
|
15255
15053
|
}
|
|
15256
15054
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
15257
15055
|
if (versions.length === 0) return null;
|
|
15258
|
-
return
|
|
15056
|
+
return path14.join(scriptsDir, versions[0]);
|
|
15259
15057
|
}
|
|
15260
15058
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
15261
|
-
const canonicalUserDir =
|
|
15262
|
-
const desiredDir = requestedDir ?
|
|
15263
|
-
const upstreamRoot =
|
|
15264
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
15059
|
+
const canonicalUserDir = path14.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
15060
|
+
const desiredDir = requestedDir ? path14.resolve(requestedDir) : canonicalUserDir;
|
|
15061
|
+
const upstreamRoot = path14.resolve(this.providerLoader.getUpstreamDir());
|
|
15062
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path14.sep}`)) {
|
|
15265
15063
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
15266
15064
|
}
|
|
15267
|
-
if (
|
|
15065
|
+
if (path14.basename(desiredDir) !== type) {
|
|
15268
15066
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
15269
15067
|
}
|
|
15270
15068
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -15272,11 +15070,11 @@ var DevServer = class _DevServer {
|
|
|
15272
15070
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
15273
15071
|
}
|
|
15274
15072
|
if (!fs11.existsSync(desiredDir)) {
|
|
15275
|
-
fs11.mkdirSync(
|
|
15073
|
+
fs11.mkdirSync(path14.dirname(desiredDir), { recursive: true });
|
|
15276
15074
|
fs11.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
15277
15075
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
15278
15076
|
}
|
|
15279
|
-
const providerJson =
|
|
15077
|
+
const providerJson = path14.join(desiredDir, "provider.json");
|
|
15280
15078
|
if (!fs11.existsSync(providerJson)) {
|
|
15281
15079
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
15282
15080
|
}
|
|
@@ -15324,7 +15122,7 @@ var DevServer = class _DevServer {
|
|
|
15324
15122
|
setMode: "set_mode.js"
|
|
15325
15123
|
};
|
|
15326
15124
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15327
|
-
const scriptsDir =
|
|
15125
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
15328
15126
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15329
15127
|
if (latestScriptsDir) {
|
|
15330
15128
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15335,7 +15133,7 @@ var DevServer = class _DevServer {
|
|
|
15335
15133
|
for (const file of fs11.readdirSync(latestScriptsDir)) {
|
|
15336
15134
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
15337
15135
|
try {
|
|
15338
|
-
const content = fs11.readFileSync(
|
|
15136
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
15339
15137
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15340
15138
|
lines.push("```javascript");
|
|
15341
15139
|
lines.push(content);
|
|
@@ -15352,7 +15150,7 @@ var DevServer = class _DevServer {
|
|
|
15352
15150
|
lines.push("");
|
|
15353
15151
|
for (const file of refFiles) {
|
|
15354
15152
|
try {
|
|
15355
|
-
const content = fs11.readFileSync(
|
|
15153
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
15356
15154
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15357
15155
|
lines.push("```javascript");
|
|
15358
15156
|
lines.push(content);
|
|
@@ -15393,10 +15191,10 @@ var DevServer = class _DevServer {
|
|
|
15393
15191
|
lines.push("");
|
|
15394
15192
|
}
|
|
15395
15193
|
}
|
|
15396
|
-
const docsDir =
|
|
15194
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
15397
15195
|
const loadGuide = (name) => {
|
|
15398
15196
|
try {
|
|
15399
|
-
const p =
|
|
15197
|
+
const p = path14.join(docsDir, name);
|
|
15400
15198
|
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
15401
15199
|
} catch {
|
|
15402
15200
|
}
|
|
@@ -15570,7 +15368,7 @@ var DevServer = class _DevServer {
|
|
|
15570
15368
|
parseApproval: "parse_approval.js"
|
|
15571
15369
|
};
|
|
15572
15370
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
15573
|
-
const scriptsDir =
|
|
15371
|
+
const scriptsDir = path14.join(providerDir, "scripts");
|
|
15574
15372
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
15575
15373
|
if (latestScriptsDir) {
|
|
15576
15374
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -15582,7 +15380,7 @@ var DevServer = class _DevServer {
|
|
|
15582
15380
|
if (!file.endsWith(".js")) continue;
|
|
15583
15381
|
if (!targetFileNames.has(file)) continue;
|
|
15584
15382
|
try {
|
|
15585
|
-
const content = fs11.readFileSync(
|
|
15383
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
15586
15384
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
15587
15385
|
lines.push("```javascript");
|
|
15588
15386
|
lines.push(content);
|
|
@@ -15598,7 +15396,7 @@ var DevServer = class _DevServer {
|
|
|
15598
15396
|
lines.push("");
|
|
15599
15397
|
for (const file of refFiles) {
|
|
15600
15398
|
try {
|
|
15601
|
-
const content = fs11.readFileSync(
|
|
15399
|
+
const content = fs11.readFileSync(path14.join(latestScriptsDir, file), "utf-8");
|
|
15602
15400
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
15603
15401
|
lines.push("```javascript");
|
|
15604
15402
|
lines.push(content);
|
|
@@ -15631,10 +15429,10 @@ var DevServer = class _DevServer {
|
|
|
15631
15429
|
lines.push("");
|
|
15632
15430
|
}
|
|
15633
15431
|
}
|
|
15634
|
-
const docsDir =
|
|
15432
|
+
const docsDir = path14.join(providerDir, "../../docs");
|
|
15635
15433
|
const loadGuide = (name) => {
|
|
15636
15434
|
try {
|
|
15637
|
-
const p =
|
|
15435
|
+
const p = path14.join(docsDir, name);
|
|
15638
15436
|
if (fs11.existsSync(p)) return fs11.readFileSync(p, "utf-8");
|
|
15639
15437
|
} catch {
|
|
15640
15438
|
}
|
|
@@ -15791,14 +15589,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
15791
15589
|
res.end(JSON.stringify(data, null, 2));
|
|
15792
15590
|
}
|
|
15793
15591
|
async readBody(req) {
|
|
15794
|
-
return new Promise((
|
|
15592
|
+
return new Promise((resolve9) => {
|
|
15795
15593
|
let body = "";
|
|
15796
15594
|
req.on("data", (chunk) => body += chunk);
|
|
15797
15595
|
req.on("end", () => {
|
|
15798
15596
|
try {
|
|
15799
|
-
|
|
15597
|
+
resolve9(JSON.parse(body));
|
|
15800
15598
|
} catch {
|
|
15801
|
-
|
|
15599
|
+
resolve9({});
|
|
15802
15600
|
}
|
|
15803
15601
|
});
|
|
15804
15602
|
});
|
|
@@ -16220,7 +16018,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
16220
16018
|
const deadline = Date.now() + timeoutMs;
|
|
16221
16019
|
while (Date.now() < deadline) {
|
|
16222
16020
|
if (await canConnect(endpoint)) return;
|
|
16223
|
-
await new Promise((
|
|
16021
|
+
await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
|
|
16224
16022
|
}
|
|
16225
16023
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
16226
16024
|
}
|
|
@@ -16375,10 +16173,10 @@ async function installExtension(ide, extension) {
|
|
|
16375
16173
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
16376
16174
|
const fs12 = await import("fs");
|
|
16377
16175
|
fs12.writeFileSync(vsixPath, buffer);
|
|
16378
|
-
return new Promise((
|
|
16176
|
+
return new Promise((resolve9) => {
|
|
16379
16177
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
16380
16178
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
16381
|
-
|
|
16179
|
+
resolve9({
|
|
16382
16180
|
extensionId: extension.id,
|
|
16383
16181
|
marketplaceId: extension.marketplaceId,
|
|
16384
16182
|
success: !error,
|
|
@@ -16391,11 +16189,11 @@ async function installExtension(ide, extension) {
|
|
|
16391
16189
|
} catch (e) {
|
|
16392
16190
|
}
|
|
16393
16191
|
}
|
|
16394
|
-
return new Promise((
|
|
16192
|
+
return new Promise((resolve9) => {
|
|
16395
16193
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
16396
16194
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
16397
16195
|
if (error) {
|
|
16398
|
-
|
|
16196
|
+
resolve9({
|
|
16399
16197
|
extensionId: extension.id,
|
|
16400
16198
|
marketplaceId: extension.marketplaceId,
|
|
16401
16199
|
success: false,
|
|
@@ -16403,7 +16201,7 @@ async function installExtension(ide, extension) {
|
|
|
16403
16201
|
error: stderr || error.message
|
|
16404
16202
|
});
|
|
16405
16203
|
} else {
|
|
16406
|
-
|
|
16204
|
+
resolve9({
|
|
16407
16205
|
extensionId: extension.id,
|
|
16408
16206
|
marketplaceId: extension.marketplaceId,
|
|
16409
16207
|
success: true,
|
|
@@ -16706,7 +16504,6 @@ export {
|
|
|
16706
16504
|
ProviderLoader,
|
|
16707
16505
|
SessionHostPtyTransportFactory,
|
|
16708
16506
|
VersionArchive,
|
|
16709
|
-
addCliHistory,
|
|
16710
16507
|
appendRecentActivity,
|
|
16711
16508
|
buildSessionEntries,
|
|
16712
16509
|
buildStatusSnapshot,
|
|
@@ -16724,7 +16521,6 @@ export {
|
|
|
16724
16521
|
getRecentActivity,
|
|
16725
16522
|
getRecentCommands,
|
|
16726
16523
|
getRecentLogs,
|
|
16727
|
-
getWorkspaceActivity,
|
|
16728
16524
|
getWorkspaceState,
|
|
16729
16525
|
hasCdpManager,
|
|
16730
16526
|
initDaemonComponents,
|