@adhdev/daemon-core 0.8.27 → 0.8.28
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/commands/handler.d.ts +1 -0
- package/dist/commands/stream-commands.d.ts +1 -1
- package/dist/detection/cli-detector.d.ts +6 -2
- package/dist/detection/ide-detector.d.ts +2 -1
- package/dist/index.js +603 -355
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +601 -353
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +1 -1
- package/dist/providers/provider-loader.d.ts +26 -0
- package/dist/shared-types.d.ts +2 -0
- package/dist/status/snapshot.d.ts +8 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/provider-adapter.ts +15 -2
- package/src/boot/daemon-lifecycle.ts +28 -1
- package/src/cli-adapters/provider-cli-adapter.ts +14 -3
- package/src/commands/chat-commands.ts +36 -7
- package/src/commands/cli-manager.ts +2 -2
- package/src/commands/handler.ts +1 -0
- package/src/commands/router.ts +12 -1
- package/src/commands/stream-commands.ts +6 -3
- package/src/detection/cli-detector.ts +72 -29
- package/src/detection/ide-detector.ts +24 -8
- package/src/launch.ts +1 -1
- package/src/providers/acp-provider-instance.ts +19 -10
- package/src/providers/provider-loader.ts +144 -11
- package/src/shared-types.ts +2 -0
- package/src/status/snapshot.ts +19 -1
package/dist/index.mjs
CHANGED
|
@@ -233,7 +233,7 @@ var init_config = __esm({
|
|
|
233
233
|
|
|
234
234
|
// src/logging/logger.ts
|
|
235
235
|
import * as fs2 from "fs";
|
|
236
|
-
import * as
|
|
236
|
+
import * as path6 from "path";
|
|
237
237
|
import * as os4 from "os";
|
|
238
238
|
function setLogLevel(level) {
|
|
239
239
|
currentLevel = level;
|
|
@@ -249,13 +249,13 @@ function getDaemonLogDir() {
|
|
|
249
249
|
return LOG_DIR;
|
|
250
250
|
}
|
|
251
251
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
252
|
-
return
|
|
252
|
+
return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
253
253
|
}
|
|
254
254
|
function checkDateRotation() {
|
|
255
255
|
const today = getDateStr();
|
|
256
256
|
if (today !== currentDate) {
|
|
257
257
|
currentDate = today;
|
|
258
|
-
currentLogFile =
|
|
258
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
259
259
|
cleanOldLogs();
|
|
260
260
|
}
|
|
261
261
|
}
|
|
@@ -269,7 +269,7 @@ function cleanOldLogs() {
|
|
|
269
269
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
270
270
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
271
271
|
try {
|
|
272
|
-
fs2.unlinkSync(
|
|
272
|
+
fs2.unlinkSync(path6.join(LOG_DIR, file));
|
|
273
273
|
} catch {
|
|
274
274
|
}
|
|
275
275
|
}
|
|
@@ -393,7 +393,7 @@ var init_logger = __esm({
|
|
|
393
393
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
394
394
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
395
395
|
currentLevel = "info";
|
|
396
|
-
LOG_DIR = process.platform === "win32" ?
|
|
396
|
+
LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os4.homedir(), "Library", "Logs", "adhdev") : path6.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
397
397
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
398
398
|
MAX_LOG_DAYS = 7;
|
|
399
399
|
try {
|
|
@@ -401,16 +401,16 @@ var init_logger = __esm({
|
|
|
401
401
|
} catch {
|
|
402
402
|
}
|
|
403
403
|
currentDate = getDateStr();
|
|
404
|
-
currentLogFile =
|
|
404
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
405
405
|
cleanOldLogs();
|
|
406
406
|
try {
|
|
407
|
-
const oldLog =
|
|
407
|
+
const oldLog = path6.join(LOG_DIR, "daemon.log");
|
|
408
408
|
if (fs2.existsSync(oldLog)) {
|
|
409
409
|
const stat = fs2.statSync(oldLog);
|
|
410
410
|
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
411
|
-
fs2.renameSync(oldLog,
|
|
411
|
+
fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
412
412
|
}
|
|
413
|
-
const oldLogBackup =
|
|
413
|
+
const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
|
|
414
414
|
if (fs2.existsSync(oldLogBackup)) {
|
|
415
415
|
fs2.unlinkSync(oldLogBackup);
|
|
416
416
|
}
|
|
@@ -442,7 +442,7 @@ var init_logger = __esm({
|
|
|
442
442
|
}
|
|
443
443
|
};
|
|
444
444
|
interceptorInstalled = false;
|
|
445
|
-
LOG_PATH =
|
|
445
|
+
LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
446
446
|
}
|
|
447
447
|
});
|
|
448
448
|
|
|
@@ -802,7 +802,7 @@ __export(provider_cli_adapter_exports, {
|
|
|
802
802
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
803
803
|
});
|
|
804
804
|
import * as os8 from "os";
|
|
805
|
-
import * as
|
|
805
|
+
import * as path9 from "path";
|
|
806
806
|
import { execSync as execSync3 } from "child_process";
|
|
807
807
|
function stripAnsi(str) {
|
|
808
808
|
return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
|
|
@@ -873,16 +873,22 @@ function computeTerminalQueryTail(buffer) {
|
|
|
873
873
|
return "";
|
|
874
874
|
}
|
|
875
875
|
function findBinary(name) {
|
|
876
|
+
const trimmed = String(name || "").trim();
|
|
877
|
+
if (!trimmed) return trimmed;
|
|
878
|
+
const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
|
|
879
|
+
if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
880
|
+
return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
881
|
+
}
|
|
876
882
|
const isWin = os8.platform() === "win32";
|
|
877
883
|
try {
|
|
878
|
-
const cmd = isWin ? `where ${
|
|
884
|
+
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
879
885
|
return execSync3(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
880
886
|
} catch {
|
|
881
|
-
return isWin ? `${
|
|
887
|
+
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
882
888
|
}
|
|
883
889
|
}
|
|
884
890
|
function isScriptBinary(binaryPath) {
|
|
885
|
-
if (!
|
|
891
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
886
892
|
try {
|
|
887
893
|
const fs15 = __require("fs");
|
|
888
894
|
const resolved = fs15.realpathSync(binaryPath);
|
|
@@ -898,7 +904,7 @@ function isScriptBinary(binaryPath) {
|
|
|
898
904
|
}
|
|
899
905
|
}
|
|
900
906
|
function looksLikeMachOOrElf(filePath) {
|
|
901
|
-
if (!
|
|
907
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
902
908
|
try {
|
|
903
909
|
const fs15 = __require("fs");
|
|
904
910
|
const resolved = fs15.realpathSync(filePath);
|
|
@@ -1379,16 +1385,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
1379
1385
|
async spawn() {
|
|
1380
1386
|
if (this.ptyProcess) return;
|
|
1381
1387
|
const { spawn: spawnConfig } = this.provider;
|
|
1382
|
-
const
|
|
1388
|
+
const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1389
|
+
const binaryPath = findBinary(configuredCommand);
|
|
1383
1390
|
const isWin = os8.platform() === "win32";
|
|
1384
1391
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
1385
1392
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1386
1393
|
this.resetTraceSession();
|
|
1387
1394
|
let shellCmd;
|
|
1388
1395
|
let shellArgs;
|
|
1389
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1396
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1390
1397
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1391
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
1398
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1392
1399
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1393
1400
|
if (useShell) {
|
|
1394
1401
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -1762,7 +1769,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1762
1769
|
`[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(this.summarizeTraceText(screenText, 220)).slice(0, 260)}`
|
|
1763
1770
|
);
|
|
1764
1771
|
}
|
|
1765
|
-
await new Promise((
|
|
1772
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
1766
1773
|
}
|
|
1767
1774
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1768
1775
|
LOG.warn(
|
|
@@ -2273,7 +2280,7 @@ ${data.message || ""}`.trim();
|
|
|
2273
2280
|
const deadline = Date.now() + 1e4;
|
|
2274
2281
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
2275
2282
|
this.resolveStartupState("send_wait");
|
|
2276
|
-
await new Promise((
|
|
2283
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
2277
2284
|
}
|
|
2278
2285
|
}
|
|
2279
2286
|
await this.waitForInteractivePrompt();
|
|
@@ -2498,17 +2505,17 @@ ${data.message || ""}`.trim();
|
|
|
2498
2505
|
}
|
|
2499
2506
|
}
|
|
2500
2507
|
waitForStopped(timeoutMs) {
|
|
2501
|
-
return new Promise((
|
|
2508
|
+
return new Promise((resolve12) => {
|
|
2502
2509
|
const startedAt = Date.now();
|
|
2503
2510
|
const timer = setInterval(() => {
|
|
2504
2511
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
2505
2512
|
clearInterval(timer);
|
|
2506
|
-
|
|
2513
|
+
resolve12(true);
|
|
2507
2514
|
return;
|
|
2508
2515
|
}
|
|
2509
2516
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
2510
2517
|
clearInterval(timer);
|
|
2511
|
-
|
|
2518
|
+
resolve12(false);
|
|
2512
2519
|
}
|
|
2513
2520
|
}, 100);
|
|
2514
2521
|
});
|
|
@@ -3124,6 +3131,7 @@ function resetState() {
|
|
|
3124
3131
|
import { execSync } from "child_process";
|
|
3125
3132
|
import { existsSync as existsSync4 } from "fs";
|
|
3126
3133
|
import { platform, homedir as homedir3 } from "os";
|
|
3134
|
+
import * as path4 from "path";
|
|
3127
3135
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
3128
3136
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
3129
3137
|
function registerIDEDefinition(def) {
|
|
@@ -3140,9 +3148,16 @@ function getMergedDefinitions() {
|
|
|
3140
3148
|
return [...merged.values()];
|
|
3141
3149
|
}
|
|
3142
3150
|
function findCliCommand(command) {
|
|
3151
|
+
const trimmed = String(command || "").trim();
|
|
3152
|
+
if (!trimmed) return null;
|
|
3153
|
+
if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
3154
|
+
const candidate = trimmed.startsWith("~") ? path4.join(homedir3(), trimmed.slice(1)) : trimmed;
|
|
3155
|
+
const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
|
|
3156
|
+
return existsSync4(resolved) ? resolved : null;
|
|
3157
|
+
}
|
|
3143
3158
|
try {
|
|
3144
3159
|
const result = execSync(
|
|
3145
|
-
platform() === "win32" ? `where ${
|
|
3160
|
+
platform() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
3146
3161
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
3147
3162
|
).trim();
|
|
3148
3163
|
return result.split("\n")[0] || null;
|
|
@@ -3165,23 +3180,23 @@ function getIdeVersion(cliCommand) {
|
|
|
3165
3180
|
function checkPathExists(paths) {
|
|
3166
3181
|
const home = homedir3();
|
|
3167
3182
|
for (const p of paths) {
|
|
3168
|
-
|
|
3183
|
+
const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
|
|
3184
|
+
if (normalized.includes("*")) {
|
|
3169
3185
|
const username = home.split(/[\\/]/).pop() || "";
|
|
3170
|
-
const resolved =
|
|
3186
|
+
const resolved = normalized.replace("*", username);
|
|
3171
3187
|
if (existsSync4(resolved)) return resolved;
|
|
3172
3188
|
} else {
|
|
3173
|
-
if (existsSync4(
|
|
3189
|
+
if (existsSync4(normalized)) return normalized;
|
|
3174
3190
|
}
|
|
3175
3191
|
}
|
|
3176
3192
|
return null;
|
|
3177
3193
|
}
|
|
3178
|
-
async function detectIDEs() {
|
|
3194
|
+
async function detectIDEs(providerLoader) {
|
|
3179
3195
|
const os18 = platform();
|
|
3180
3196
|
const results = [];
|
|
3181
3197
|
for (const def of getMergedDefinitions()) {
|
|
3182
|
-
const cliPath = findCliCommand(def.cli);
|
|
3183
|
-
const appPath = checkPathExists(def.paths[os18] || []);
|
|
3184
|
-
const installed = !!(cliPath || appPath);
|
|
3198
|
+
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
3199
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
|
|
3185
3200
|
let resolvedCli = cliPath;
|
|
3186
3201
|
if (!resolvedCli && appPath && os18 === "darwin") {
|
|
3187
3202
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
@@ -3204,6 +3219,7 @@ async function detectIDEs() {
|
|
|
3204
3219
|
}
|
|
3205
3220
|
}
|
|
3206
3221
|
}
|
|
3222
|
+
const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
3207
3223
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
3208
3224
|
results.push({
|
|
3209
3225
|
id: def.id,
|
|
@@ -3222,48 +3238,77 @@ async function detectIDEs() {
|
|
|
3222
3238
|
// src/detection/cli-detector.ts
|
|
3223
3239
|
import { exec } from "child_process";
|
|
3224
3240
|
import * as os2 from "os";
|
|
3241
|
+
import * as path5 from "path";
|
|
3242
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3225
3243
|
function parseVersion(raw) {
|
|
3226
3244
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
3227
3245
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
3228
3246
|
}
|
|
3247
|
+
function shellQuote(value) {
|
|
3248
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
3249
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
3250
|
+
}
|
|
3251
|
+
function expandHome(value) {
|
|
3252
|
+
const trimmed = value.trim();
|
|
3253
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
3254
|
+
return path5.join(os2.homedir(), trimmed.slice(1));
|
|
3255
|
+
}
|
|
3256
|
+
function isExplicitCommandPath(command) {
|
|
3257
|
+
const trimmed = command.trim();
|
|
3258
|
+
return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
3259
|
+
}
|
|
3260
|
+
function resolveCommandPath(command) {
|
|
3261
|
+
const trimmed = command.trim();
|
|
3262
|
+
if (!trimmed) return null;
|
|
3263
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
3264
|
+
const expanded = expandHome(trimmed);
|
|
3265
|
+
const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
|
|
3266
|
+
return existsSync5(candidate) ? candidate : null;
|
|
3267
|
+
}
|
|
3268
|
+
return null;
|
|
3269
|
+
}
|
|
3229
3270
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
3230
|
-
return new Promise((
|
|
3271
|
+
return new Promise((resolve12) => {
|
|
3231
3272
|
const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
3232
3273
|
if (err || !stdout?.trim()) {
|
|
3233
|
-
|
|
3274
|
+
resolve12(null);
|
|
3234
3275
|
} else {
|
|
3235
|
-
|
|
3276
|
+
resolve12(stdout.trim());
|
|
3236
3277
|
}
|
|
3237
3278
|
});
|
|
3238
|
-
child.on("error", () =>
|
|
3279
|
+
child.on("error", () => resolve12(null));
|
|
3239
3280
|
});
|
|
3240
3281
|
}
|
|
3241
|
-
async function detectCLIs(providerLoader) {
|
|
3282
|
+
async function detectCLIs(providerLoader, options) {
|
|
3242
3283
|
const platform9 = os2.platform();
|
|
3243
3284
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
3285
|
+
const includeVersion = options?.includeVersion !== false;
|
|
3244
3286
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
3245
3287
|
const results = await Promise.all(
|
|
3246
3288
|
cliList.map(async (cli) => {
|
|
3247
3289
|
try {
|
|
3248
|
-
const
|
|
3290
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
3291
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
3249
3292
|
if (!pathResult) return { ...cli, installed: false };
|
|
3250
|
-
const firstPath = pathResult.split("\n")[0];
|
|
3293
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
3251
3294
|
let version;
|
|
3252
|
-
|
|
3295
|
+
if (includeVersion) {
|
|
3253
3296
|
const versionCommands = [
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3297
|
+
`"${firstPath}" --version`,
|
|
3298
|
+
`"${firstPath}" -V`,
|
|
3299
|
+
`"${firstPath}" -v`,
|
|
3300
|
+
cli.versionCommand
|
|
3258
3301
|
].filter((v) => !!v);
|
|
3259
|
-
|
|
3260
|
-
const
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3302
|
+
try {
|
|
3303
|
+
for (const versionCommand of versionCommands) {
|
|
3304
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
3305
|
+
if (versionResult) {
|
|
3306
|
+
version = parseVersion(versionResult);
|
|
3307
|
+
break;
|
|
3308
|
+
}
|
|
3264
3309
|
}
|
|
3310
|
+
} catch {
|
|
3265
3311
|
}
|
|
3266
|
-
} catch {
|
|
3267
3312
|
}
|
|
3268
3313
|
return { ...cli, installed: true, version, path: firstPath };
|
|
3269
3314
|
} catch {
|
|
@@ -3273,7 +3318,7 @@ async function detectCLIs(providerLoader) {
|
|
|
3273
3318
|
);
|
|
3274
3319
|
return results;
|
|
3275
3320
|
}
|
|
3276
|
-
async function detectCLI(cliId, providerLoader) {
|
|
3321
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
3277
3322
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
3278
3323
|
if (providerLoader) {
|
|
3279
3324
|
const cliList = providerLoader.getCliDetectionList();
|
|
@@ -3282,25 +3327,28 @@ async function detectCLI(cliId, providerLoader) {
|
|
|
3282
3327
|
const platform9 = os2.platform();
|
|
3283
3328
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
3284
3329
|
try {
|
|
3285
|
-
const
|
|
3330
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
3331
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
3286
3332
|
if (!pathResult) return null;
|
|
3287
|
-
const firstPath = pathResult.split("\n")[0];
|
|
3333
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
3288
3334
|
let version;
|
|
3289
|
-
|
|
3335
|
+
if (options?.includeVersion !== false) {
|
|
3290
3336
|
const versionCommands = [
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3337
|
+
`"${firstPath}" --version`,
|
|
3338
|
+
`"${firstPath}" -V`,
|
|
3339
|
+
`"${firstPath}" -v`,
|
|
3340
|
+
target.versionCommand
|
|
3295
3341
|
].filter((v) => !!v);
|
|
3296
|
-
|
|
3297
|
-
const
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3342
|
+
try {
|
|
3343
|
+
for (const versionCommand of versionCommands) {
|
|
3344
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
3345
|
+
if (versionResult) {
|
|
3346
|
+
version = parseVersion(versionResult);
|
|
3347
|
+
break;
|
|
3348
|
+
}
|
|
3301
3349
|
}
|
|
3350
|
+
} catch {
|
|
3302
3351
|
}
|
|
3303
|
-
} catch {
|
|
3304
3352
|
}
|
|
3305
3353
|
return { ...target, installed: true, version, path: firstPath };
|
|
3306
3354
|
} catch {
|
|
@@ -3308,7 +3356,7 @@ async function detectCLI(cliId, providerLoader) {
|
|
|
3308
3356
|
}
|
|
3309
3357
|
}
|
|
3310
3358
|
}
|
|
3311
|
-
const all = await detectCLIs(providerLoader);
|
|
3359
|
+
const all = await detectCLIs(providerLoader, options);
|
|
3312
3360
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
3313
3361
|
}
|
|
3314
3362
|
|
|
@@ -3435,7 +3483,7 @@ var DaemonCdpManager = class {
|
|
|
3435
3483
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
3436
3484
|
*/
|
|
3437
3485
|
static listAllTargets(port) {
|
|
3438
|
-
return new Promise((
|
|
3486
|
+
return new Promise((resolve12) => {
|
|
3439
3487
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
3440
3488
|
let data = "";
|
|
3441
3489
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -3451,16 +3499,16 @@ var DaemonCdpManager = class {
|
|
|
3451
3499
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
3452
3500
|
);
|
|
3453
3501
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
3454
|
-
|
|
3502
|
+
resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
3455
3503
|
} catch {
|
|
3456
|
-
|
|
3504
|
+
resolve12([]);
|
|
3457
3505
|
}
|
|
3458
3506
|
});
|
|
3459
3507
|
});
|
|
3460
|
-
req.on("error", () =>
|
|
3508
|
+
req.on("error", () => resolve12([]));
|
|
3461
3509
|
req.setTimeout(2e3, () => {
|
|
3462
3510
|
req.destroy();
|
|
3463
|
-
|
|
3511
|
+
resolve12([]);
|
|
3464
3512
|
});
|
|
3465
3513
|
});
|
|
3466
3514
|
}
|
|
@@ -3500,7 +3548,7 @@ var DaemonCdpManager = class {
|
|
|
3500
3548
|
}
|
|
3501
3549
|
}
|
|
3502
3550
|
findTargetOnPort(port) {
|
|
3503
|
-
return new Promise((
|
|
3551
|
+
return new Promise((resolve12) => {
|
|
3504
3552
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
3505
3553
|
let data = "";
|
|
3506
3554
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -3511,7 +3559,7 @@ var DaemonCdpManager = class {
|
|
|
3511
3559
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
3512
3560
|
);
|
|
3513
3561
|
if (pages.length === 0) {
|
|
3514
|
-
|
|
3562
|
+
resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
3515
3563
|
return;
|
|
3516
3564
|
}
|
|
3517
3565
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -3521,24 +3569,24 @@ var DaemonCdpManager = class {
|
|
|
3521
3569
|
const specific = list.find((t) => t.id === this._targetId);
|
|
3522
3570
|
if (specific) {
|
|
3523
3571
|
this._pageTitle = specific.title || "";
|
|
3524
|
-
|
|
3572
|
+
resolve12(specific);
|
|
3525
3573
|
} else {
|
|
3526
3574
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
3527
|
-
|
|
3575
|
+
resolve12(null);
|
|
3528
3576
|
}
|
|
3529
3577
|
return;
|
|
3530
3578
|
}
|
|
3531
3579
|
this._pageTitle = list[0]?.title || "";
|
|
3532
|
-
|
|
3580
|
+
resolve12(list[0]);
|
|
3533
3581
|
} catch {
|
|
3534
|
-
|
|
3582
|
+
resolve12(null);
|
|
3535
3583
|
}
|
|
3536
3584
|
});
|
|
3537
3585
|
});
|
|
3538
|
-
req.on("error", () =>
|
|
3586
|
+
req.on("error", () => resolve12(null));
|
|
3539
3587
|
req.setTimeout(2e3, () => {
|
|
3540
3588
|
req.destroy();
|
|
3541
|
-
|
|
3589
|
+
resolve12(null);
|
|
3542
3590
|
});
|
|
3543
3591
|
});
|
|
3544
3592
|
}
|
|
@@ -3549,7 +3597,7 @@ var DaemonCdpManager = class {
|
|
|
3549
3597
|
this.extensionProviders = providers;
|
|
3550
3598
|
}
|
|
3551
3599
|
connectToTarget(wsUrl) {
|
|
3552
|
-
return new Promise((
|
|
3600
|
+
return new Promise((resolve12) => {
|
|
3553
3601
|
this.ws = new WebSocket(wsUrl);
|
|
3554
3602
|
this.ws.on("open", async () => {
|
|
3555
3603
|
this._connected = true;
|
|
@@ -3559,17 +3607,17 @@ var DaemonCdpManager = class {
|
|
|
3559
3607
|
}
|
|
3560
3608
|
this.connectBrowserWs().catch(() => {
|
|
3561
3609
|
});
|
|
3562
|
-
|
|
3610
|
+
resolve12(true);
|
|
3563
3611
|
});
|
|
3564
3612
|
this.ws.on("message", (data) => {
|
|
3565
3613
|
try {
|
|
3566
3614
|
const msg = JSON.parse(data.toString());
|
|
3567
3615
|
if (msg.id && this.pending.has(msg.id)) {
|
|
3568
|
-
const { resolve:
|
|
3616
|
+
const { resolve: resolve13, reject } = this.pending.get(msg.id);
|
|
3569
3617
|
this.pending.delete(msg.id);
|
|
3570
3618
|
this.failureCount = 0;
|
|
3571
3619
|
if (msg.error) reject(new Error(msg.error.message));
|
|
3572
|
-
else
|
|
3620
|
+
else resolve13(msg.result);
|
|
3573
3621
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
3574
3622
|
this.contexts.add(msg.params.context.id);
|
|
3575
3623
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -3592,7 +3640,7 @@ var DaemonCdpManager = class {
|
|
|
3592
3640
|
this.ws.on("error", (err) => {
|
|
3593
3641
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
3594
3642
|
this._connected = false;
|
|
3595
|
-
|
|
3643
|
+
resolve12(false);
|
|
3596
3644
|
});
|
|
3597
3645
|
});
|
|
3598
3646
|
}
|
|
@@ -3606,7 +3654,7 @@ var DaemonCdpManager = class {
|
|
|
3606
3654
|
return;
|
|
3607
3655
|
}
|
|
3608
3656
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
3609
|
-
await new Promise((
|
|
3657
|
+
await new Promise((resolve12, reject) => {
|
|
3610
3658
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
3611
3659
|
this.browserWs.on("open", async () => {
|
|
3612
3660
|
this._browserConnected = true;
|
|
@@ -3616,16 +3664,16 @@ var DaemonCdpManager = class {
|
|
|
3616
3664
|
} catch (e) {
|
|
3617
3665
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
3618
3666
|
}
|
|
3619
|
-
|
|
3667
|
+
resolve12();
|
|
3620
3668
|
});
|
|
3621
3669
|
this.browserWs.on("message", (data) => {
|
|
3622
3670
|
try {
|
|
3623
3671
|
const msg = JSON.parse(data.toString());
|
|
3624
3672
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
3625
|
-
const { resolve:
|
|
3673
|
+
const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
|
|
3626
3674
|
this.browserPending.delete(msg.id);
|
|
3627
3675
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
3628
|
-
else
|
|
3676
|
+
else resolve13(msg.result);
|
|
3629
3677
|
}
|
|
3630
3678
|
} catch {
|
|
3631
3679
|
}
|
|
@@ -3645,31 +3693,31 @@ var DaemonCdpManager = class {
|
|
|
3645
3693
|
}
|
|
3646
3694
|
}
|
|
3647
3695
|
getBrowserWsUrl() {
|
|
3648
|
-
return new Promise((
|
|
3696
|
+
return new Promise((resolve12) => {
|
|
3649
3697
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
3650
3698
|
let data = "";
|
|
3651
3699
|
res.on("data", (chunk) => data += chunk.toString());
|
|
3652
3700
|
res.on("end", () => {
|
|
3653
3701
|
try {
|
|
3654
3702
|
const info = JSON.parse(data);
|
|
3655
|
-
|
|
3703
|
+
resolve12(info.webSocketDebuggerUrl || null);
|
|
3656
3704
|
} catch {
|
|
3657
|
-
|
|
3705
|
+
resolve12(null);
|
|
3658
3706
|
}
|
|
3659
3707
|
});
|
|
3660
3708
|
});
|
|
3661
|
-
req.on("error", () =>
|
|
3709
|
+
req.on("error", () => resolve12(null));
|
|
3662
3710
|
req.setTimeout(3e3, () => {
|
|
3663
3711
|
req.destroy();
|
|
3664
|
-
|
|
3712
|
+
resolve12(null);
|
|
3665
3713
|
});
|
|
3666
3714
|
});
|
|
3667
3715
|
}
|
|
3668
3716
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
3669
|
-
return new Promise((
|
|
3717
|
+
return new Promise((resolve12, reject) => {
|
|
3670
3718
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
3671
3719
|
const id = this.browserMsgId++;
|
|
3672
|
-
this.browserPending.set(id, { resolve:
|
|
3720
|
+
this.browserPending.set(id, { resolve: resolve12, reject });
|
|
3673
3721
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
3674
3722
|
setTimeout(() => {
|
|
3675
3723
|
if (this.browserPending.has(id)) {
|
|
@@ -3709,11 +3757,11 @@ var DaemonCdpManager = class {
|
|
|
3709
3757
|
}
|
|
3710
3758
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
3711
3759
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
3712
|
-
return new Promise((
|
|
3760
|
+
return new Promise((resolve12, reject) => {
|
|
3713
3761
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
3714
3762
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
3715
3763
|
const id = this.msgId++;
|
|
3716
|
-
this.pending.set(id, { resolve:
|
|
3764
|
+
this.pending.set(id, { resolve: resolve12, reject });
|
|
3717
3765
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
3718
3766
|
setTimeout(() => {
|
|
3719
3767
|
if (this.pending.has(id)) {
|
|
@@ -3962,7 +4010,7 @@ var DaemonCdpManager = class {
|
|
|
3962
4010
|
const browserWs = this.browserWs;
|
|
3963
4011
|
let msgId = this.browserMsgId;
|
|
3964
4012
|
const sendWs = (method, params = {}, sessionId) => {
|
|
3965
|
-
return new Promise((
|
|
4013
|
+
return new Promise((resolve12, reject) => {
|
|
3966
4014
|
const mid = msgId++;
|
|
3967
4015
|
this.browserMsgId = msgId;
|
|
3968
4016
|
const handler = (raw) => {
|
|
@@ -3971,7 +4019,7 @@ var DaemonCdpManager = class {
|
|
|
3971
4019
|
if (msg.id === mid) {
|
|
3972
4020
|
browserWs.removeListener("message", handler);
|
|
3973
4021
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
3974
|
-
else
|
|
4022
|
+
else resolve12(msg.result);
|
|
3975
4023
|
}
|
|
3976
4024
|
} catch {
|
|
3977
4025
|
}
|
|
@@ -4162,14 +4210,14 @@ var DaemonCdpManager = class {
|
|
|
4162
4210
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
4163
4211
|
throw new Error("CDP not connected");
|
|
4164
4212
|
}
|
|
4165
|
-
return new Promise((
|
|
4213
|
+
return new Promise((resolve12, reject) => {
|
|
4166
4214
|
const id = getNextId();
|
|
4167
4215
|
pendingMap.set(id, {
|
|
4168
4216
|
resolve: (result) => {
|
|
4169
4217
|
if (result?.result?.subtype === "error") {
|
|
4170
4218
|
reject(new Error(result.result.description));
|
|
4171
4219
|
} else {
|
|
4172
|
-
|
|
4220
|
+
resolve12(result?.result?.value);
|
|
4173
4221
|
}
|
|
4174
4222
|
},
|
|
4175
4223
|
reject
|
|
@@ -4201,10 +4249,10 @@ var DaemonCdpManager = class {
|
|
|
4201
4249
|
throw new Error("CDP not connected");
|
|
4202
4250
|
}
|
|
4203
4251
|
const sendViaSession = (method, params = {}) => {
|
|
4204
|
-
return new Promise((
|
|
4252
|
+
return new Promise((resolve12, reject) => {
|
|
4205
4253
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
4206
4254
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
4207
|
-
pendingMap.set(id, { resolve:
|
|
4255
|
+
pendingMap.set(id, { resolve: resolve12, reject });
|
|
4208
4256
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
4209
4257
|
setTimeout(() => {
|
|
4210
4258
|
if (pendingMap.has(id)) {
|
|
@@ -4832,9 +4880,9 @@ function normalizeControlValue(value) {
|
|
|
4832
4880
|
|
|
4833
4881
|
// src/config/chat-history.ts
|
|
4834
4882
|
import * as fs3 from "fs";
|
|
4835
|
-
import * as
|
|
4883
|
+
import * as path7 from "path";
|
|
4836
4884
|
import * as os5 from "os";
|
|
4837
|
-
var HISTORY_DIR =
|
|
4885
|
+
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
4838
4886
|
var RETAIN_DAYS = 30;
|
|
4839
4887
|
var ChatHistoryWriter = class {
|
|
4840
4888
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -4879,11 +4927,11 @@ var ChatHistoryWriter = class {
|
|
|
4879
4927
|
});
|
|
4880
4928
|
}
|
|
4881
4929
|
if (newMessages.length === 0) return;
|
|
4882
|
-
const dir =
|
|
4930
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4883
4931
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4884
4932
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4885
4933
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
4886
|
-
const filePath =
|
|
4934
|
+
const filePath = path7.join(dir, `${filePrefix}${date}.jsonl`);
|
|
4887
4935
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
4888
4936
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
4889
4937
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
@@ -4937,14 +4985,14 @@ var ChatHistoryWriter = class {
|
|
|
4937
4985
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
4938
4986
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
4939
4987
|
}
|
|
4940
|
-
const dir =
|
|
4988
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4941
4989
|
if (!fs3.existsSync(dir)) return;
|
|
4942
4990
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
4943
4991
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
4944
4992
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
4945
4993
|
for (const file of files) {
|
|
4946
|
-
const sourcePath =
|
|
4947
|
-
const targetPath =
|
|
4994
|
+
const sourcePath = path7.join(dir, file);
|
|
4995
|
+
const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
4948
4996
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
4949
4997
|
const rewritten = sourceLines.map((line) => {
|
|
4950
4998
|
try {
|
|
@@ -4985,10 +5033,10 @@ var ChatHistoryWriter = class {
|
|
|
4985
5033
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
4986
5034
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
4987
5035
|
for (const dir of agentDirs) {
|
|
4988
|
-
const dirPath =
|
|
5036
|
+
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
4989
5037
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
4990
5038
|
for (const file of files) {
|
|
4991
|
-
const filePath =
|
|
5039
|
+
const filePath = path7.join(dirPath, file);
|
|
4992
5040
|
const stat = fs3.statSync(filePath);
|
|
4993
5041
|
if (stat.mtimeMs < cutoff) {
|
|
4994
5042
|
fs3.unlinkSync(filePath);
|
|
@@ -5006,7 +5054,7 @@ var ChatHistoryWriter = class {
|
|
|
5006
5054
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
5007
5055
|
try {
|
|
5008
5056
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5009
|
-
const dir =
|
|
5057
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
5010
5058
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
5011
5059
|
const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5012
5060
|
const files = fs3.readdirSync(dir).filter((f) => {
|
|
@@ -5020,7 +5068,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
|
5020
5068
|
const needed = offset + limit + 1;
|
|
5021
5069
|
for (const file of files) {
|
|
5022
5070
|
if (allMessages.length >= needed) break;
|
|
5023
|
-
const filePath =
|
|
5071
|
+
const filePath = path7.join(dir, file);
|
|
5024
5072
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
5025
5073
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
5026
5074
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -5042,7 +5090,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
|
5042
5090
|
function listSavedHistorySessions(agentType, options = {}) {
|
|
5043
5091
|
try {
|
|
5044
5092
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5045
|
-
const dir =
|
|
5093
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
5046
5094
|
if (!fs3.existsSync(dir)) return { sessions: [], hasMore: false };
|
|
5047
5095
|
const groupedFiles = /* @__PURE__ */ new Map();
|
|
5048
5096
|
const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
@@ -5063,7 +5111,7 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
5063
5111
|
let sessionTitle = "";
|
|
5064
5112
|
let preview = "";
|
|
5065
5113
|
for (const file of files.sort()) {
|
|
5066
|
-
const filePath =
|
|
5114
|
+
const filePath = path7.join(dir, file);
|
|
5067
5115
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
5068
5116
|
const lines = content.split("\n").filter(Boolean);
|
|
5069
5117
|
for (const line of lines) {
|
|
@@ -7238,6 +7286,14 @@ async function handleListChats(h, args) {
|
|
|
7238
7286
|
} catch {
|
|
7239
7287
|
}
|
|
7240
7288
|
}
|
|
7289
|
+
if (parsed?.sessions && Array.isArray(parsed.sessions)) {
|
|
7290
|
+
LOG.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
|
|
7291
|
+
return { success: true, chats: parsed.sessions };
|
|
7292
|
+
}
|
|
7293
|
+
if (parsed?.chats && Array.isArray(parsed.chats)) {
|
|
7294
|
+
LOG.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
|
|
7295
|
+
return { success: true, chats: parsed.chats };
|
|
7296
|
+
}
|
|
7241
7297
|
if (Array.isArray(parsed)) {
|
|
7242
7298
|
LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
|
|
7243
7299
|
return { success: true, chats: parsed };
|
|
@@ -7307,7 +7363,13 @@ async function handleSwitchChat(h, args) {
|
|
|
7307
7363
|
} catch (e) {
|
|
7308
7364
|
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
7309
7365
|
}
|
|
7310
|
-
const
|
|
7366
|
+
const switchParams = {
|
|
7367
|
+
sessionId,
|
|
7368
|
+
title: sessionId,
|
|
7369
|
+
id: sessionId,
|
|
7370
|
+
SESSION_ID: JSON.stringify(sessionId)
|
|
7371
|
+
};
|
|
7372
|
+
const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
|
|
7311
7373
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
7312
7374
|
try {
|
|
7313
7375
|
const raw = await cdp.evaluate(script, 15e3);
|
|
@@ -7386,8 +7448,8 @@ async function handleSetMode(h, args) {
|
|
|
7386
7448
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7387
7449
|
if (adapter) {
|
|
7388
7450
|
const acpInstance = adapter._acpInstance;
|
|
7389
|
-
if (acpInstance && typeof acpInstance.
|
|
7390
|
-
acpInstance.
|
|
7451
|
+
if (acpInstance && typeof acpInstance.setMode === "function") {
|
|
7452
|
+
await acpInstance.setMode(mode);
|
|
7391
7453
|
return { success: true, mode };
|
|
7392
7454
|
}
|
|
7393
7455
|
}
|
|
@@ -7444,9 +7506,9 @@ async function handleChangeModel(h, args) {
|
|
|
7444
7506
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
7445
7507
|
if (adapter) {
|
|
7446
7508
|
const acpInstance = adapter._acpInstance;
|
|
7447
|
-
if (acpInstance && typeof acpInstance.
|
|
7448
|
-
acpInstance.
|
|
7449
|
-
LOG.info("Command", `[change_model]
|
|
7509
|
+
if (acpInstance && typeof acpInstance.setConfigOption === "function") {
|
|
7510
|
+
await acpInstance.setConfigOption("model", model);
|
|
7511
|
+
LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
|
|
7450
7512
|
return { success: true, model };
|
|
7451
7513
|
}
|
|
7452
7514
|
}
|
|
@@ -7566,6 +7628,18 @@ async function handleResolveAction(h, args) {
|
|
|
7566
7628
|
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
7567
7629
|
return { success: ok };
|
|
7568
7630
|
}
|
|
7631
|
+
if (transport === "acp") {
|
|
7632
|
+
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7633
|
+
const acpInstance = adapter?._acpInstance;
|
|
7634
|
+
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
7635
|
+
try {
|
|
7636
|
+
await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
|
|
7637
|
+
LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
|
|
7638
|
+
return { success: true, action };
|
|
7639
|
+
} catch (e) {
|
|
7640
|
+
return { success: false, error: e?.message || "ACP resolve action failed" };
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7569
7643
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
7570
7644
|
const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
7571
7645
|
if (script) {
|
|
@@ -7644,7 +7718,7 @@ async function handleResolveAction(h, args) {
|
|
|
7644
7718
|
|
|
7645
7719
|
// src/commands/cdp-commands.ts
|
|
7646
7720
|
import * as fs4 from "fs";
|
|
7647
|
-
import * as
|
|
7721
|
+
import * as path8 from "path";
|
|
7648
7722
|
import * as os6 from "os";
|
|
7649
7723
|
var KEY_TO_VK = {
|
|
7650
7724
|
Backspace: 8,
|
|
@@ -7896,25 +7970,25 @@ function resolveSafePath(requestedPath) {
|
|
|
7896
7970
|
const inputPath = rawPath || ".";
|
|
7897
7971
|
const home = os6.homedir();
|
|
7898
7972
|
if (inputPath.startsWith("~")) {
|
|
7899
|
-
return
|
|
7973
|
+
return path8.resolve(path8.join(home, inputPath.slice(1)));
|
|
7900
7974
|
}
|
|
7901
7975
|
if (process.platform === "win32") {
|
|
7902
7976
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
7903
|
-
if (
|
|
7904
|
-
return
|
|
7977
|
+
if (path8.win32.isAbsolute(normalized)) {
|
|
7978
|
+
return path8.win32.normalize(normalized);
|
|
7905
7979
|
}
|
|
7906
|
-
return
|
|
7980
|
+
return path8.win32.resolve(normalized);
|
|
7907
7981
|
}
|
|
7908
|
-
if (
|
|
7909
|
-
return
|
|
7982
|
+
if (path8.isAbsolute(inputPath)) {
|
|
7983
|
+
return path8.normalize(inputPath);
|
|
7910
7984
|
}
|
|
7911
|
-
return
|
|
7985
|
+
return path8.resolve(inputPath);
|
|
7912
7986
|
}
|
|
7913
7987
|
function listDirectoryEntriesSafe(dirPath) {
|
|
7914
7988
|
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
7915
7989
|
const files = [];
|
|
7916
7990
|
for (const entry of entries) {
|
|
7917
|
-
const entryPath =
|
|
7991
|
+
const entryPath = path8.join(dirPath, entry.name);
|
|
7918
7992
|
try {
|
|
7919
7993
|
if (entry.isDirectory()) {
|
|
7920
7994
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -7953,7 +8027,7 @@ async function handleFileRead(h, args) {
|
|
|
7953
8027
|
async function handleFileWrite(h, args) {
|
|
7954
8028
|
try {
|
|
7955
8029
|
const filePath = resolveSafePath(args?.path);
|
|
7956
|
-
fs4.mkdirSync(
|
|
8030
|
+
fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
|
|
7957
8031
|
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
7958
8032
|
return { success: true, path: filePath };
|
|
7959
8033
|
} catch (e) {
|
|
@@ -8041,7 +8115,7 @@ function handleGetProviderSettings(h, args) {
|
|
|
8041
8115
|
}
|
|
8042
8116
|
return { success: true, settings: allSettings, values: allValues };
|
|
8043
8117
|
}
|
|
8044
|
-
function handleSetProviderSetting(h, args) {
|
|
8118
|
+
async function handleSetProviderSetting(h, args) {
|
|
8045
8119
|
const loader = h.ctx.providerLoader;
|
|
8046
8120
|
const { providerType, key, value } = args || {};
|
|
8047
8121
|
if (!providerType || !key || value === void 0) {
|
|
@@ -8054,6 +8128,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
8054
8128
|
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
8055
8129
|
LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
|
|
8056
8130
|
}
|
|
8131
|
+
await h.ctx.onProviderSettingChanged?.(providerType, key, value);
|
|
8057
8132
|
return { success: true, providerType, key, value };
|
|
8058
8133
|
}
|
|
8059
8134
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
@@ -8091,10 +8166,10 @@ function getCliScriptCommand(payload) {
|
|
|
8091
8166
|
}
|
|
8092
8167
|
const command = payload.command;
|
|
8093
8168
|
if (!command || typeof command !== "object") return null;
|
|
8094
|
-
if (command.type !== "send_message") return null;
|
|
8169
|
+
if (command.type !== "send_message" && command.type !== "pty_write") return null;
|
|
8095
8170
|
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
8096
8171
|
if (!text) return null;
|
|
8097
|
-
return { type:
|
|
8172
|
+
return { type: command.type, text };
|
|
8098
8173
|
}
|
|
8099
8174
|
function applyProviderPatch(h, args, payload) {
|
|
8100
8175
|
if (!payload || typeof payload !== "object") return;
|
|
@@ -8135,6 +8210,8 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8135
8210
|
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
8136
8211
|
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
8137
8212
|
await adapter.sendMessage(cliCommand.text);
|
|
8213
|
+
} else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
|
|
8214
|
+
adapter.writeRaw(cliCommand.text + "\r");
|
|
8138
8215
|
}
|
|
8139
8216
|
applyProviderPatch(h, args, parsed.payload);
|
|
8140
8217
|
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
@@ -8813,7 +8890,7 @@ var DaemonCommandHandler = class {
|
|
|
8813
8890
|
try {
|
|
8814
8891
|
const http3 = await import("http");
|
|
8815
8892
|
const postData = JSON.stringify(body);
|
|
8816
|
-
const result = await new Promise((
|
|
8893
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8817
8894
|
const req = http3.request({
|
|
8818
8895
|
hostname: "127.0.0.1",
|
|
8819
8896
|
port: 19280,
|
|
@@ -8825,9 +8902,9 @@ var DaemonCommandHandler = class {
|
|
|
8825
8902
|
res.on("data", (chunk) => data += chunk);
|
|
8826
8903
|
res.on("end", () => {
|
|
8827
8904
|
try {
|
|
8828
|
-
|
|
8905
|
+
resolve12(JSON.parse(data));
|
|
8829
8906
|
} catch {
|
|
8830
|
-
|
|
8907
|
+
resolve12({ raw: data });
|
|
8831
8908
|
}
|
|
8832
8909
|
});
|
|
8833
8910
|
});
|
|
@@ -8845,15 +8922,15 @@ var DaemonCommandHandler = class {
|
|
|
8845
8922
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
8846
8923
|
try {
|
|
8847
8924
|
const http3 = await import("http");
|
|
8848
|
-
const result = await new Promise((
|
|
8925
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8849
8926
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
8850
8927
|
let data = "";
|
|
8851
8928
|
res.on("data", (chunk) => data += chunk);
|
|
8852
8929
|
res.on("end", () => {
|
|
8853
8930
|
try {
|
|
8854
|
-
|
|
8931
|
+
resolve12(JSON.parse(data));
|
|
8855
8932
|
} catch {
|
|
8856
|
-
|
|
8933
|
+
resolve12({ raw: data });
|
|
8857
8934
|
}
|
|
8858
8935
|
});
|
|
8859
8936
|
}).on("error", reject);
|
|
@@ -8867,7 +8944,7 @@ var DaemonCommandHandler = class {
|
|
|
8867
8944
|
try {
|
|
8868
8945
|
const http3 = await import("http");
|
|
8869
8946
|
const postData = JSON.stringify(args || {});
|
|
8870
|
-
const result = await new Promise((
|
|
8947
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8871
8948
|
const req = http3.request({
|
|
8872
8949
|
hostname: "127.0.0.1",
|
|
8873
8950
|
port: 19280,
|
|
@@ -8879,9 +8956,9 @@ var DaemonCommandHandler = class {
|
|
|
8879
8956
|
res.on("data", (chunk) => data += chunk);
|
|
8880
8957
|
res.on("end", () => {
|
|
8881
8958
|
try {
|
|
8882
|
-
|
|
8959
|
+
resolve12(JSON.parse(data));
|
|
8883
8960
|
} catch {
|
|
8884
|
-
|
|
8961
|
+
resolve12({ raw: data });
|
|
8885
8962
|
}
|
|
8886
8963
|
});
|
|
8887
8964
|
});
|
|
@@ -8899,7 +8976,7 @@ var DaemonCommandHandler = class {
|
|
|
8899
8976
|
// src/commands/cli-manager.ts
|
|
8900
8977
|
init_provider_cli_adapter();
|
|
8901
8978
|
import * as os10 from "os";
|
|
8902
|
-
import * as
|
|
8979
|
+
import * as path11 from "path";
|
|
8903
8980
|
import * as crypto4 from "crypto";
|
|
8904
8981
|
import chalk from "chalk";
|
|
8905
8982
|
init_config();
|
|
@@ -8907,7 +8984,7 @@ init_config();
|
|
|
8907
8984
|
// src/providers/cli-provider-instance.ts
|
|
8908
8985
|
init_provider_cli_adapter();
|
|
8909
8986
|
import * as os9 from "os";
|
|
8910
|
-
import * as
|
|
8987
|
+
import * as path10 from "path";
|
|
8911
8988
|
import * as crypto3 from "crypto";
|
|
8912
8989
|
import * as fs5 from "fs";
|
|
8913
8990
|
import { createRequire } from "module";
|
|
@@ -8915,7 +8992,7 @@ init_logger();
|
|
|
8915
8992
|
var CachedDatabaseSync = null;
|
|
8916
8993
|
function getDatabaseSync() {
|
|
8917
8994
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
8918
|
-
const requireFn = typeof __require === "function" ? __require : createRequire(
|
|
8995
|
+
const requireFn = typeof __require === "function" ? __require : createRequire(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
8919
8996
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
8920
8997
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
8921
8998
|
if (!CachedDatabaseSync) {
|
|
@@ -9749,8 +9826,9 @@ var AcpProviderInstance = class {
|
|
|
9749
9826
|
async setConfigOption(category, value) {
|
|
9750
9827
|
const opt = this.configOptions.find((c) => c.category === category);
|
|
9751
9828
|
if (!opt) {
|
|
9752
|
-
|
|
9753
|
-
|
|
9829
|
+
const message = `[${this.type}] No config option for category: ${category}`;
|
|
9830
|
+
this.log.warn(message);
|
|
9831
|
+
throw new Error(message);
|
|
9754
9832
|
}
|
|
9755
9833
|
if (this.useStaticConfig) {
|
|
9756
9834
|
opt.currentValue = value;
|
|
@@ -9762,8 +9840,9 @@ var AcpProviderInstance = class {
|
|
|
9762
9840
|
return;
|
|
9763
9841
|
}
|
|
9764
9842
|
if (!this.connection || !this.sessionId) {
|
|
9765
|
-
|
|
9766
|
-
|
|
9843
|
+
const message = `[${this.type}] Cannot set config: no active connection/session`;
|
|
9844
|
+
this.log.warn(message);
|
|
9845
|
+
throw new Error(message);
|
|
9767
9846
|
}
|
|
9768
9847
|
try {
|
|
9769
9848
|
this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
|
|
@@ -9777,7 +9856,9 @@ var AcpProviderInstance = class {
|
|
|
9777
9856
|
if (result?.configOptions) this.parseConfigOptions(result.configOptions);
|
|
9778
9857
|
this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
|
|
9779
9858
|
} catch (e) {
|
|
9780
|
-
|
|
9859
|
+
const message = e?.message || "Unknown ACP config error";
|
|
9860
|
+
this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
|
|
9861
|
+
throw new Error(message);
|
|
9781
9862
|
}
|
|
9782
9863
|
}
|
|
9783
9864
|
async setMode(modeId) {
|
|
@@ -9793,8 +9874,9 @@ var AcpProviderInstance = class {
|
|
|
9793
9874
|
return;
|
|
9794
9875
|
}
|
|
9795
9876
|
if (!this.connection || !this.sessionId) {
|
|
9796
|
-
|
|
9797
|
-
|
|
9877
|
+
const message = `[${this.type}] Cannot set mode: no active connection/session`;
|
|
9878
|
+
this.log.warn(message);
|
|
9879
|
+
throw new Error(message);
|
|
9798
9880
|
}
|
|
9799
9881
|
try {
|
|
9800
9882
|
await this.connection.setSessionMode({
|
|
@@ -9804,7 +9886,9 @@ var AcpProviderInstance = class {
|
|
|
9804
9886
|
this.currentMode = modeId;
|
|
9805
9887
|
this.log.info(`[${this.type}] Mode set to: ${modeId}`);
|
|
9806
9888
|
} catch (e) {
|
|
9807
|
-
|
|
9889
|
+
const message = e?.message || "Unknown ACP mode error";
|
|
9890
|
+
this.log.warn(`[${this.type}] set_mode failed: ${message}`);
|
|
9891
|
+
throw new Error(message);
|
|
9808
9892
|
}
|
|
9809
9893
|
}
|
|
9810
9894
|
/** Static config: kill process and restart with new args */
|
|
@@ -9852,7 +9936,7 @@ var AcpProviderInstance = class {
|
|
|
9852
9936
|
if (!spawnConfig) {
|
|
9853
9937
|
throw new Error(`[ACP:${this.type}] No spawn config defined`);
|
|
9854
9938
|
}
|
|
9855
|
-
const command = spawnConfig.command;
|
|
9939
|
+
const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
|
|
9856
9940
|
let baseArgs = spawnConfig.args || [];
|
|
9857
9941
|
if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
|
|
9858
9942
|
baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
|
|
@@ -9968,13 +10052,13 @@ var AcpProviderInstance = class {
|
|
|
9968
10052
|
}
|
|
9969
10053
|
this.currentStatus = "waiting_approval";
|
|
9970
10054
|
this.detectStatusTransition();
|
|
9971
|
-
const approved = await new Promise((
|
|
9972
|
-
this.permissionResolvers.push(
|
|
10055
|
+
const approved = await new Promise((resolve12) => {
|
|
10056
|
+
this.permissionResolvers.push(resolve12);
|
|
9973
10057
|
setTimeout(() => {
|
|
9974
|
-
const idx = this.permissionResolvers.indexOf(
|
|
10058
|
+
const idx = this.permissionResolvers.indexOf(resolve12);
|
|
9975
10059
|
if (idx >= 0) {
|
|
9976
10060
|
this.permissionResolvers.splice(idx, 1);
|
|
9977
|
-
|
|
10061
|
+
resolve12(false);
|
|
9978
10062
|
}
|
|
9979
10063
|
}, 3e5);
|
|
9980
10064
|
});
|
|
@@ -10681,7 +10765,7 @@ var DaemonCliManager = class {
|
|
|
10681
10765
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
10682
10766
|
const trimmed = (workingDir || "").trim();
|
|
10683
10767
|
if (!trimmed) throw new Error("working directory required");
|
|
10684
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) :
|
|
10768
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
|
|
10685
10769
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10686
10770
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10687
10771
|
const key = crypto4.randomUUID();
|
|
@@ -10768,10 +10852,10 @@ ${installInfo}`
|
|
|
10768
10852
|
if (!cliInfo) {
|
|
10769
10853
|
const installHint = provider?.install || "";
|
|
10770
10854
|
const displayName = provider?.displayName || provider?.name || cliType;
|
|
10771
|
-
const spawnCmd = provider?.spawn?.command || cliType;
|
|
10855
|
+
const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
|
|
10772
10856
|
throw new Error(
|
|
10773
10857
|
`${displayName} is not installed.
|
|
10774
|
-
Command '${spawnCmd}' not
|
|
10858
|
+
Command '${spawnCmd}' is not available.
|
|
10775
10859
|
` + (installHint ? `
|
|
10776
10860
|
${installHint}
|
|
10777
10861
|
` : "") + `
|
|
@@ -11131,16 +11215,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
11131
11215
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
11132
11216
|
import * as net from "net";
|
|
11133
11217
|
import * as os12 from "os";
|
|
11134
|
-
import * as
|
|
11218
|
+
import * as path13 from "path";
|
|
11135
11219
|
|
|
11136
11220
|
// src/providers/provider-loader.ts
|
|
11137
11221
|
import * as fs6 from "fs";
|
|
11138
|
-
import * as
|
|
11222
|
+
import * as path12 from "path";
|
|
11139
11223
|
import * as os11 from "os";
|
|
11140
11224
|
import * as chokidar from "chokidar";
|
|
11141
11225
|
init_logger();
|
|
11142
11226
|
var ProviderLoader = class _ProviderLoader {
|
|
11143
11227
|
providers = /* @__PURE__ */ new Map();
|
|
11228
|
+
providerAvailability = /* @__PURE__ */ new Map();
|
|
11144
11229
|
userDir;
|
|
11145
11230
|
upstreamDir;
|
|
11146
11231
|
disableUpstream;
|
|
@@ -11156,12 +11241,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11156
11241
|
static META_FILE = ".meta.json";
|
|
11157
11242
|
constructor(options) {
|
|
11158
11243
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
11159
|
-
const defaultProvidersDir =
|
|
11244
|
+
const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
|
|
11160
11245
|
if (options?.userDir) {
|
|
11161
11246
|
this.userDir = options.userDir;
|
|
11162
11247
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
11163
11248
|
} else {
|
|
11164
|
-
const localRepoPath =
|
|
11249
|
+
const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
|
|
11165
11250
|
if (fs6.existsSync(localRepoPath)) {
|
|
11166
11251
|
this.userDir = localRepoPath;
|
|
11167
11252
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -11170,7 +11255,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11170
11255
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
11171
11256
|
}
|
|
11172
11257
|
}
|
|
11173
|
-
this.upstreamDir =
|
|
11258
|
+
this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
|
|
11174
11259
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
11175
11260
|
}
|
|
11176
11261
|
log(msg) {
|
|
@@ -11200,7 +11285,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11200
11285
|
* Canonical provider directory shape for a given root.
|
|
11201
11286
|
*/
|
|
11202
11287
|
getProviderDir(root, category, type) {
|
|
11203
|
-
return
|
|
11288
|
+
return path12.join(root, category, type);
|
|
11204
11289
|
}
|
|
11205
11290
|
/**
|
|
11206
11291
|
* Canonical user override directory for a provider.
|
|
@@ -11227,7 +11312,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11227
11312
|
resolveProviderFile(type, ...segments) {
|
|
11228
11313
|
const dir = this.findProviderDirInternal(type);
|
|
11229
11314
|
if (!dir) return null;
|
|
11230
|
-
return
|
|
11315
|
+
return path12.join(dir, ...segments);
|
|
11231
11316
|
}
|
|
11232
11317
|
/**
|
|
11233
11318
|
* Load all providers (3-tier priority)
|
|
@@ -11238,6 +11323,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11238
11323
|
*/
|
|
11239
11324
|
loadAll() {
|
|
11240
11325
|
this.providers.clear();
|
|
11326
|
+
this.providerAvailability.clear();
|
|
11241
11327
|
let upstreamCount = 0;
|
|
11242
11328
|
if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
|
|
11243
11329
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
@@ -11265,7 +11351,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11265
11351
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
11266
11352
|
try {
|
|
11267
11353
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
11268
|
-
(d) => fs6.statSync(
|
|
11354
|
+
(d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
|
|
11269
11355
|
);
|
|
11270
11356
|
} catch {
|
|
11271
11357
|
return false;
|
|
@@ -11308,11 +11394,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11308
11394
|
if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
|
|
11309
11395
|
const verCmdConfig = p.versionCommand;
|
|
11310
11396
|
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
|
|
11397
|
+
const command = this.getSpawnCommand(p.type, p.spawn.command);
|
|
11311
11398
|
result.push({
|
|
11312
11399
|
id: p.type,
|
|
11313
11400
|
displayName: p.displayName || p.name,
|
|
11314
11401
|
icon: p.icon || "\u{1F527}",
|
|
11315
|
-
command
|
|
11402
|
+
command,
|
|
11316
11403
|
category: p.category,
|
|
11317
11404
|
...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
|
|
11318
11405
|
});
|
|
@@ -11441,6 +11528,71 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11441
11528
|
getAvailableIdeTypes() {
|
|
11442
11529
|
return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
|
|
11443
11530
|
}
|
|
11531
|
+
getSpawnCommand(type, fallback) {
|
|
11532
|
+
const override = this.getOptionalStringSetting(type, "executablePath");
|
|
11533
|
+
if (override) return override;
|
|
11534
|
+
return fallback || this.providers.get(type)?.spawn?.command || type;
|
|
11535
|
+
}
|
|
11536
|
+
getIdeCliCommand(type, fallback) {
|
|
11537
|
+
const override = this.getOptionalStringSetting(type, "cliPathOverride");
|
|
11538
|
+
if (override) return override;
|
|
11539
|
+
return fallback || this.providers.get(type)?.cli || null;
|
|
11540
|
+
}
|
|
11541
|
+
getIdePathCandidates(type, fallback) {
|
|
11542
|
+
const override = this.getOptionalStringSetting(type, "appPathOverride");
|
|
11543
|
+
if (override) return [override];
|
|
11544
|
+
if (fallback && fallback.length > 0) return fallback;
|
|
11545
|
+
const osPaths = this.providers.get(type)?.paths?.[process.platform];
|
|
11546
|
+
return Array.isArray(osPaths) ? [...osPaths] : [];
|
|
11547
|
+
}
|
|
11548
|
+
setProviderAvailability(type, state) {
|
|
11549
|
+
this.providerAvailability.set(type, {
|
|
11550
|
+
installed: !!state.installed,
|
|
11551
|
+
detectedPath: state.detectedPath ?? null
|
|
11552
|
+
});
|
|
11553
|
+
}
|
|
11554
|
+
setCliDetectionResults(results, replace = true) {
|
|
11555
|
+
if (replace) {
|
|
11556
|
+
for (const provider of this.providers.values()) {
|
|
11557
|
+
if (provider.category === "cli" || provider.category === "acp") {
|
|
11558
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
11559
|
+
}
|
|
11560
|
+
}
|
|
11561
|
+
}
|
|
11562
|
+
for (const result of results) {
|
|
11563
|
+
this.setProviderAvailability(result.id, {
|
|
11564
|
+
installed: !!result.installed,
|
|
11565
|
+
detectedPath: result.path || null
|
|
11566
|
+
});
|
|
11567
|
+
}
|
|
11568
|
+
}
|
|
11569
|
+
setIdeDetectionResults(results, replace = true) {
|
|
11570
|
+
if (replace) {
|
|
11571
|
+
for (const provider of this.providers.values()) {
|
|
11572
|
+
if (provider.category === "ide") {
|
|
11573
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
11574
|
+
}
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
for (const result of results) {
|
|
11578
|
+
this.setProviderAvailability(result.id, {
|
|
11579
|
+
installed: !!result.installed,
|
|
11580
|
+
detectedPath: result.cliCommand || result.path || null
|
|
11581
|
+
});
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
getAvailableProviderInfos() {
|
|
11585
|
+
return this.getAll().map((provider) => {
|
|
11586
|
+
const availability = this.providerAvailability.get(provider.type);
|
|
11587
|
+
return {
|
|
11588
|
+
...provider,
|
|
11589
|
+
...availability ? {
|
|
11590
|
+
installed: availability.installed,
|
|
11591
|
+
detectedPath: availability.detectedPath
|
|
11592
|
+
} : {}
|
|
11593
|
+
};
|
|
11594
|
+
});
|
|
11595
|
+
}
|
|
11444
11596
|
/**
|
|
11445
11597
|
* Register IDE providers to core/detector registry
|
|
11446
11598
|
* → Enables detectIDEs() to detect provider.js-based IDEs
|
|
@@ -11515,8 +11667,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11515
11667
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
11516
11668
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
11517
11669
|
if (providerDir) {
|
|
11518
|
-
const fullDir =
|
|
11519
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11670
|
+
const fullDir = path12.join(providerDir, entry.scriptDir);
|
|
11671
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11520
11672
|
}
|
|
11521
11673
|
matched = true;
|
|
11522
11674
|
}
|
|
@@ -11531,8 +11683,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11531
11683
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11532
11684
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
11533
11685
|
if (providerDir) {
|
|
11534
|
-
const fullDir =
|
|
11535
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11686
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
11687
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11536
11688
|
}
|
|
11537
11689
|
}
|
|
11538
11690
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -11549,8 +11701,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11549
11701
|
resolved._resolvedScriptDir = dirOverride;
|
|
11550
11702
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
11551
11703
|
if (providerDir) {
|
|
11552
|
-
const fullDir =
|
|
11553
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11704
|
+
const fullDir = path12.join(providerDir, dirOverride);
|
|
11705
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11554
11706
|
}
|
|
11555
11707
|
}
|
|
11556
11708
|
} else if (override.scripts) {
|
|
@@ -11566,8 +11718,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11566
11718
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11567
11719
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
11568
11720
|
if (providerDir) {
|
|
11569
|
-
const fullDir =
|
|
11570
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11721
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
11722
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11571
11723
|
}
|
|
11572
11724
|
}
|
|
11573
11725
|
}
|
|
@@ -11592,14 +11744,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11592
11744
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
11593
11745
|
return null;
|
|
11594
11746
|
}
|
|
11595
|
-
const dir =
|
|
11747
|
+
const dir = path12.join(providerDir, scriptDir);
|
|
11596
11748
|
if (!fs6.existsSync(dir)) {
|
|
11597
11749
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
11598
11750
|
return null;
|
|
11599
11751
|
}
|
|
11600
11752
|
const cached = this.scriptsCache.get(dir);
|
|
11601
11753
|
if (cached) return cached;
|
|
11602
|
-
const scriptsJs =
|
|
11754
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
11603
11755
|
if (fs6.existsSync(scriptsJs)) {
|
|
11604
11756
|
try {
|
|
11605
11757
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -11641,7 +11793,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11641
11793
|
return;
|
|
11642
11794
|
}
|
|
11643
11795
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
11644
|
-
this.log(`File changed: ${
|
|
11796
|
+
this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
|
|
11645
11797
|
this.reload();
|
|
11646
11798
|
}
|
|
11647
11799
|
};
|
|
@@ -11696,7 +11848,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11696
11848
|
}
|
|
11697
11849
|
const https = __require("https");
|
|
11698
11850
|
const { execSync: execSync7 } = __require("child_process");
|
|
11699
|
-
const metaPath =
|
|
11851
|
+
const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
11700
11852
|
let prevEtag = "";
|
|
11701
11853
|
let prevTimestamp = 0;
|
|
11702
11854
|
try {
|
|
@@ -11713,7 +11865,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11713
11865
|
return { updated: false };
|
|
11714
11866
|
}
|
|
11715
11867
|
try {
|
|
11716
|
-
const etag = await new Promise((
|
|
11868
|
+
const etag = await new Promise((resolve12, reject) => {
|
|
11717
11869
|
const options = {
|
|
11718
11870
|
method: "HEAD",
|
|
11719
11871
|
hostname: "github.com",
|
|
@@ -11731,7 +11883,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11731
11883
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
11732
11884
|
timeout: 1e4
|
|
11733
11885
|
}, (res2) => {
|
|
11734
|
-
|
|
11886
|
+
resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
11735
11887
|
});
|
|
11736
11888
|
req2.on("error", reject);
|
|
11737
11889
|
req2.on("timeout", () => {
|
|
@@ -11740,7 +11892,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11740
11892
|
});
|
|
11741
11893
|
req2.end();
|
|
11742
11894
|
} else {
|
|
11743
|
-
|
|
11895
|
+
resolve12(res.headers.etag || res.headers["last-modified"] || "");
|
|
11744
11896
|
}
|
|
11745
11897
|
});
|
|
11746
11898
|
req.on("error", reject);
|
|
@@ -11756,17 +11908,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11756
11908
|
return { updated: false };
|
|
11757
11909
|
}
|
|
11758
11910
|
this.log("Downloading latest providers from GitHub...");
|
|
11759
|
-
const tmpTar =
|
|
11760
|
-
const tmpExtract =
|
|
11911
|
+
const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
11912
|
+
const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
11761
11913
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
11762
11914
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
11763
11915
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
11764
11916
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
11765
11917
|
const rootDir = extracted.find(
|
|
11766
|
-
(d) => fs6.statSync(
|
|
11918
|
+
(d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
11767
11919
|
);
|
|
11768
11920
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
11769
|
-
const sourceDir =
|
|
11921
|
+
const sourceDir = path12.join(tmpExtract, rootDir);
|
|
11770
11922
|
const backupDir = this.upstreamDir + ".bak";
|
|
11771
11923
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
11772
11924
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -11804,7 +11956,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11804
11956
|
downloadFile(url, destPath) {
|
|
11805
11957
|
const https = __require("https");
|
|
11806
11958
|
const http3 = __require("http");
|
|
11807
|
-
return new Promise((
|
|
11959
|
+
return new Promise((resolve12, reject) => {
|
|
11808
11960
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
11809
11961
|
if (redirectCount > 5) {
|
|
11810
11962
|
reject(new Error("Too many redirects"));
|
|
@@ -11824,7 +11976,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11824
11976
|
res.pipe(ws);
|
|
11825
11977
|
ws.on("finish", () => {
|
|
11826
11978
|
ws.close();
|
|
11827
|
-
|
|
11979
|
+
resolve12();
|
|
11828
11980
|
});
|
|
11829
11981
|
ws.on("error", reject);
|
|
11830
11982
|
});
|
|
@@ -11841,8 +11993,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11841
11993
|
copyDirRecursive(src, dest) {
|
|
11842
11994
|
fs6.mkdirSync(dest, { recursive: true });
|
|
11843
11995
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
11844
|
-
const srcPath =
|
|
11845
|
-
const destPath =
|
|
11996
|
+
const srcPath = path12.join(src, entry.name);
|
|
11997
|
+
const destPath = path12.join(dest, entry.name);
|
|
11846
11998
|
if (entry.isDirectory()) {
|
|
11847
11999
|
this.copyDirRecursive(srcPath, destPath);
|
|
11848
12000
|
} else {
|
|
@@ -11853,7 +12005,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11853
12005
|
/** .meta.json save */
|
|
11854
12006
|
writeMeta(metaPath, etag, timestamp) {
|
|
11855
12007
|
try {
|
|
11856
|
-
fs6.mkdirSync(
|
|
12008
|
+
fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
|
|
11857
12009
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
11858
12010
|
etag,
|
|
11859
12011
|
timestamp,
|
|
@@ -11870,7 +12022,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11870
12022
|
const scan = (d) => {
|
|
11871
12023
|
try {
|
|
11872
12024
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
11873
|
-
if (entry.isDirectory()) scan(
|
|
12025
|
+
if (entry.isDirectory()) scan(path12.join(d, entry.name));
|
|
11874
12026
|
else if (entry.name === "provider.json") count++;
|
|
11875
12027
|
}
|
|
11876
12028
|
} catch {
|
|
@@ -11884,9 +12036,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11884
12036
|
* Get public settings schema for a provider (for dashboard UI rendering)
|
|
11885
12037
|
*/
|
|
11886
12038
|
getPublicSettings(type) {
|
|
11887
|
-
const
|
|
11888
|
-
|
|
11889
|
-
return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
12039
|
+
const settings = this.getSettingsSchema(type);
|
|
12040
|
+
return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
11890
12041
|
}
|
|
11891
12042
|
/**
|
|
11892
12043
|
* Get public settings schema for all providers
|
|
@@ -11903,8 +12054,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11903
12054
|
* Resolved setting value for a provider (default + user override)
|
|
11904
12055
|
*/
|
|
11905
12056
|
getSettingValue(type, key) {
|
|
11906
|
-
const
|
|
11907
|
-
const schemaDef = provider?.settings?.[key];
|
|
12057
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
11908
12058
|
const defaultVal = schemaDef ? schemaDef.default : void 0;
|
|
11909
12059
|
try {
|
|
11910
12060
|
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
@@ -11919,10 +12069,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11919
12069
|
* All resolved settings for a provider (default + user override)
|
|
11920
12070
|
*/
|
|
11921
12071
|
getSettings(type) {
|
|
11922
|
-
const
|
|
11923
|
-
if (!provider?.settings) return {};
|
|
12072
|
+
const settings = this.getSettingsSchema(type);
|
|
11924
12073
|
const result = {};
|
|
11925
|
-
for (const [key
|
|
12074
|
+
for (const [key] of Object.entries(settings)) {
|
|
11926
12075
|
result[key] = this.getSettingValue(type, key);
|
|
11927
12076
|
}
|
|
11928
12077
|
return result;
|
|
@@ -11931,11 +12080,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11931
12080
|
* Save provider setting value (writes to config.json)
|
|
11932
12081
|
*/
|
|
11933
12082
|
setSetting(type, key, value) {
|
|
11934
|
-
const
|
|
11935
|
-
const schemaDef = provider?.settings?.[key];
|
|
12083
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
11936
12084
|
if (!schemaDef) return false;
|
|
11937
12085
|
if (!schemaDef.public) return false;
|
|
11938
12086
|
if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
|
|
12087
|
+
if (schemaDef.type === "string" && typeof value !== "string") return false;
|
|
11939
12088
|
if (schemaDef.type === "number") {
|
|
11940
12089
|
if (typeof value !== "number") return false;
|
|
11941
12090
|
if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
|
|
@@ -11956,6 +12105,53 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11956
12105
|
return false;
|
|
11957
12106
|
}
|
|
11958
12107
|
}
|
|
12108
|
+
getOptionalStringSetting(type, key) {
|
|
12109
|
+
const value = this.getSettingValue(type, key);
|
|
12110
|
+
if (typeof value !== "string") return null;
|
|
12111
|
+
const trimmed = value.trim();
|
|
12112
|
+
return trimmed ? trimmed : null;
|
|
12113
|
+
}
|
|
12114
|
+
getSettingsSchema(type) {
|
|
12115
|
+
const provider = this.providers.get(type);
|
|
12116
|
+
if (!provider) return {};
|
|
12117
|
+
return {
|
|
12118
|
+
...this.getSyntheticSettings(type, provider),
|
|
12119
|
+
...provider.settings || {}
|
|
12120
|
+
};
|
|
12121
|
+
}
|
|
12122
|
+
getSyntheticSettings(type, provider) {
|
|
12123
|
+
const result = {};
|
|
12124
|
+
if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
|
|
12125
|
+
result.executablePath = {
|
|
12126
|
+
type: "string",
|
|
12127
|
+
default: "",
|
|
12128
|
+
public: true,
|
|
12129
|
+
label: "Executable path",
|
|
12130
|
+
description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
|
|
12131
|
+
};
|
|
12132
|
+
}
|
|
12133
|
+
if (provider.category === "ide") {
|
|
12134
|
+
if (provider.cli && !provider.settings?.cliPathOverride) {
|
|
12135
|
+
result.cliPathOverride = {
|
|
12136
|
+
type: "string",
|
|
12137
|
+
default: "",
|
|
12138
|
+
public: true,
|
|
12139
|
+
label: "CLI path override",
|
|
12140
|
+
description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
|
|
12141
|
+
};
|
|
12142
|
+
}
|
|
12143
|
+
if (provider.paths && !provider.settings?.appPathOverride) {
|
|
12144
|
+
result.appPathOverride = {
|
|
12145
|
+
type: "string",
|
|
12146
|
+
default: "",
|
|
12147
|
+
public: true,
|
|
12148
|
+
label: "App path override",
|
|
12149
|
+
description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
|
|
12150
|
+
};
|
|
12151
|
+
}
|
|
12152
|
+
}
|
|
12153
|
+
return result;
|
|
12154
|
+
}
|
|
11959
12155
|
// ─── Private ───────────────────────────────────
|
|
11960
12156
|
/**
|
|
11961
12157
|
* Find the on-disk directory for a provider by type.
|
|
@@ -11969,17 +12165,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11969
12165
|
for (const root of searchRoots) {
|
|
11970
12166
|
if (!fs6.existsSync(root)) continue;
|
|
11971
12167
|
const candidate = this.getProviderDir(root, cat, type);
|
|
11972
|
-
if (fs6.existsSync(
|
|
11973
|
-
const catDir =
|
|
12168
|
+
if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
|
|
12169
|
+
const catDir = path12.join(root, cat);
|
|
11974
12170
|
if (fs6.existsSync(catDir)) {
|
|
11975
12171
|
try {
|
|
11976
12172
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
11977
12173
|
if (!entry.isDirectory()) continue;
|
|
11978
|
-
const jsonPath =
|
|
12174
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
11979
12175
|
if (fs6.existsSync(jsonPath)) {
|
|
11980
12176
|
try {
|
|
11981
12177
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
11982
|
-
if (data.type === type) return
|
|
12178
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
11983
12179
|
} catch {
|
|
11984
12180
|
}
|
|
11985
12181
|
}
|
|
@@ -11996,7 +12192,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11996
12192
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
11997
12193
|
*/
|
|
11998
12194
|
buildScriptWrappersFromDir(dir) {
|
|
11999
|
-
const scriptsJs =
|
|
12195
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
12000
12196
|
if (fs6.existsSync(scriptsJs)) {
|
|
12001
12197
|
try {
|
|
12002
12198
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -12010,7 +12206,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12010
12206
|
for (const file of fs6.readdirSync(dir)) {
|
|
12011
12207
|
if (!file.endsWith(".js")) continue;
|
|
12012
12208
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
12013
|
-
const filePath =
|
|
12209
|
+
const filePath = path12.join(dir, file);
|
|
12014
12210
|
result[scriptName] = (...args) => {
|
|
12015
12211
|
try {
|
|
12016
12212
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -12070,7 +12266,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12070
12266
|
}
|
|
12071
12267
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
12072
12268
|
if (hasJson) {
|
|
12073
|
-
const jsonPath =
|
|
12269
|
+
const jsonPath = path12.join(d, "provider.json");
|
|
12074
12270
|
try {
|
|
12075
12271
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
12076
12272
|
const mod = JSON.parse(raw);
|
|
@@ -12083,7 +12279,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12083
12279
|
delete mod.extensionIdPattern_flags;
|
|
12084
12280
|
}
|
|
12085
12281
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
12086
|
-
const scriptsPath =
|
|
12282
|
+
const scriptsPath = path12.join(d, "scripts.js");
|
|
12087
12283
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
12088
12284
|
try {
|
|
12089
12285
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -12109,7 +12305,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12109
12305
|
if (!entry.isDirectory()) continue;
|
|
12110
12306
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
12111
12307
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
12112
|
-
scan(
|
|
12308
|
+
scan(path12.join(d, entry.name));
|
|
12113
12309
|
}
|
|
12114
12310
|
}
|
|
12115
12311
|
};
|
|
@@ -12205,17 +12401,17 @@ async function findFreePort(ports) {
|
|
|
12205
12401
|
throw new Error("No free port found");
|
|
12206
12402
|
}
|
|
12207
12403
|
function checkPortFree(port) {
|
|
12208
|
-
return new Promise((
|
|
12404
|
+
return new Promise((resolve12) => {
|
|
12209
12405
|
const server = net.createServer();
|
|
12210
12406
|
server.unref();
|
|
12211
|
-
server.on("error", () =>
|
|
12407
|
+
server.on("error", () => resolve12(false));
|
|
12212
12408
|
server.listen(port, "127.0.0.1", () => {
|
|
12213
|
-
server.close(() =>
|
|
12409
|
+
server.close(() => resolve12(true));
|
|
12214
12410
|
});
|
|
12215
12411
|
});
|
|
12216
12412
|
}
|
|
12217
12413
|
async function isCdpActive(port) {
|
|
12218
|
-
return new Promise((
|
|
12414
|
+
return new Promise((resolve12) => {
|
|
12219
12415
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
12220
12416
|
timeout: 2e3
|
|
12221
12417
|
}, (res) => {
|
|
@@ -12224,16 +12420,16 @@ async function isCdpActive(port) {
|
|
|
12224
12420
|
res.on("end", () => {
|
|
12225
12421
|
try {
|
|
12226
12422
|
const info = JSON.parse(data);
|
|
12227
|
-
|
|
12423
|
+
resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
12228
12424
|
} catch {
|
|
12229
|
-
|
|
12425
|
+
resolve12(false);
|
|
12230
12426
|
}
|
|
12231
12427
|
});
|
|
12232
12428
|
});
|
|
12233
|
-
req.on("error", () =>
|
|
12429
|
+
req.on("error", () => resolve12(false));
|
|
12234
12430
|
req.on("timeout", () => {
|
|
12235
12431
|
req.destroy();
|
|
12236
|
-
|
|
12432
|
+
resolve12(false);
|
|
12237
12433
|
});
|
|
12238
12434
|
});
|
|
12239
12435
|
}
|
|
@@ -12367,8 +12563,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12367
12563
|
const appNameMap = getMacAppIdentifiers();
|
|
12368
12564
|
const appName = appNameMap[ideId];
|
|
12369
12565
|
if (appName) {
|
|
12370
|
-
const storagePath =
|
|
12371
|
-
process.env.APPDATA ||
|
|
12566
|
+
const storagePath = path13.join(
|
|
12567
|
+
process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
|
|
12372
12568
|
appName,
|
|
12373
12569
|
"storage.json"
|
|
12374
12570
|
);
|
|
@@ -12392,7 +12588,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12392
12588
|
async function launchWithCdp(options = {}) {
|
|
12393
12589
|
const platform9 = os12.platform();
|
|
12394
12590
|
let targetIde;
|
|
12395
|
-
const ides = await detectIDEs();
|
|
12591
|
+
const ides = await detectIDEs(getProviderLoader());
|
|
12396
12592
|
if (options.ideId) {
|
|
12397
12593
|
targetIde = ides.find((i) => i.id === options.ideId && i.installed);
|
|
12398
12594
|
if (!targetIde) {
|
|
@@ -12546,9 +12742,9 @@ init_logger();
|
|
|
12546
12742
|
|
|
12547
12743
|
// src/logging/command-log.ts
|
|
12548
12744
|
import * as fs7 from "fs";
|
|
12549
|
-
import * as
|
|
12745
|
+
import * as path14 from "path";
|
|
12550
12746
|
import * as os13 from "os";
|
|
12551
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
12747
|
+
var LOG_DIR2 = process.platform === "win32" ? path14.join(process.env.LOCALAPPDATA || process.env.APPDATA || path14.join(os13.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path14.join(os13.homedir(), "Library", "Logs", "adhdev") : path14.join(os13.homedir(), ".local", "share", "adhdev", "logs");
|
|
12552
12748
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
12553
12749
|
var MAX_DAYS = 7;
|
|
12554
12750
|
try {
|
|
@@ -12586,13 +12782,13 @@ function getDateStr2() {
|
|
|
12586
12782
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
12587
12783
|
}
|
|
12588
12784
|
var currentDate2 = getDateStr2();
|
|
12589
|
-
var currentFile =
|
|
12785
|
+
var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12590
12786
|
var writeCount2 = 0;
|
|
12591
12787
|
function checkRotation() {
|
|
12592
12788
|
const today = getDateStr2();
|
|
12593
12789
|
if (today !== currentDate2) {
|
|
12594
12790
|
currentDate2 = today;
|
|
12595
|
-
currentFile =
|
|
12791
|
+
currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12596
12792
|
cleanOldFiles();
|
|
12597
12793
|
}
|
|
12598
12794
|
}
|
|
@@ -12606,7 +12802,7 @@ function cleanOldFiles() {
|
|
|
12606
12802
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
12607
12803
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
12608
12804
|
try {
|
|
12609
|
-
fs7.unlinkSync(
|
|
12805
|
+
fs7.unlinkSync(path14.join(LOG_DIR2, file));
|
|
12610
12806
|
} catch {
|
|
12611
12807
|
}
|
|
12612
12808
|
}
|
|
@@ -12698,12 +12894,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
|
12698
12894
|
}));
|
|
12699
12895
|
}
|
|
12700
12896
|
function buildAvailableProviders(providerLoader) {
|
|
12701
|
-
|
|
12897
|
+
const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
|
|
12898
|
+
return providers.map((provider) => ({
|
|
12702
12899
|
type: provider.type,
|
|
12703
12900
|
name: provider.displayName || provider.type,
|
|
12704
12901
|
displayName: provider.displayName || provider.type,
|
|
12705
12902
|
icon: provider.icon || "\u{1F4BB}",
|
|
12706
|
-
category: provider.category
|
|
12903
|
+
category: provider.category,
|
|
12904
|
+
...provider.installed !== void 0 ? { installed: provider.installed } : {},
|
|
12905
|
+
...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
|
|
12707
12906
|
}));
|
|
12708
12907
|
}
|
|
12709
12908
|
function parseMessageTime(value) {
|
|
@@ -12831,13 +13030,13 @@ import { execFileSync } from "child_process";
|
|
|
12831
13030
|
import { spawn as spawn3 } from "child_process";
|
|
12832
13031
|
import * as fs8 from "fs";
|
|
12833
13032
|
import * as os15 from "os";
|
|
12834
|
-
import * as
|
|
13033
|
+
import * as path15 from "path";
|
|
12835
13034
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
12836
13035
|
function getUpgradeLogPath() {
|
|
12837
13036
|
const home = os15.homedir();
|
|
12838
|
-
const dir =
|
|
13037
|
+
const dir = path15.join(home, ".adhdev");
|
|
12839
13038
|
fs8.mkdirSync(dir, { recursive: true });
|
|
12840
|
-
return
|
|
13039
|
+
return path15.join(dir, "daemon-upgrade.log");
|
|
12841
13040
|
}
|
|
12842
13041
|
function appendUpgradeLog(message) {
|
|
12843
13042
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -12870,14 +13069,14 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
12870
13069
|
while (Date.now() - start < timeoutMs) {
|
|
12871
13070
|
try {
|
|
12872
13071
|
process.kill(pid, 0);
|
|
12873
|
-
await new Promise((
|
|
13072
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
12874
13073
|
} catch {
|
|
12875
13074
|
return;
|
|
12876
13075
|
}
|
|
12877
13076
|
}
|
|
12878
13077
|
}
|
|
12879
13078
|
function stopSessionHostProcesses(appName) {
|
|
12880
|
-
const pidFile =
|
|
13079
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
12881
13080
|
try {
|
|
12882
13081
|
if (fs8.existsSync(pidFile)) {
|
|
12883
13082
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -12906,7 +13105,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
12906
13105
|
}
|
|
12907
13106
|
}
|
|
12908
13107
|
function removeDaemonPidFile() {
|
|
12909
|
-
const pidFile =
|
|
13108
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
|
|
12910
13109
|
try {
|
|
12911
13110
|
fs8.unlinkSync(pidFile);
|
|
12912
13111
|
} catch {
|
|
@@ -12917,7 +13116,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
12917
13116
|
const npmRoot = execFileSync(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
12918
13117
|
if (!npmRoot) return;
|
|
12919
13118
|
const npmPrefix = execFileSync(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
12920
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
13119
|
+
const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
|
|
12921
13120
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
12922
13121
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
12923
13122
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -12925,25 +13124,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
12925
13124
|
}
|
|
12926
13125
|
if (pkgName.startsWith("@")) {
|
|
12927
13126
|
const [scope, name] = pkgName.split("/");
|
|
12928
|
-
const scopeDir =
|
|
13127
|
+
const scopeDir = path15.join(npmRoot, scope);
|
|
12929
13128
|
if (!fs8.existsSync(scopeDir)) return;
|
|
12930
13129
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
12931
13130
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
12932
|
-
fs8.rmSync(
|
|
12933
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
13131
|
+
fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
|
|
13132
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
|
|
12934
13133
|
}
|
|
12935
13134
|
} else {
|
|
12936
13135
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
12937
13136
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
12938
|
-
fs8.rmSync(
|
|
12939
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
13137
|
+
fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
|
|
13138
|
+
appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
|
|
12940
13139
|
}
|
|
12941
13140
|
}
|
|
12942
13141
|
if (fs8.existsSync(binDir)) {
|
|
12943
13142
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
12944
13143
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
12945
|
-
fs8.rmSync(
|
|
12946
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
13144
|
+
fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
|
|
13145
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
|
|
12947
13146
|
}
|
|
12948
13147
|
}
|
|
12949
13148
|
}
|
|
@@ -12985,7 +13184,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
12985
13184
|
appendUpgradeLog(installOutput.trim());
|
|
12986
13185
|
}
|
|
12987
13186
|
if (process.platform === "win32") {
|
|
12988
|
-
await new Promise((
|
|
13187
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
12989
13188
|
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
12990
13189
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
12991
13190
|
}
|
|
@@ -13263,6 +13462,12 @@ var DaemonCommandRouter = class {
|
|
|
13263
13462
|
if (!ideType) throw new Error("ideType required");
|
|
13264
13463
|
const killProcess = args?.killProcess !== false;
|
|
13265
13464
|
await this.stopIde(ideType, killProcess);
|
|
13465
|
+
try {
|
|
13466
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13467
|
+
this.deps.detectedIdes.value = results;
|
|
13468
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13469
|
+
} catch {
|
|
13470
|
+
}
|
|
13266
13471
|
return { success: true, ideType, stopped: true, processKilled: killProcess };
|
|
13267
13472
|
}
|
|
13268
13473
|
// ─── IDE restart ───
|
|
@@ -13305,6 +13510,12 @@ var DaemonCommandRouter = class {
|
|
|
13305
13510
|
}
|
|
13306
13511
|
}
|
|
13307
13512
|
this.deps.onIdeConnected?.();
|
|
13513
|
+
try {
|
|
13514
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13515
|
+
this.deps.detectedIdes.value = results;
|
|
13516
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13517
|
+
} catch {
|
|
13518
|
+
}
|
|
13308
13519
|
if (result.success && resolvedWorkspace) {
|
|
13309
13520
|
try {
|
|
13310
13521
|
const next = appendRecentActivity(loadState(), {
|
|
@@ -13332,8 +13543,9 @@ var DaemonCommandRouter = class {
|
|
|
13332
13543
|
}
|
|
13333
13544
|
// ─── Detect IDEs ───
|
|
13334
13545
|
case "detect_ides": {
|
|
13335
|
-
const results = await detectIDEs();
|
|
13546
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13336
13547
|
this.deps.detectedIdes.value = results;
|
|
13548
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13337
13549
|
return { success: true, detectedInfo: results };
|
|
13338
13550
|
}
|
|
13339
13551
|
// ─── Set User Name ───
|
|
@@ -13847,7 +14059,10 @@ var ProviderStreamAdapter = class {
|
|
|
13847
14059
|
const raw = await evaluate(script, 1e4);
|
|
13848
14060
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
13849
14061
|
if (data?.error) return [];
|
|
13850
|
-
|
|
14062
|
+
if (Array.isArray(data)) return data;
|
|
14063
|
+
if (Array.isArray(data?.sessions)) return data.sessions;
|
|
14064
|
+
if (Array.isArray(data?.chats)) return data.chats;
|
|
14065
|
+
return [];
|
|
13851
14066
|
} catch {
|
|
13852
14067
|
return [];
|
|
13853
14068
|
}
|
|
@@ -13855,7 +14070,17 @@ var ProviderStreamAdapter = class {
|
|
|
13855
14070
|
async switchSession(evaluate, sessionId) {
|
|
13856
14071
|
const script = this.callScript("switchSession", sessionId);
|
|
13857
14072
|
if (!script) return false;
|
|
13858
|
-
|
|
14073
|
+
const raw = await evaluate(script, 1e4);
|
|
14074
|
+
const data = this.parseMaybeJson(raw);
|
|
14075
|
+
if (data === true) return true;
|
|
14076
|
+
if (typeof data === "string") {
|
|
14077
|
+
const normalized = data.trim().toLowerCase();
|
|
14078
|
+
return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
|
|
14079
|
+
}
|
|
14080
|
+
if (data && typeof data === "object") {
|
|
14081
|
+
return data.switched === true || data.success === true || data.ok === true;
|
|
14082
|
+
}
|
|
14083
|
+
return false;
|
|
13859
14084
|
}
|
|
13860
14085
|
async focusEditor(evaluate) {
|
|
13861
14086
|
const script = this.callScript("focusEditor");
|
|
@@ -14545,11 +14770,11 @@ var ProviderInstanceManager = class {
|
|
|
14545
14770
|
|
|
14546
14771
|
// src/providers/version-archive.ts
|
|
14547
14772
|
import * as fs10 from "fs";
|
|
14548
|
-
import * as
|
|
14773
|
+
import * as path16 from "path";
|
|
14549
14774
|
import * as os16 from "os";
|
|
14550
14775
|
import { execSync as execSync5 } from "child_process";
|
|
14551
14776
|
import { platform as platform7 } from "os";
|
|
14552
|
-
var ARCHIVE_PATH =
|
|
14777
|
+
var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
14553
14778
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
14554
14779
|
var VersionArchive = class {
|
|
14555
14780
|
history = {};
|
|
@@ -14596,7 +14821,7 @@ var VersionArchive = class {
|
|
|
14596
14821
|
}
|
|
14597
14822
|
save() {
|
|
14598
14823
|
try {
|
|
14599
|
-
fs10.mkdirSync(
|
|
14824
|
+
fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
|
|
14600
14825
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
14601
14826
|
} catch {
|
|
14602
14827
|
}
|
|
@@ -14637,7 +14862,7 @@ function checkPathExists2(paths) {
|
|
|
14637
14862
|
for (const p of paths) {
|
|
14638
14863
|
if (p.includes("*")) {
|
|
14639
14864
|
const home = os16.homedir();
|
|
14640
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
14865
|
+
const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
|
|
14641
14866
|
if (fs10.existsSync(resolved)) return resolved;
|
|
14642
14867
|
} else {
|
|
14643
14868
|
if (fs10.existsSync(p)) return p;
|
|
@@ -14647,7 +14872,7 @@ function checkPathExists2(paths) {
|
|
|
14647
14872
|
}
|
|
14648
14873
|
function getMacAppVersion(appPath) {
|
|
14649
14874
|
if (platform7() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
14650
|
-
const plistPath =
|
|
14875
|
+
const plistPath = path16.join(appPath, "Contents", "Info.plist");
|
|
14651
14876
|
if (!fs10.existsSync(plistPath)) return null;
|
|
14652
14877
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
14653
14878
|
return raw || null;
|
|
@@ -14674,7 +14899,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14674
14899
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
14675
14900
|
let resolvedBin = cliBin;
|
|
14676
14901
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
14677
|
-
const bundled =
|
|
14902
|
+
const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
14678
14903
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
14679
14904
|
}
|
|
14680
14905
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -14715,7 +14940,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14715
14940
|
// src/daemon/dev-server.ts
|
|
14716
14941
|
import * as http2 from "http";
|
|
14717
14942
|
import * as fs14 from "fs";
|
|
14718
|
-
import * as
|
|
14943
|
+
import * as path20 from "path";
|
|
14719
14944
|
|
|
14720
14945
|
// src/daemon/scaffold-template.ts
|
|
14721
14946
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -15052,7 +15277,7 @@ init_logger();
|
|
|
15052
15277
|
// src/daemon/dev-cdp-handlers.ts
|
|
15053
15278
|
init_logger();
|
|
15054
15279
|
import * as fs11 from "fs";
|
|
15055
|
-
import * as
|
|
15280
|
+
import * as path17 from "path";
|
|
15056
15281
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
15057
15282
|
const body = await ctx.readBody(req);
|
|
15058
15283
|
const { expression, timeout, ideType } = body;
|
|
@@ -15230,17 +15455,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
15230
15455
|
return;
|
|
15231
15456
|
}
|
|
15232
15457
|
let scriptsPath = "";
|
|
15233
|
-
const directScripts =
|
|
15458
|
+
const directScripts = path17.join(dir, "scripts.js");
|
|
15234
15459
|
if (fs11.existsSync(directScripts)) {
|
|
15235
15460
|
scriptsPath = directScripts;
|
|
15236
15461
|
} else {
|
|
15237
|
-
const scriptsDir =
|
|
15462
|
+
const scriptsDir = path17.join(dir, "scripts");
|
|
15238
15463
|
if (fs11.existsSync(scriptsDir)) {
|
|
15239
15464
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
15240
|
-
return fs11.statSync(
|
|
15465
|
+
return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
15241
15466
|
}).sort().reverse();
|
|
15242
15467
|
for (const ver of versions) {
|
|
15243
|
-
const p =
|
|
15468
|
+
const p = path17.join(scriptsDir, ver, "scripts.js");
|
|
15244
15469
|
if (fs11.existsSync(p)) {
|
|
15245
15470
|
scriptsPath = p;
|
|
15246
15471
|
break;
|
|
@@ -16059,7 +16284,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
16059
16284
|
|
|
16060
16285
|
// src/daemon/dev-cli-debug.ts
|
|
16061
16286
|
import * as fs12 from "fs";
|
|
16062
|
-
import * as
|
|
16287
|
+
import * as path18 from "path";
|
|
16063
16288
|
function slugifyFixtureName(value) {
|
|
16064
16289
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
16065
16290
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -16069,11 +16294,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
16069
16294
|
if (!providerDir) {
|
|
16070
16295
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
16071
16296
|
}
|
|
16072
|
-
return
|
|
16297
|
+
return path18.join(providerDir, "fixtures");
|
|
16073
16298
|
}
|
|
16074
16299
|
function readCliFixture(ctx, type, name) {
|
|
16075
16300
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
16076
|
-
const filePath =
|
|
16301
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
16077
16302
|
if (!fs12.existsSync(filePath)) {
|
|
16078
16303
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
16079
16304
|
}
|
|
@@ -16233,7 +16458,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
16233
16458
|
return { target, instance, adapter };
|
|
16234
16459
|
}
|
|
16235
16460
|
function sleep(ms) {
|
|
16236
|
-
return new Promise((
|
|
16461
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
16237
16462
|
}
|
|
16238
16463
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
16239
16464
|
const startedAt = Date.now();
|
|
@@ -16832,7 +17057,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
16832
17057
|
},
|
|
16833
17058
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
16834
17059
|
};
|
|
16835
|
-
const filePath =
|
|
17060
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
16836
17061
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
16837
17062
|
ctx.json(res, 200, {
|
|
16838
17063
|
saved: true,
|
|
@@ -16856,7 +17081,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
16856
17081
|
return;
|
|
16857
17082
|
}
|
|
16858
17083
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
16859
|
-
const fullPath =
|
|
17084
|
+
const fullPath = path18.join(fixtureDir, file);
|
|
16860
17085
|
try {
|
|
16861
17086
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
16862
17087
|
return {
|
|
@@ -16992,7 +17217,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
16992
17217
|
|
|
16993
17218
|
// src/daemon/dev-auto-implement.ts
|
|
16994
17219
|
import * as fs13 from "fs";
|
|
16995
|
-
import * as
|
|
17220
|
+
import * as path19 from "path";
|
|
16996
17221
|
import * as os17 from "os";
|
|
16997
17222
|
function getAutoImplPid(ctx) {
|
|
16998
17223
|
const proc = ctx.autoImplProcess;
|
|
@@ -17032,22 +17257,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
17032
17257
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
17033
17258
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
17034
17259
|
try {
|
|
17035
|
-
return fs13.statSync(
|
|
17260
|
+
return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
|
|
17036
17261
|
} catch {
|
|
17037
17262
|
return false;
|
|
17038
17263
|
}
|
|
17039
17264
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
17040
17265
|
if (versions.length === 0) return null;
|
|
17041
|
-
return
|
|
17266
|
+
return path19.join(scriptsDir, versions[0]);
|
|
17042
17267
|
}
|
|
17043
17268
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
17044
|
-
const canonicalUserDir =
|
|
17045
|
-
const desiredDir = requestedDir ?
|
|
17046
|
-
const upstreamRoot =
|
|
17047
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
17269
|
+
const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
17270
|
+
const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
|
|
17271
|
+
const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
|
|
17272
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
|
|
17048
17273
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
17049
17274
|
}
|
|
17050
|
-
if (
|
|
17275
|
+
if (path19.basename(desiredDir) !== type) {
|
|
17051
17276
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
17052
17277
|
}
|
|
17053
17278
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -17055,11 +17280,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
17055
17280
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
17056
17281
|
}
|
|
17057
17282
|
if (!fs13.existsSync(desiredDir)) {
|
|
17058
|
-
fs13.mkdirSync(
|
|
17283
|
+
fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
|
|
17059
17284
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
17060
17285
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
17061
17286
|
}
|
|
17062
|
-
const providerJson =
|
|
17287
|
+
const providerJson = path19.join(desiredDir, "provider.json");
|
|
17063
17288
|
if (!fs13.existsSync(providerJson)) {
|
|
17064
17289
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
17065
17290
|
}
|
|
@@ -17082,13 +17307,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
17082
17307
|
const refDir = ctx.findProviderDir(referenceType);
|
|
17083
17308
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
17084
17309
|
const referenceScripts = {};
|
|
17085
|
-
const scriptsDir =
|
|
17310
|
+
const scriptsDir = path19.join(refDir, "scripts");
|
|
17086
17311
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
17087
17312
|
if (!latestDir) return referenceScripts;
|
|
17088
17313
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
17089
17314
|
if (!file.endsWith(".js")) continue;
|
|
17090
17315
|
try {
|
|
17091
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
17316
|
+
referenceScripts[file] = fs13.readFileSync(path19.join(latestDir, file), "utf-8");
|
|
17092
17317
|
} catch {
|
|
17093
17318
|
}
|
|
17094
17319
|
}
|
|
@@ -17196,9 +17421,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
17196
17421
|
});
|
|
17197
17422
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
17198
17423
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
17199
|
-
const tmpDir =
|
|
17424
|
+
const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
17200
17425
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
17201
|
-
const promptFile =
|
|
17426
|
+
const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
17202
17427
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
17203
17428
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
17204
17429
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -17625,7 +17850,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17625
17850
|
setMode: "set_mode.js"
|
|
17626
17851
|
};
|
|
17627
17852
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
17628
|
-
const scriptsDir =
|
|
17853
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
17629
17854
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
17630
17855
|
if (latestScriptsDir) {
|
|
17631
17856
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -17636,7 +17861,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17636
17861
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
17637
17862
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
17638
17863
|
try {
|
|
17639
|
-
const content = fs13.readFileSync(
|
|
17864
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17640
17865
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
17641
17866
|
lines.push("```javascript");
|
|
17642
17867
|
lines.push(content);
|
|
@@ -17653,7 +17878,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17653
17878
|
lines.push("");
|
|
17654
17879
|
for (const file of refFiles) {
|
|
17655
17880
|
try {
|
|
17656
|
-
const content = fs13.readFileSync(
|
|
17881
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17657
17882
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
17658
17883
|
lines.push("```javascript");
|
|
17659
17884
|
lines.push(content);
|
|
@@ -17694,10 +17919,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17694
17919
|
lines.push("");
|
|
17695
17920
|
}
|
|
17696
17921
|
}
|
|
17697
|
-
const docsDir =
|
|
17922
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
17698
17923
|
const loadGuide = (name) => {
|
|
17699
17924
|
try {
|
|
17700
|
-
const p =
|
|
17925
|
+
const p = path19.join(docsDir, name);
|
|
17701
17926
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
17702
17927
|
} catch {
|
|
17703
17928
|
}
|
|
@@ -17932,7 +18157,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17932
18157
|
parseApproval: "parse_approval.js"
|
|
17933
18158
|
};
|
|
17934
18159
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
17935
|
-
const scriptsDir =
|
|
18160
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
17936
18161
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
17937
18162
|
if (latestScriptsDir) {
|
|
17938
18163
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -17944,7 +18169,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17944
18169
|
if (!file.endsWith(".js")) continue;
|
|
17945
18170
|
if (!targetFileNames.has(file)) continue;
|
|
17946
18171
|
try {
|
|
17947
|
-
const content = fs13.readFileSync(
|
|
18172
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17948
18173
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
17949
18174
|
lines.push("```javascript");
|
|
17950
18175
|
lines.push(content);
|
|
@@ -17960,7 +18185,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17960
18185
|
lines.push("");
|
|
17961
18186
|
for (const file of refFiles) {
|
|
17962
18187
|
try {
|
|
17963
|
-
const content = fs13.readFileSync(
|
|
18188
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17964
18189
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
17965
18190
|
lines.push("```javascript");
|
|
17966
18191
|
lines.push(content);
|
|
@@ -17993,10 +18218,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17993
18218
|
lines.push("");
|
|
17994
18219
|
}
|
|
17995
18220
|
}
|
|
17996
|
-
const docsDir =
|
|
18221
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
17997
18222
|
const loadGuide = (name) => {
|
|
17998
18223
|
try {
|
|
17999
|
-
const p =
|
|
18224
|
+
const p = path19.join(docsDir, name);
|
|
18000
18225
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
18001
18226
|
} catch {
|
|
18002
18227
|
}
|
|
@@ -18407,8 +18632,8 @@ var DevServer = class _DevServer {
|
|
|
18407
18632
|
}
|
|
18408
18633
|
getEndpointList() {
|
|
18409
18634
|
return this.routes.map((r) => {
|
|
18410
|
-
const
|
|
18411
|
-
return `${r.method.padEnd(5)} ${
|
|
18635
|
+
const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
18636
|
+
return `${r.method.padEnd(5)} ${path21}`;
|
|
18412
18637
|
});
|
|
18413
18638
|
}
|
|
18414
18639
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -18439,15 +18664,15 @@ var DevServer = class _DevServer {
|
|
|
18439
18664
|
this.json(res, 500, { error: e.message });
|
|
18440
18665
|
}
|
|
18441
18666
|
});
|
|
18442
|
-
return new Promise((
|
|
18667
|
+
return new Promise((resolve12, reject) => {
|
|
18443
18668
|
this.server.listen(port, "127.0.0.1", () => {
|
|
18444
18669
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
18445
|
-
|
|
18670
|
+
resolve12();
|
|
18446
18671
|
});
|
|
18447
18672
|
this.server.on("error", (e) => {
|
|
18448
18673
|
if (e.code === "EADDRINUSE") {
|
|
18449
18674
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
18450
|
-
|
|
18675
|
+
resolve12();
|
|
18451
18676
|
} else {
|
|
18452
18677
|
reject(e);
|
|
18453
18678
|
}
|
|
@@ -18530,20 +18755,20 @@ var DevServer = class _DevServer {
|
|
|
18530
18755
|
child.stderr?.on("data", (d) => {
|
|
18531
18756
|
stderr += d.toString().slice(0, 2e3);
|
|
18532
18757
|
});
|
|
18533
|
-
await new Promise((
|
|
18758
|
+
await new Promise((resolve12) => {
|
|
18534
18759
|
const timer = setTimeout(() => {
|
|
18535
18760
|
child.kill();
|
|
18536
|
-
|
|
18761
|
+
resolve12();
|
|
18537
18762
|
}, 3e3);
|
|
18538
18763
|
child.on("exit", () => {
|
|
18539
18764
|
clearTimeout(timer);
|
|
18540
|
-
|
|
18765
|
+
resolve12();
|
|
18541
18766
|
});
|
|
18542
18767
|
child.stdout?.once("data", () => {
|
|
18543
18768
|
setTimeout(() => {
|
|
18544
18769
|
child.kill();
|
|
18545
18770
|
clearTimeout(timer);
|
|
18546
|
-
|
|
18771
|
+
resolve12();
|
|
18547
18772
|
}, 500);
|
|
18548
18773
|
});
|
|
18549
18774
|
});
|
|
@@ -18690,12 +18915,12 @@ var DevServer = class _DevServer {
|
|
|
18690
18915
|
// ─── DevConsole SPA ───
|
|
18691
18916
|
getConsoleDistDir() {
|
|
18692
18917
|
const candidates = [
|
|
18693
|
-
|
|
18694
|
-
|
|
18695
|
-
|
|
18918
|
+
path20.resolve(__dirname, "../../web-devconsole/dist"),
|
|
18919
|
+
path20.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
18920
|
+
path20.join(process.cwd(), "packages/web-devconsole/dist")
|
|
18696
18921
|
];
|
|
18697
18922
|
for (const dir of candidates) {
|
|
18698
|
-
if (fs14.existsSync(
|
|
18923
|
+
if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
|
|
18699
18924
|
}
|
|
18700
18925
|
return null;
|
|
18701
18926
|
}
|
|
@@ -18705,7 +18930,7 @@ var DevServer = class _DevServer {
|
|
|
18705
18930
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
18706
18931
|
return;
|
|
18707
18932
|
}
|
|
18708
|
-
const htmlPath =
|
|
18933
|
+
const htmlPath = path20.join(distDir, "index.html");
|
|
18709
18934
|
try {
|
|
18710
18935
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
18711
18936
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -18730,15 +18955,15 @@ var DevServer = class _DevServer {
|
|
|
18730
18955
|
this.json(res, 404, { error: "Not found" });
|
|
18731
18956
|
return;
|
|
18732
18957
|
}
|
|
18733
|
-
const safePath =
|
|
18734
|
-
const filePath =
|
|
18958
|
+
const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
|
|
18959
|
+
const filePath = path20.join(distDir, safePath);
|
|
18735
18960
|
if (!filePath.startsWith(distDir)) {
|
|
18736
18961
|
this.json(res, 403, { error: "Forbidden" });
|
|
18737
18962
|
return;
|
|
18738
18963
|
}
|
|
18739
18964
|
try {
|
|
18740
18965
|
const content = fs14.readFileSync(filePath);
|
|
18741
|
-
const ext =
|
|
18966
|
+
const ext = path20.extname(filePath);
|
|
18742
18967
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
18743
18968
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
18744
18969
|
res.end(content);
|
|
@@ -18851,9 +19076,9 @@ var DevServer = class _DevServer {
|
|
|
18851
19076
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18852
19077
|
if (entry.isDirectory()) {
|
|
18853
19078
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
18854
|
-
scan(
|
|
19079
|
+
scan(path20.join(d, entry.name), rel);
|
|
18855
19080
|
} else {
|
|
18856
|
-
const stat = fs14.statSync(
|
|
19081
|
+
const stat = fs14.statSync(path20.join(d, entry.name));
|
|
18857
19082
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
18858
19083
|
}
|
|
18859
19084
|
}
|
|
@@ -18876,7 +19101,7 @@ var DevServer = class _DevServer {
|
|
|
18876
19101
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18877
19102
|
return;
|
|
18878
19103
|
}
|
|
18879
|
-
const fullPath =
|
|
19104
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18880
19105
|
if (!fullPath.startsWith(dir)) {
|
|
18881
19106
|
this.json(res, 403, { error: "Forbidden" });
|
|
18882
19107
|
return;
|
|
@@ -18901,14 +19126,14 @@ var DevServer = class _DevServer {
|
|
|
18901
19126
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18902
19127
|
return;
|
|
18903
19128
|
}
|
|
18904
|
-
const fullPath =
|
|
19129
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18905
19130
|
if (!fullPath.startsWith(dir)) {
|
|
18906
19131
|
this.json(res, 403, { error: "Forbidden" });
|
|
18907
19132
|
return;
|
|
18908
19133
|
}
|
|
18909
19134
|
try {
|
|
18910
19135
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
18911
|
-
fs14.mkdirSync(
|
|
19136
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
18912
19137
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
18913
19138
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
18914
19139
|
this.providerLoader.reload();
|
|
@@ -18925,7 +19150,7 @@ var DevServer = class _DevServer {
|
|
|
18925
19150
|
return;
|
|
18926
19151
|
}
|
|
18927
19152
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
18928
|
-
const p =
|
|
19153
|
+
const p = path20.join(dir, name);
|
|
18929
19154
|
if (fs14.existsSync(p)) {
|
|
18930
19155
|
const source = fs14.readFileSync(p, "utf-8");
|
|
18931
19156
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -18946,8 +19171,8 @@ var DevServer = class _DevServer {
|
|
|
18946
19171
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
18947
19172
|
return;
|
|
18948
19173
|
}
|
|
18949
|
-
const target = fs14.existsSync(
|
|
18950
|
-
const targetPath =
|
|
19174
|
+
const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
19175
|
+
const targetPath = path20.join(dir, target);
|
|
18951
19176
|
try {
|
|
18952
19177
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
18953
19178
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -19052,14 +19277,14 @@ var DevServer = class _DevServer {
|
|
|
19052
19277
|
child.stderr?.on("data", (d) => {
|
|
19053
19278
|
stderr += d.toString();
|
|
19054
19279
|
});
|
|
19055
|
-
await new Promise((
|
|
19280
|
+
await new Promise((resolve12) => {
|
|
19056
19281
|
const timer = setTimeout(() => {
|
|
19057
19282
|
child.kill();
|
|
19058
|
-
|
|
19283
|
+
resolve12();
|
|
19059
19284
|
}, timeout);
|
|
19060
19285
|
child.on("exit", () => {
|
|
19061
19286
|
clearTimeout(timer);
|
|
19062
|
-
|
|
19287
|
+
resolve12();
|
|
19063
19288
|
});
|
|
19064
19289
|
});
|
|
19065
19290
|
const elapsed = Date.now() - start;
|
|
@@ -19107,7 +19332,7 @@ var DevServer = class _DevServer {
|
|
|
19107
19332
|
}
|
|
19108
19333
|
let targetDir;
|
|
19109
19334
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
19110
|
-
const jsonPath =
|
|
19335
|
+
const jsonPath = path20.join(targetDir, "provider.json");
|
|
19111
19336
|
if (fs14.existsSync(jsonPath)) {
|
|
19112
19337
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
19113
19338
|
return;
|
|
@@ -19119,8 +19344,8 @@ var DevServer = class _DevServer {
|
|
|
19119
19344
|
const createdFiles = ["provider.json"];
|
|
19120
19345
|
if (result.files) {
|
|
19121
19346
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
19122
|
-
const fullPath =
|
|
19123
|
-
fs14.mkdirSync(
|
|
19347
|
+
const fullPath = path20.join(targetDir, relPath);
|
|
19348
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
19124
19349
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
19125
19350
|
createdFiles.push(relPath);
|
|
19126
19351
|
}
|
|
@@ -19173,22 +19398,22 @@ var DevServer = class _DevServer {
|
|
|
19173
19398
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
19174
19399
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
19175
19400
|
try {
|
|
19176
|
-
return fs14.statSync(
|
|
19401
|
+
return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
19177
19402
|
} catch {
|
|
19178
19403
|
return false;
|
|
19179
19404
|
}
|
|
19180
19405
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
19181
19406
|
if (versions.length === 0) return null;
|
|
19182
|
-
return
|
|
19407
|
+
return path20.join(scriptsDir, versions[0]);
|
|
19183
19408
|
}
|
|
19184
19409
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
19185
|
-
const canonicalUserDir =
|
|
19186
|
-
const desiredDir = requestedDir ?
|
|
19187
|
-
const upstreamRoot =
|
|
19188
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
19410
|
+
const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
19411
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
19412
|
+
const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
|
|
19413
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
19189
19414
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
19190
19415
|
}
|
|
19191
|
-
if (
|
|
19416
|
+
if (path20.basename(desiredDir) !== type) {
|
|
19192
19417
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
19193
19418
|
}
|
|
19194
19419
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -19196,11 +19421,11 @@ var DevServer = class _DevServer {
|
|
|
19196
19421
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
19197
19422
|
}
|
|
19198
19423
|
if (!fs14.existsSync(desiredDir)) {
|
|
19199
|
-
fs14.mkdirSync(
|
|
19424
|
+
fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
19200
19425
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
19201
19426
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
19202
19427
|
}
|
|
19203
|
-
const providerJson =
|
|
19428
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
19204
19429
|
if (!fs14.existsSync(providerJson)) {
|
|
19205
19430
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
19206
19431
|
}
|
|
@@ -19248,7 +19473,7 @@ var DevServer = class _DevServer {
|
|
|
19248
19473
|
setMode: "set_mode.js"
|
|
19249
19474
|
};
|
|
19250
19475
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19251
|
-
const scriptsDir =
|
|
19476
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19252
19477
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19253
19478
|
if (latestScriptsDir) {
|
|
19254
19479
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19259,7 +19484,7 @@ var DevServer = class _DevServer {
|
|
|
19259
19484
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
19260
19485
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
19261
19486
|
try {
|
|
19262
|
-
const content = fs14.readFileSync(
|
|
19487
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19263
19488
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19264
19489
|
lines.push("```javascript");
|
|
19265
19490
|
lines.push(content);
|
|
@@ -19276,7 +19501,7 @@ var DevServer = class _DevServer {
|
|
|
19276
19501
|
lines.push("");
|
|
19277
19502
|
for (const file of refFiles) {
|
|
19278
19503
|
try {
|
|
19279
|
-
const content = fs14.readFileSync(
|
|
19504
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19280
19505
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19281
19506
|
lines.push("```javascript");
|
|
19282
19507
|
lines.push(content);
|
|
@@ -19317,10 +19542,10 @@ var DevServer = class _DevServer {
|
|
|
19317
19542
|
lines.push("");
|
|
19318
19543
|
}
|
|
19319
19544
|
}
|
|
19320
|
-
const docsDir =
|
|
19545
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19321
19546
|
const loadGuide = (name) => {
|
|
19322
19547
|
try {
|
|
19323
|
-
const p =
|
|
19548
|
+
const p = path20.join(docsDir, name);
|
|
19324
19549
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19325
19550
|
} catch {
|
|
19326
19551
|
}
|
|
@@ -19494,7 +19719,7 @@ var DevServer = class _DevServer {
|
|
|
19494
19719
|
parseApproval: "parse_approval.js"
|
|
19495
19720
|
};
|
|
19496
19721
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19497
|
-
const scriptsDir =
|
|
19722
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19498
19723
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19499
19724
|
if (latestScriptsDir) {
|
|
19500
19725
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19506,7 +19731,7 @@ var DevServer = class _DevServer {
|
|
|
19506
19731
|
if (!file.endsWith(".js")) continue;
|
|
19507
19732
|
if (!targetFileNames.has(file)) continue;
|
|
19508
19733
|
try {
|
|
19509
|
-
const content = fs14.readFileSync(
|
|
19734
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19510
19735
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19511
19736
|
lines.push("```javascript");
|
|
19512
19737
|
lines.push(content);
|
|
@@ -19522,7 +19747,7 @@ var DevServer = class _DevServer {
|
|
|
19522
19747
|
lines.push("");
|
|
19523
19748
|
for (const file of refFiles) {
|
|
19524
19749
|
try {
|
|
19525
|
-
const content = fs14.readFileSync(
|
|
19750
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19526
19751
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19527
19752
|
lines.push("```javascript");
|
|
19528
19753
|
lines.push(content);
|
|
@@ -19555,10 +19780,10 @@ var DevServer = class _DevServer {
|
|
|
19555
19780
|
lines.push("");
|
|
19556
19781
|
}
|
|
19557
19782
|
}
|
|
19558
|
-
const docsDir =
|
|
19783
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19559
19784
|
const loadGuide = (name) => {
|
|
19560
19785
|
try {
|
|
19561
|
-
const p =
|
|
19786
|
+
const p = path20.join(docsDir, name);
|
|
19562
19787
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19563
19788
|
} catch {
|
|
19564
19789
|
}
|
|
@@ -19734,14 +19959,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
19734
19959
|
res.end(JSON.stringify(data, null, 2));
|
|
19735
19960
|
}
|
|
19736
19961
|
async readBody(req) {
|
|
19737
|
-
return new Promise((
|
|
19962
|
+
return new Promise((resolve12) => {
|
|
19738
19963
|
let body = "";
|
|
19739
19964
|
req.on("data", (chunk) => body += chunk);
|
|
19740
19965
|
req.on("end", () => {
|
|
19741
19966
|
try {
|
|
19742
|
-
|
|
19967
|
+
resolve12(JSON.parse(body));
|
|
19743
19968
|
} catch {
|
|
19744
|
-
|
|
19969
|
+
resolve12({});
|
|
19745
19970
|
}
|
|
19746
19971
|
});
|
|
19747
19972
|
});
|
|
@@ -20214,7 +20439,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
20214
20439
|
const deadline = Date.now() + timeoutMs;
|
|
20215
20440
|
while (Date.now() < deadline) {
|
|
20216
20441
|
if (await canConnect(endpoint)) return;
|
|
20217
|
-
await new Promise((
|
|
20442
|
+
await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
|
|
20218
20443
|
}
|
|
20219
20444
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
20220
20445
|
}
|
|
@@ -20370,10 +20595,10 @@ async function installExtension(ide, extension) {
|
|
|
20370
20595
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
20371
20596
|
const fs15 = await import("fs");
|
|
20372
20597
|
fs15.writeFileSync(vsixPath, buffer);
|
|
20373
|
-
return new Promise((
|
|
20598
|
+
return new Promise((resolve12) => {
|
|
20374
20599
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
20375
20600
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
20376
|
-
|
|
20601
|
+
resolve12({
|
|
20377
20602
|
extensionId: extension.id,
|
|
20378
20603
|
marketplaceId: extension.marketplaceId,
|
|
20379
20604
|
success: !error,
|
|
@@ -20386,11 +20611,11 @@ async function installExtension(ide, extension) {
|
|
|
20386
20611
|
} catch (e) {
|
|
20387
20612
|
}
|
|
20388
20613
|
}
|
|
20389
|
-
return new Promise((
|
|
20614
|
+
return new Promise((resolve12) => {
|
|
20390
20615
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
20391
20616
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
20392
20617
|
if (error) {
|
|
20393
|
-
|
|
20618
|
+
resolve12({
|
|
20394
20619
|
extensionId: extension.id,
|
|
20395
20620
|
marketplaceId: extension.marketplaceId,
|
|
20396
20621
|
success: false,
|
|
@@ -20398,7 +20623,7 @@ async function installExtension(ide, extension) {
|
|
|
20398
20623
|
error: stderr || error.message
|
|
20399
20624
|
});
|
|
20400
20625
|
} else {
|
|
20401
|
-
|
|
20626
|
+
resolve12({
|
|
20402
20627
|
extensionId: extension.id,
|
|
20403
20628
|
marketplaceId: extension.marketplaceId,
|
|
20404
20629
|
success: true,
|
|
@@ -20534,13 +20759,32 @@ async function initDaemonComponents(config) {
|
|
|
20534
20759
|
const detectedIdesRef = { value: [] };
|
|
20535
20760
|
let agentStreamManager = null;
|
|
20536
20761
|
let poller = null;
|
|
20762
|
+
const refreshProviderAvailability = async (providerType) => {
|
|
20763
|
+
const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
|
|
20764
|
+
const targetCategory = targetProvider?.category;
|
|
20765
|
+
if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
|
|
20766
|
+
if (providerType && targetProvider) {
|
|
20767
|
+
const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
|
|
20768
|
+
providerLoader.setProviderAvailability(targetProvider.type, {
|
|
20769
|
+
installed: !!detected,
|
|
20770
|
+
detectedPath: detected?.path || null
|
|
20771
|
+
});
|
|
20772
|
+
} else {
|
|
20773
|
+
providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
|
|
20774
|
+
}
|
|
20775
|
+
}
|
|
20776
|
+
if (!providerType || targetCategory === "ide") {
|
|
20777
|
+
detectedIdesRef.value = await detectIDEs(providerLoader);
|
|
20778
|
+
providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
|
|
20779
|
+
}
|
|
20780
|
+
};
|
|
20537
20781
|
const cliManager = new DaemonCliManager({
|
|
20538
20782
|
...config.cliManagerDeps,
|
|
20539
20783
|
getInstanceManager: () => instanceManager,
|
|
20540
20784
|
getSessionRegistry: () => sessionRegistry
|
|
20541
20785
|
}, providerLoader);
|
|
20542
20786
|
LOG.info("Init", "Detecting IDEs...");
|
|
20543
|
-
|
|
20787
|
+
await refreshProviderAvailability();
|
|
20544
20788
|
const installed = detectedIdesRef.value.filter((i) => i.installed);
|
|
20545
20789
|
LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
|
|
20546
20790
|
const cdpSetupContext = {
|
|
@@ -20580,7 +20824,11 @@ async function initDaemonComponents(config) {
|
|
|
20580
20824
|
adapters: cliManager.adapters,
|
|
20581
20825
|
providerLoader,
|
|
20582
20826
|
instanceManager,
|
|
20583
|
-
sessionRegistry
|
|
20827
|
+
sessionRegistry,
|
|
20828
|
+
onProviderSettingChanged: async (providerType) => {
|
|
20829
|
+
await refreshProviderAvailability(providerType);
|
|
20830
|
+
config.onStatusChange?.();
|
|
20831
|
+
}
|
|
20584
20832
|
});
|
|
20585
20833
|
agentStreamManager = new DaemonAgentStreamManager(
|
|
20586
20834
|
LOG.forComponent("AgentStream").asLogFn(),
|