@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.js
CHANGED
|
@@ -251,13 +251,13 @@ function getDaemonLogDir() {
|
|
|
251
251
|
return LOG_DIR;
|
|
252
252
|
}
|
|
253
253
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
254
|
-
return
|
|
254
|
+
return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
255
255
|
}
|
|
256
256
|
function checkDateRotation() {
|
|
257
257
|
const today = getDateStr();
|
|
258
258
|
if (today !== currentDate) {
|
|
259
259
|
currentDate = today;
|
|
260
|
-
currentLogFile =
|
|
260
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
261
261
|
cleanOldLogs();
|
|
262
262
|
}
|
|
263
263
|
}
|
|
@@ -271,7 +271,7 @@ function cleanOldLogs() {
|
|
|
271
271
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
272
272
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
273
273
|
try {
|
|
274
|
-
fs2.unlinkSync(
|
|
274
|
+
fs2.unlinkSync(path6.join(LOG_DIR, file));
|
|
275
275
|
} catch {
|
|
276
276
|
}
|
|
277
277
|
}
|
|
@@ -388,17 +388,17 @@ function installGlobalInterceptor() {
|
|
|
388
388
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
389
389
|
writeToFile(`Log level: ${currentLevel}`);
|
|
390
390
|
}
|
|
391
|
-
var fs2,
|
|
391
|
+
var fs2, path6, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
|
|
392
392
|
var init_logger = __esm({
|
|
393
393
|
"src/logging/logger.ts"() {
|
|
394
394
|
"use strict";
|
|
395
395
|
fs2 = __toESM(require("fs"));
|
|
396
|
-
|
|
396
|
+
path6 = __toESM(require("path"));
|
|
397
397
|
os4 = __toESM(require("os"));
|
|
398
398
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
399
399
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
400
400
|
currentLevel = "info";
|
|
401
|
-
LOG_DIR = process.platform === "win32" ?
|
|
401
|
+
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");
|
|
402
402
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
403
403
|
MAX_LOG_DAYS = 7;
|
|
404
404
|
try {
|
|
@@ -406,16 +406,16 @@ var init_logger = __esm({
|
|
|
406
406
|
} catch {
|
|
407
407
|
}
|
|
408
408
|
currentDate = getDateStr();
|
|
409
|
-
currentLogFile =
|
|
409
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
410
410
|
cleanOldLogs();
|
|
411
411
|
try {
|
|
412
|
-
const oldLog =
|
|
412
|
+
const oldLog = path6.join(LOG_DIR, "daemon.log");
|
|
413
413
|
if (fs2.existsSync(oldLog)) {
|
|
414
414
|
const stat = fs2.statSync(oldLog);
|
|
415
415
|
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
416
|
-
fs2.renameSync(oldLog,
|
|
416
|
+
fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
417
417
|
}
|
|
418
|
-
const oldLogBackup =
|
|
418
|
+
const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
|
|
419
419
|
if (fs2.existsSync(oldLogBackup)) {
|
|
420
420
|
fs2.unlinkSync(oldLogBackup);
|
|
421
421
|
}
|
|
@@ -447,7 +447,7 @@ var init_logger = __esm({
|
|
|
447
447
|
}
|
|
448
448
|
};
|
|
449
449
|
interceptorInstalled = false;
|
|
450
|
-
LOG_PATH =
|
|
450
|
+
LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
451
451
|
}
|
|
452
452
|
});
|
|
453
453
|
|
|
@@ -872,16 +872,22 @@ function computeTerminalQueryTail(buffer) {
|
|
|
872
872
|
return "";
|
|
873
873
|
}
|
|
874
874
|
function findBinary(name) {
|
|
875
|
+
const trimmed = String(name || "").trim();
|
|
876
|
+
if (!trimmed) return trimmed;
|
|
877
|
+
const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
|
|
878
|
+
if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
879
|
+
return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
880
|
+
}
|
|
875
881
|
const isWin = os8.platform() === "win32";
|
|
876
882
|
try {
|
|
877
|
-
const cmd = isWin ? `where ${
|
|
883
|
+
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
878
884
|
return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
879
885
|
} catch {
|
|
880
|
-
return isWin ? `${
|
|
886
|
+
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
881
887
|
}
|
|
882
888
|
}
|
|
883
889
|
function isScriptBinary(binaryPath) {
|
|
884
|
-
if (!
|
|
890
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
885
891
|
try {
|
|
886
892
|
const fs15 = require("fs");
|
|
887
893
|
const resolved = fs15.realpathSync(binaryPath);
|
|
@@ -897,7 +903,7 @@ function isScriptBinary(binaryPath) {
|
|
|
897
903
|
}
|
|
898
904
|
}
|
|
899
905
|
function looksLikeMachOOrElf(filePath) {
|
|
900
|
-
if (!
|
|
906
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
901
907
|
try {
|
|
902
908
|
const fs15 = require("fs");
|
|
903
909
|
const resolved = fs15.realpathSync(filePath);
|
|
@@ -1021,12 +1027,12 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
1021
1027
|
}
|
|
1022
1028
|
};
|
|
1023
1029
|
}
|
|
1024
|
-
var os8,
|
|
1030
|
+
var os8, path9, import_child_process4, buildCliSpawnEnv, ProviderCliAdapter;
|
|
1025
1031
|
var init_provider_cli_adapter = __esm({
|
|
1026
1032
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
1027
1033
|
"use strict";
|
|
1028
1034
|
os8 = __toESM(require("os"));
|
|
1029
|
-
|
|
1035
|
+
path9 = __toESM(require("path"));
|
|
1030
1036
|
import_child_process4 = require("child_process");
|
|
1031
1037
|
init_logger();
|
|
1032
1038
|
init_terminal_screen();
|
|
@@ -1381,16 +1387,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
1381
1387
|
async spawn() {
|
|
1382
1388
|
if (this.ptyProcess) return;
|
|
1383
1389
|
const { spawn: spawnConfig } = this.provider;
|
|
1384
|
-
const
|
|
1390
|
+
const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1391
|
+
const binaryPath = findBinary(configuredCommand);
|
|
1385
1392
|
const isWin = os8.platform() === "win32";
|
|
1386
1393
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
1387
1394
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1388
1395
|
this.resetTraceSession();
|
|
1389
1396
|
let shellCmd;
|
|
1390
1397
|
let shellArgs;
|
|
1391
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1398
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1392
1399
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1393
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
1400
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1394
1401
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1395
1402
|
if (useShell) {
|
|
1396
1403
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -1764,7 +1771,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1764
1771
|
`[${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)}`
|
|
1765
1772
|
);
|
|
1766
1773
|
}
|
|
1767
|
-
await new Promise((
|
|
1774
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
1768
1775
|
}
|
|
1769
1776
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1770
1777
|
LOG.warn(
|
|
@@ -2275,7 +2282,7 @@ ${data.message || ""}`.trim();
|
|
|
2275
2282
|
const deadline = Date.now() + 1e4;
|
|
2276
2283
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
2277
2284
|
this.resolveStartupState("send_wait");
|
|
2278
|
-
await new Promise((
|
|
2285
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
2279
2286
|
}
|
|
2280
2287
|
}
|
|
2281
2288
|
await this.waitForInteractivePrompt();
|
|
@@ -2500,17 +2507,17 @@ ${data.message || ""}`.trim();
|
|
|
2500
2507
|
}
|
|
2501
2508
|
}
|
|
2502
2509
|
waitForStopped(timeoutMs) {
|
|
2503
|
-
return new Promise((
|
|
2510
|
+
return new Promise((resolve12) => {
|
|
2504
2511
|
const startedAt = Date.now();
|
|
2505
2512
|
const timer = setInterval(() => {
|
|
2506
2513
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
2507
2514
|
clearInterval(timer);
|
|
2508
|
-
|
|
2515
|
+
resolve12(true);
|
|
2509
2516
|
return;
|
|
2510
2517
|
}
|
|
2511
2518
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
2512
2519
|
clearInterval(timer);
|
|
2513
|
-
|
|
2520
|
+
resolve12(false);
|
|
2514
2521
|
}
|
|
2515
2522
|
}, 100);
|
|
2516
2523
|
});
|
|
@@ -3209,6 +3216,7 @@ function resetState() {
|
|
|
3209
3216
|
var import_child_process = require("child_process");
|
|
3210
3217
|
var import_fs3 = require("fs");
|
|
3211
3218
|
var import_os2 = require("os");
|
|
3219
|
+
var path4 = __toESM(require("path"));
|
|
3212
3220
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
3213
3221
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
3214
3222
|
function registerIDEDefinition(def) {
|
|
@@ -3225,9 +3233,16 @@ function getMergedDefinitions() {
|
|
|
3225
3233
|
return [...merged.values()];
|
|
3226
3234
|
}
|
|
3227
3235
|
function findCliCommand(command) {
|
|
3236
|
+
const trimmed = String(command || "").trim();
|
|
3237
|
+
if (!trimmed) return null;
|
|
3238
|
+
if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
3239
|
+
const candidate = trimmed.startsWith("~") ? path4.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
3240
|
+
const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
|
|
3241
|
+
return (0, import_fs3.existsSync)(resolved) ? resolved : null;
|
|
3242
|
+
}
|
|
3228
3243
|
try {
|
|
3229
3244
|
const result = (0, import_child_process.execSync)(
|
|
3230
|
-
(0, import_os2.platform)() === "win32" ? `where ${
|
|
3245
|
+
(0, import_os2.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
3231
3246
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
3232
3247
|
).trim();
|
|
3233
3248
|
return result.split("\n")[0] || null;
|
|
@@ -3250,23 +3265,23 @@ function getIdeVersion(cliCommand) {
|
|
|
3250
3265
|
function checkPathExists(paths) {
|
|
3251
3266
|
const home = (0, import_os2.homedir)();
|
|
3252
3267
|
for (const p of paths) {
|
|
3253
|
-
|
|
3268
|
+
const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
|
|
3269
|
+
if (normalized.includes("*")) {
|
|
3254
3270
|
const username = home.split(/[\\/]/).pop() || "";
|
|
3255
|
-
const resolved =
|
|
3271
|
+
const resolved = normalized.replace("*", username);
|
|
3256
3272
|
if ((0, import_fs3.existsSync)(resolved)) return resolved;
|
|
3257
3273
|
} else {
|
|
3258
|
-
if ((0, import_fs3.existsSync)(
|
|
3274
|
+
if ((0, import_fs3.existsSync)(normalized)) return normalized;
|
|
3259
3275
|
}
|
|
3260
3276
|
}
|
|
3261
3277
|
return null;
|
|
3262
3278
|
}
|
|
3263
|
-
async function detectIDEs() {
|
|
3279
|
+
async function detectIDEs(providerLoader) {
|
|
3264
3280
|
const os18 = (0, import_os2.platform)();
|
|
3265
3281
|
const results = [];
|
|
3266
3282
|
for (const def of getMergedDefinitions()) {
|
|
3267
|
-
const cliPath = findCliCommand(def.cli);
|
|
3268
|
-
const appPath = checkPathExists(def.paths[os18] || []);
|
|
3269
|
-
const installed = !!(cliPath || appPath);
|
|
3283
|
+
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
3284
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
|
|
3270
3285
|
let resolvedCli = cliPath;
|
|
3271
3286
|
if (!resolvedCli && appPath && os18 === "darwin") {
|
|
3272
3287
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
@@ -3289,6 +3304,7 @@ async function detectIDEs() {
|
|
|
3289
3304
|
}
|
|
3290
3305
|
}
|
|
3291
3306
|
}
|
|
3307
|
+
const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
3292
3308
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
3293
3309
|
results.push({
|
|
3294
3310
|
id: def.id,
|
|
@@ -3307,48 +3323,77 @@ async function detectIDEs() {
|
|
|
3307
3323
|
// src/detection/cli-detector.ts
|
|
3308
3324
|
var import_child_process2 = require("child_process");
|
|
3309
3325
|
var os2 = __toESM(require("os"));
|
|
3326
|
+
var path5 = __toESM(require("path"));
|
|
3327
|
+
var import_fs4 = require("fs");
|
|
3310
3328
|
function parseVersion(raw) {
|
|
3311
3329
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
3312
3330
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
3313
3331
|
}
|
|
3332
|
+
function shellQuote(value) {
|
|
3333
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
3334
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
3335
|
+
}
|
|
3336
|
+
function expandHome(value) {
|
|
3337
|
+
const trimmed = value.trim();
|
|
3338
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
3339
|
+
return path5.join(os2.homedir(), trimmed.slice(1));
|
|
3340
|
+
}
|
|
3341
|
+
function isExplicitCommandPath(command) {
|
|
3342
|
+
const trimmed = command.trim();
|
|
3343
|
+
return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
3344
|
+
}
|
|
3345
|
+
function resolveCommandPath(command) {
|
|
3346
|
+
const trimmed = command.trim();
|
|
3347
|
+
if (!trimmed) return null;
|
|
3348
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
3349
|
+
const expanded = expandHome(trimmed);
|
|
3350
|
+
const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
|
|
3351
|
+
return (0, import_fs4.existsSync)(candidate) ? candidate : null;
|
|
3352
|
+
}
|
|
3353
|
+
return null;
|
|
3354
|
+
}
|
|
3314
3355
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
3315
|
-
return new Promise((
|
|
3356
|
+
return new Promise((resolve12) => {
|
|
3316
3357
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
3317
3358
|
if (err || !stdout?.trim()) {
|
|
3318
|
-
|
|
3359
|
+
resolve12(null);
|
|
3319
3360
|
} else {
|
|
3320
|
-
|
|
3361
|
+
resolve12(stdout.trim());
|
|
3321
3362
|
}
|
|
3322
3363
|
});
|
|
3323
|
-
child.on("error", () =>
|
|
3364
|
+
child.on("error", () => resolve12(null));
|
|
3324
3365
|
});
|
|
3325
3366
|
}
|
|
3326
|
-
async function detectCLIs(providerLoader) {
|
|
3367
|
+
async function detectCLIs(providerLoader, options) {
|
|
3327
3368
|
const platform9 = os2.platform();
|
|
3328
3369
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
3370
|
+
const includeVersion = options?.includeVersion !== false;
|
|
3329
3371
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
3330
3372
|
const results = await Promise.all(
|
|
3331
3373
|
cliList.map(async (cli) => {
|
|
3332
3374
|
try {
|
|
3333
|
-
const
|
|
3375
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
3376
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
3334
3377
|
if (!pathResult) return { ...cli, installed: false };
|
|
3335
|
-
const firstPath = pathResult.split("\n")[0];
|
|
3378
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
3336
3379
|
let version;
|
|
3337
|
-
|
|
3380
|
+
if (includeVersion) {
|
|
3338
3381
|
const versionCommands = [
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3382
|
+
`"${firstPath}" --version`,
|
|
3383
|
+
`"${firstPath}" -V`,
|
|
3384
|
+
`"${firstPath}" -v`,
|
|
3385
|
+
cli.versionCommand
|
|
3343
3386
|
].filter((v) => !!v);
|
|
3344
|
-
|
|
3345
|
-
const
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3387
|
+
try {
|
|
3388
|
+
for (const versionCommand of versionCommands) {
|
|
3389
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
3390
|
+
if (versionResult) {
|
|
3391
|
+
version = parseVersion(versionResult);
|
|
3392
|
+
break;
|
|
3393
|
+
}
|
|
3349
3394
|
}
|
|
3395
|
+
} catch {
|
|
3350
3396
|
}
|
|
3351
|
-
} catch {
|
|
3352
3397
|
}
|
|
3353
3398
|
return { ...cli, installed: true, version, path: firstPath };
|
|
3354
3399
|
} catch {
|
|
@@ -3358,7 +3403,7 @@ async function detectCLIs(providerLoader) {
|
|
|
3358
3403
|
);
|
|
3359
3404
|
return results;
|
|
3360
3405
|
}
|
|
3361
|
-
async function detectCLI(cliId, providerLoader) {
|
|
3406
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
3362
3407
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
3363
3408
|
if (providerLoader) {
|
|
3364
3409
|
const cliList = providerLoader.getCliDetectionList();
|
|
@@ -3367,25 +3412,28 @@ async function detectCLI(cliId, providerLoader) {
|
|
|
3367
3412
|
const platform9 = os2.platform();
|
|
3368
3413
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
3369
3414
|
try {
|
|
3370
|
-
const
|
|
3415
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
3416
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
3371
3417
|
if (!pathResult) return null;
|
|
3372
|
-
const firstPath = pathResult.split("\n")[0];
|
|
3418
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
3373
3419
|
let version;
|
|
3374
|
-
|
|
3420
|
+
if (options?.includeVersion !== false) {
|
|
3375
3421
|
const versionCommands = [
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3422
|
+
`"${firstPath}" --version`,
|
|
3423
|
+
`"${firstPath}" -V`,
|
|
3424
|
+
`"${firstPath}" -v`,
|
|
3425
|
+
target.versionCommand
|
|
3380
3426
|
].filter((v) => !!v);
|
|
3381
|
-
|
|
3382
|
-
const
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3427
|
+
try {
|
|
3428
|
+
for (const versionCommand of versionCommands) {
|
|
3429
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
3430
|
+
if (versionResult) {
|
|
3431
|
+
version = parseVersion(versionResult);
|
|
3432
|
+
break;
|
|
3433
|
+
}
|
|
3386
3434
|
}
|
|
3435
|
+
} catch {
|
|
3387
3436
|
}
|
|
3388
|
-
} catch {
|
|
3389
3437
|
}
|
|
3390
3438
|
return { ...target, installed: true, version, path: firstPath };
|
|
3391
3439
|
} catch {
|
|
@@ -3393,7 +3441,7 @@ async function detectCLI(cliId, providerLoader) {
|
|
|
3393
3441
|
}
|
|
3394
3442
|
}
|
|
3395
3443
|
}
|
|
3396
|
-
const all = await detectCLIs(providerLoader);
|
|
3444
|
+
const all = await detectCLIs(providerLoader, options);
|
|
3397
3445
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
3398
3446
|
}
|
|
3399
3447
|
|
|
@@ -3520,7 +3568,7 @@ var DaemonCdpManager = class {
|
|
|
3520
3568
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
3521
3569
|
*/
|
|
3522
3570
|
static listAllTargets(port) {
|
|
3523
|
-
return new Promise((
|
|
3571
|
+
return new Promise((resolve12) => {
|
|
3524
3572
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
3525
3573
|
let data = "";
|
|
3526
3574
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -3536,16 +3584,16 @@ var DaemonCdpManager = class {
|
|
|
3536
3584
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
3537
3585
|
);
|
|
3538
3586
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
3539
|
-
|
|
3587
|
+
resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
3540
3588
|
} catch {
|
|
3541
|
-
|
|
3589
|
+
resolve12([]);
|
|
3542
3590
|
}
|
|
3543
3591
|
});
|
|
3544
3592
|
});
|
|
3545
|
-
req.on("error", () =>
|
|
3593
|
+
req.on("error", () => resolve12([]));
|
|
3546
3594
|
req.setTimeout(2e3, () => {
|
|
3547
3595
|
req.destroy();
|
|
3548
|
-
|
|
3596
|
+
resolve12([]);
|
|
3549
3597
|
});
|
|
3550
3598
|
});
|
|
3551
3599
|
}
|
|
@@ -3585,7 +3633,7 @@ var DaemonCdpManager = class {
|
|
|
3585
3633
|
}
|
|
3586
3634
|
}
|
|
3587
3635
|
findTargetOnPort(port) {
|
|
3588
|
-
return new Promise((
|
|
3636
|
+
return new Promise((resolve12) => {
|
|
3589
3637
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
3590
3638
|
let data = "";
|
|
3591
3639
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -3596,7 +3644,7 @@ var DaemonCdpManager = class {
|
|
|
3596
3644
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
3597
3645
|
);
|
|
3598
3646
|
if (pages.length === 0) {
|
|
3599
|
-
|
|
3647
|
+
resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
3600
3648
|
return;
|
|
3601
3649
|
}
|
|
3602
3650
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -3606,24 +3654,24 @@ var DaemonCdpManager = class {
|
|
|
3606
3654
|
const specific = list.find((t) => t.id === this._targetId);
|
|
3607
3655
|
if (specific) {
|
|
3608
3656
|
this._pageTitle = specific.title || "";
|
|
3609
|
-
|
|
3657
|
+
resolve12(specific);
|
|
3610
3658
|
} else {
|
|
3611
3659
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
3612
|
-
|
|
3660
|
+
resolve12(null);
|
|
3613
3661
|
}
|
|
3614
3662
|
return;
|
|
3615
3663
|
}
|
|
3616
3664
|
this._pageTitle = list[0]?.title || "";
|
|
3617
|
-
|
|
3665
|
+
resolve12(list[0]);
|
|
3618
3666
|
} catch {
|
|
3619
|
-
|
|
3667
|
+
resolve12(null);
|
|
3620
3668
|
}
|
|
3621
3669
|
});
|
|
3622
3670
|
});
|
|
3623
|
-
req.on("error", () =>
|
|
3671
|
+
req.on("error", () => resolve12(null));
|
|
3624
3672
|
req.setTimeout(2e3, () => {
|
|
3625
3673
|
req.destroy();
|
|
3626
|
-
|
|
3674
|
+
resolve12(null);
|
|
3627
3675
|
});
|
|
3628
3676
|
});
|
|
3629
3677
|
}
|
|
@@ -3634,7 +3682,7 @@ var DaemonCdpManager = class {
|
|
|
3634
3682
|
this.extensionProviders = providers;
|
|
3635
3683
|
}
|
|
3636
3684
|
connectToTarget(wsUrl) {
|
|
3637
|
-
return new Promise((
|
|
3685
|
+
return new Promise((resolve12) => {
|
|
3638
3686
|
this.ws = new import_ws.default(wsUrl);
|
|
3639
3687
|
this.ws.on("open", async () => {
|
|
3640
3688
|
this._connected = true;
|
|
@@ -3644,17 +3692,17 @@ var DaemonCdpManager = class {
|
|
|
3644
3692
|
}
|
|
3645
3693
|
this.connectBrowserWs().catch(() => {
|
|
3646
3694
|
});
|
|
3647
|
-
|
|
3695
|
+
resolve12(true);
|
|
3648
3696
|
});
|
|
3649
3697
|
this.ws.on("message", (data) => {
|
|
3650
3698
|
try {
|
|
3651
3699
|
const msg = JSON.parse(data.toString());
|
|
3652
3700
|
if (msg.id && this.pending.has(msg.id)) {
|
|
3653
|
-
const { resolve:
|
|
3701
|
+
const { resolve: resolve13, reject } = this.pending.get(msg.id);
|
|
3654
3702
|
this.pending.delete(msg.id);
|
|
3655
3703
|
this.failureCount = 0;
|
|
3656
3704
|
if (msg.error) reject(new Error(msg.error.message));
|
|
3657
|
-
else
|
|
3705
|
+
else resolve13(msg.result);
|
|
3658
3706
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
3659
3707
|
this.contexts.add(msg.params.context.id);
|
|
3660
3708
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -3677,7 +3725,7 @@ var DaemonCdpManager = class {
|
|
|
3677
3725
|
this.ws.on("error", (err) => {
|
|
3678
3726
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
3679
3727
|
this._connected = false;
|
|
3680
|
-
|
|
3728
|
+
resolve12(false);
|
|
3681
3729
|
});
|
|
3682
3730
|
});
|
|
3683
3731
|
}
|
|
@@ -3691,7 +3739,7 @@ var DaemonCdpManager = class {
|
|
|
3691
3739
|
return;
|
|
3692
3740
|
}
|
|
3693
3741
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
3694
|
-
await new Promise((
|
|
3742
|
+
await new Promise((resolve12, reject) => {
|
|
3695
3743
|
this.browserWs = new import_ws.default(browserWsUrl);
|
|
3696
3744
|
this.browserWs.on("open", async () => {
|
|
3697
3745
|
this._browserConnected = true;
|
|
@@ -3701,16 +3749,16 @@ var DaemonCdpManager = class {
|
|
|
3701
3749
|
} catch (e) {
|
|
3702
3750
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
3703
3751
|
}
|
|
3704
|
-
|
|
3752
|
+
resolve12();
|
|
3705
3753
|
});
|
|
3706
3754
|
this.browserWs.on("message", (data) => {
|
|
3707
3755
|
try {
|
|
3708
3756
|
const msg = JSON.parse(data.toString());
|
|
3709
3757
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
3710
|
-
const { resolve:
|
|
3758
|
+
const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
|
|
3711
3759
|
this.browserPending.delete(msg.id);
|
|
3712
3760
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
3713
|
-
else
|
|
3761
|
+
else resolve13(msg.result);
|
|
3714
3762
|
}
|
|
3715
3763
|
} catch {
|
|
3716
3764
|
}
|
|
@@ -3730,31 +3778,31 @@ var DaemonCdpManager = class {
|
|
|
3730
3778
|
}
|
|
3731
3779
|
}
|
|
3732
3780
|
getBrowserWsUrl() {
|
|
3733
|
-
return new Promise((
|
|
3781
|
+
return new Promise((resolve12) => {
|
|
3734
3782
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
3735
3783
|
let data = "";
|
|
3736
3784
|
res.on("data", (chunk) => data += chunk.toString());
|
|
3737
3785
|
res.on("end", () => {
|
|
3738
3786
|
try {
|
|
3739
3787
|
const info = JSON.parse(data);
|
|
3740
|
-
|
|
3788
|
+
resolve12(info.webSocketDebuggerUrl || null);
|
|
3741
3789
|
} catch {
|
|
3742
|
-
|
|
3790
|
+
resolve12(null);
|
|
3743
3791
|
}
|
|
3744
3792
|
});
|
|
3745
3793
|
});
|
|
3746
|
-
req.on("error", () =>
|
|
3794
|
+
req.on("error", () => resolve12(null));
|
|
3747
3795
|
req.setTimeout(3e3, () => {
|
|
3748
3796
|
req.destroy();
|
|
3749
|
-
|
|
3797
|
+
resolve12(null);
|
|
3750
3798
|
});
|
|
3751
3799
|
});
|
|
3752
3800
|
}
|
|
3753
3801
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
3754
|
-
return new Promise((
|
|
3802
|
+
return new Promise((resolve12, reject) => {
|
|
3755
3803
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
3756
3804
|
const id = this.browserMsgId++;
|
|
3757
|
-
this.browserPending.set(id, { resolve:
|
|
3805
|
+
this.browserPending.set(id, { resolve: resolve12, reject });
|
|
3758
3806
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
3759
3807
|
setTimeout(() => {
|
|
3760
3808
|
if (this.browserPending.has(id)) {
|
|
@@ -3794,11 +3842,11 @@ var DaemonCdpManager = class {
|
|
|
3794
3842
|
}
|
|
3795
3843
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
3796
3844
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
3797
|
-
return new Promise((
|
|
3845
|
+
return new Promise((resolve12, reject) => {
|
|
3798
3846
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
3799
3847
|
if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
3800
3848
|
const id = this.msgId++;
|
|
3801
|
-
this.pending.set(id, { resolve:
|
|
3849
|
+
this.pending.set(id, { resolve: resolve12, reject });
|
|
3802
3850
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
3803
3851
|
setTimeout(() => {
|
|
3804
3852
|
if (this.pending.has(id)) {
|
|
@@ -4047,7 +4095,7 @@ var DaemonCdpManager = class {
|
|
|
4047
4095
|
const browserWs = this.browserWs;
|
|
4048
4096
|
let msgId = this.browserMsgId;
|
|
4049
4097
|
const sendWs = (method, params = {}, sessionId) => {
|
|
4050
|
-
return new Promise((
|
|
4098
|
+
return new Promise((resolve12, reject) => {
|
|
4051
4099
|
const mid = msgId++;
|
|
4052
4100
|
this.browserMsgId = msgId;
|
|
4053
4101
|
const handler = (raw) => {
|
|
@@ -4056,7 +4104,7 @@ var DaemonCdpManager = class {
|
|
|
4056
4104
|
if (msg.id === mid) {
|
|
4057
4105
|
browserWs.removeListener("message", handler);
|
|
4058
4106
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
4059
|
-
else
|
|
4107
|
+
else resolve12(msg.result);
|
|
4060
4108
|
}
|
|
4061
4109
|
} catch {
|
|
4062
4110
|
}
|
|
@@ -4247,14 +4295,14 @@ var DaemonCdpManager = class {
|
|
|
4247
4295
|
if (!ws || ws.readyState !== import_ws.default.OPEN) {
|
|
4248
4296
|
throw new Error("CDP not connected");
|
|
4249
4297
|
}
|
|
4250
|
-
return new Promise((
|
|
4298
|
+
return new Promise((resolve12, reject) => {
|
|
4251
4299
|
const id = getNextId();
|
|
4252
4300
|
pendingMap.set(id, {
|
|
4253
4301
|
resolve: (result) => {
|
|
4254
4302
|
if (result?.result?.subtype === "error") {
|
|
4255
4303
|
reject(new Error(result.result.description));
|
|
4256
4304
|
} else {
|
|
4257
|
-
|
|
4305
|
+
resolve12(result?.result?.value);
|
|
4258
4306
|
}
|
|
4259
4307
|
},
|
|
4260
4308
|
reject
|
|
@@ -4286,10 +4334,10 @@ var DaemonCdpManager = class {
|
|
|
4286
4334
|
throw new Error("CDP not connected");
|
|
4287
4335
|
}
|
|
4288
4336
|
const sendViaSession = (method, params = {}) => {
|
|
4289
|
-
return new Promise((
|
|
4337
|
+
return new Promise((resolve12, reject) => {
|
|
4290
4338
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
4291
4339
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
4292
|
-
pendingMap.set(id, { resolve:
|
|
4340
|
+
pendingMap.set(id, { resolve: resolve12, reject });
|
|
4293
4341
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
4294
4342
|
setTimeout(() => {
|
|
4295
4343
|
if (pendingMap.has(id)) {
|
|
@@ -4917,9 +4965,9 @@ function normalizeControlValue(value) {
|
|
|
4917
4965
|
|
|
4918
4966
|
// src/config/chat-history.ts
|
|
4919
4967
|
var fs3 = __toESM(require("fs"));
|
|
4920
|
-
var
|
|
4968
|
+
var path7 = __toESM(require("path"));
|
|
4921
4969
|
var os5 = __toESM(require("os"));
|
|
4922
|
-
var HISTORY_DIR =
|
|
4970
|
+
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
4923
4971
|
var RETAIN_DAYS = 30;
|
|
4924
4972
|
var ChatHistoryWriter = class {
|
|
4925
4973
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -4964,11 +5012,11 @@ var ChatHistoryWriter = class {
|
|
|
4964
5012
|
});
|
|
4965
5013
|
}
|
|
4966
5014
|
if (newMessages.length === 0) return;
|
|
4967
|
-
const dir =
|
|
5015
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4968
5016
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4969
5017
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4970
5018
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
4971
|
-
const filePath =
|
|
5019
|
+
const filePath = path7.join(dir, `${filePrefix}${date}.jsonl`);
|
|
4972
5020
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
4973
5021
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
4974
5022
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
@@ -5022,14 +5070,14 @@ var ChatHistoryWriter = class {
|
|
|
5022
5070
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
5023
5071
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
5024
5072
|
}
|
|
5025
|
-
const dir =
|
|
5073
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
5026
5074
|
if (!fs3.existsSync(dir)) return;
|
|
5027
5075
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
5028
5076
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
5029
5077
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
5030
5078
|
for (const file of files) {
|
|
5031
|
-
const sourcePath =
|
|
5032
|
-
const targetPath =
|
|
5079
|
+
const sourcePath = path7.join(dir, file);
|
|
5080
|
+
const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
5033
5081
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
5034
5082
|
const rewritten = sourceLines.map((line) => {
|
|
5035
5083
|
try {
|
|
@@ -5070,10 +5118,10 @@ var ChatHistoryWriter = class {
|
|
|
5070
5118
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
5071
5119
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
5072
5120
|
for (const dir of agentDirs) {
|
|
5073
|
-
const dirPath =
|
|
5121
|
+
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
5074
5122
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
5075
5123
|
for (const file of files) {
|
|
5076
|
-
const filePath =
|
|
5124
|
+
const filePath = path7.join(dirPath, file);
|
|
5077
5125
|
const stat = fs3.statSync(filePath);
|
|
5078
5126
|
if (stat.mtimeMs < cutoff) {
|
|
5079
5127
|
fs3.unlinkSync(filePath);
|
|
@@ -5091,7 +5139,7 @@ var ChatHistoryWriter = class {
|
|
|
5091
5139
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
5092
5140
|
try {
|
|
5093
5141
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5094
|
-
const dir =
|
|
5142
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
5095
5143
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
5096
5144
|
const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5097
5145
|
const files = fs3.readdirSync(dir).filter((f) => {
|
|
@@ -5105,7 +5153,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
|
5105
5153
|
const needed = offset + limit + 1;
|
|
5106
5154
|
for (const file of files) {
|
|
5107
5155
|
if (allMessages.length >= needed) break;
|
|
5108
|
-
const filePath =
|
|
5156
|
+
const filePath = path7.join(dir, file);
|
|
5109
5157
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
5110
5158
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
5111
5159
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -5127,7 +5175,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
|
5127
5175
|
function listSavedHistorySessions(agentType, options = {}) {
|
|
5128
5176
|
try {
|
|
5129
5177
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5130
|
-
const dir =
|
|
5178
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
5131
5179
|
if (!fs3.existsSync(dir)) return { sessions: [], hasMore: false };
|
|
5132
5180
|
const groupedFiles = /* @__PURE__ */ new Map();
|
|
5133
5181
|
const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
@@ -5148,7 +5196,7 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
5148
5196
|
let sessionTitle = "";
|
|
5149
5197
|
let preview = "";
|
|
5150
5198
|
for (const file of files.sort()) {
|
|
5151
|
-
const filePath =
|
|
5199
|
+
const filePath = path7.join(dir, file);
|
|
5152
5200
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
5153
5201
|
const lines = content.split("\n").filter(Boolean);
|
|
5154
5202
|
for (const line of lines) {
|
|
@@ -7323,6 +7371,14 @@ async function handleListChats(h, args) {
|
|
|
7323
7371
|
} catch {
|
|
7324
7372
|
}
|
|
7325
7373
|
}
|
|
7374
|
+
if (parsed?.sessions && Array.isArray(parsed.sessions)) {
|
|
7375
|
+
LOG.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
|
|
7376
|
+
return { success: true, chats: parsed.sessions };
|
|
7377
|
+
}
|
|
7378
|
+
if (parsed?.chats && Array.isArray(parsed.chats)) {
|
|
7379
|
+
LOG.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
|
|
7380
|
+
return { success: true, chats: parsed.chats };
|
|
7381
|
+
}
|
|
7326
7382
|
if (Array.isArray(parsed)) {
|
|
7327
7383
|
LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
|
|
7328
7384
|
return { success: true, chats: parsed };
|
|
@@ -7392,7 +7448,13 @@ async function handleSwitchChat(h, args) {
|
|
|
7392
7448
|
} catch (e) {
|
|
7393
7449
|
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
7394
7450
|
}
|
|
7395
|
-
const
|
|
7451
|
+
const switchParams = {
|
|
7452
|
+
sessionId,
|
|
7453
|
+
title: sessionId,
|
|
7454
|
+
id: sessionId,
|
|
7455
|
+
SESSION_ID: JSON.stringify(sessionId)
|
|
7456
|
+
};
|
|
7457
|
+
const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
|
|
7396
7458
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
7397
7459
|
try {
|
|
7398
7460
|
const raw = await cdp.evaluate(script, 15e3);
|
|
@@ -7471,8 +7533,8 @@ async function handleSetMode(h, args) {
|
|
|
7471
7533
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7472
7534
|
if (adapter) {
|
|
7473
7535
|
const acpInstance = adapter._acpInstance;
|
|
7474
|
-
if (acpInstance && typeof acpInstance.
|
|
7475
|
-
acpInstance.
|
|
7536
|
+
if (acpInstance && typeof acpInstance.setMode === "function") {
|
|
7537
|
+
await acpInstance.setMode(mode);
|
|
7476
7538
|
return { success: true, mode };
|
|
7477
7539
|
}
|
|
7478
7540
|
}
|
|
@@ -7529,9 +7591,9 @@ async function handleChangeModel(h, args) {
|
|
|
7529
7591
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
7530
7592
|
if (adapter) {
|
|
7531
7593
|
const acpInstance = adapter._acpInstance;
|
|
7532
|
-
if (acpInstance && typeof acpInstance.
|
|
7533
|
-
acpInstance.
|
|
7534
|
-
LOG.info("Command", `[change_model]
|
|
7594
|
+
if (acpInstance && typeof acpInstance.setConfigOption === "function") {
|
|
7595
|
+
await acpInstance.setConfigOption("model", model);
|
|
7596
|
+
LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
|
|
7535
7597
|
return { success: true, model };
|
|
7536
7598
|
}
|
|
7537
7599
|
}
|
|
@@ -7651,6 +7713,18 @@ async function handleResolveAction(h, args) {
|
|
|
7651
7713
|
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
7652
7714
|
return { success: ok };
|
|
7653
7715
|
}
|
|
7716
|
+
if (transport === "acp") {
|
|
7717
|
+
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7718
|
+
const acpInstance = adapter?._acpInstance;
|
|
7719
|
+
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
7720
|
+
try {
|
|
7721
|
+
await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
|
|
7722
|
+
LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
|
|
7723
|
+
return { success: true, action };
|
|
7724
|
+
} catch (e) {
|
|
7725
|
+
return { success: false, error: e?.message || "ACP resolve action failed" };
|
|
7726
|
+
}
|
|
7727
|
+
}
|
|
7654
7728
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
7655
7729
|
const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
7656
7730
|
if (script) {
|
|
@@ -7729,7 +7803,7 @@ async function handleResolveAction(h, args) {
|
|
|
7729
7803
|
|
|
7730
7804
|
// src/commands/cdp-commands.ts
|
|
7731
7805
|
var fs4 = __toESM(require("fs"));
|
|
7732
|
-
var
|
|
7806
|
+
var path8 = __toESM(require("path"));
|
|
7733
7807
|
var os6 = __toESM(require("os"));
|
|
7734
7808
|
var KEY_TO_VK = {
|
|
7735
7809
|
Backspace: 8,
|
|
@@ -7981,25 +8055,25 @@ function resolveSafePath(requestedPath) {
|
|
|
7981
8055
|
const inputPath = rawPath || ".";
|
|
7982
8056
|
const home = os6.homedir();
|
|
7983
8057
|
if (inputPath.startsWith("~")) {
|
|
7984
|
-
return
|
|
8058
|
+
return path8.resolve(path8.join(home, inputPath.slice(1)));
|
|
7985
8059
|
}
|
|
7986
8060
|
if (process.platform === "win32") {
|
|
7987
8061
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
7988
|
-
if (
|
|
7989
|
-
return
|
|
8062
|
+
if (path8.win32.isAbsolute(normalized)) {
|
|
8063
|
+
return path8.win32.normalize(normalized);
|
|
7990
8064
|
}
|
|
7991
|
-
return
|
|
8065
|
+
return path8.win32.resolve(normalized);
|
|
7992
8066
|
}
|
|
7993
|
-
if (
|
|
7994
|
-
return
|
|
8067
|
+
if (path8.isAbsolute(inputPath)) {
|
|
8068
|
+
return path8.normalize(inputPath);
|
|
7995
8069
|
}
|
|
7996
|
-
return
|
|
8070
|
+
return path8.resolve(inputPath);
|
|
7997
8071
|
}
|
|
7998
8072
|
function listDirectoryEntriesSafe(dirPath) {
|
|
7999
8073
|
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
8000
8074
|
const files = [];
|
|
8001
8075
|
for (const entry of entries) {
|
|
8002
|
-
const entryPath =
|
|
8076
|
+
const entryPath = path8.join(dirPath, entry.name);
|
|
8003
8077
|
try {
|
|
8004
8078
|
if (entry.isDirectory()) {
|
|
8005
8079
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -8038,7 +8112,7 @@ async function handleFileRead(h, args) {
|
|
|
8038
8112
|
async function handleFileWrite(h, args) {
|
|
8039
8113
|
try {
|
|
8040
8114
|
const filePath = resolveSafePath(args?.path);
|
|
8041
|
-
fs4.mkdirSync(
|
|
8115
|
+
fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
|
|
8042
8116
|
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
8043
8117
|
return { success: true, path: filePath };
|
|
8044
8118
|
} catch (e) {
|
|
@@ -8126,7 +8200,7 @@ function handleGetProviderSettings(h, args) {
|
|
|
8126
8200
|
}
|
|
8127
8201
|
return { success: true, settings: allSettings, values: allValues };
|
|
8128
8202
|
}
|
|
8129
|
-
function handleSetProviderSetting(h, args) {
|
|
8203
|
+
async function handleSetProviderSetting(h, args) {
|
|
8130
8204
|
const loader = h.ctx.providerLoader;
|
|
8131
8205
|
const { providerType, key, value } = args || {};
|
|
8132
8206
|
if (!providerType || !key || value === void 0) {
|
|
@@ -8139,6 +8213,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
8139
8213
|
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
8140
8214
|
LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
|
|
8141
8215
|
}
|
|
8216
|
+
await h.ctx.onProviderSettingChanged?.(providerType, key, value);
|
|
8142
8217
|
return { success: true, providerType, key, value };
|
|
8143
8218
|
}
|
|
8144
8219
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
@@ -8176,10 +8251,10 @@ function getCliScriptCommand(payload) {
|
|
|
8176
8251
|
}
|
|
8177
8252
|
const command = payload.command;
|
|
8178
8253
|
if (!command || typeof command !== "object") return null;
|
|
8179
|
-
if (command.type !== "send_message") return null;
|
|
8254
|
+
if (command.type !== "send_message" && command.type !== "pty_write") return null;
|
|
8180
8255
|
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
8181
8256
|
if (!text) return null;
|
|
8182
|
-
return { type:
|
|
8257
|
+
return { type: command.type, text };
|
|
8183
8258
|
}
|
|
8184
8259
|
function applyProviderPatch(h, args, payload) {
|
|
8185
8260
|
if (!payload || typeof payload !== "object") return;
|
|
@@ -8220,6 +8295,8 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8220
8295
|
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
8221
8296
|
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
8222
8297
|
await adapter.sendMessage(cliCommand.text);
|
|
8298
|
+
} else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
|
|
8299
|
+
adapter.writeRaw(cliCommand.text + "\r");
|
|
8223
8300
|
}
|
|
8224
8301
|
applyProviderPatch(h, args, parsed.payload);
|
|
8225
8302
|
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
@@ -8898,7 +8975,7 @@ var DaemonCommandHandler = class {
|
|
|
8898
8975
|
try {
|
|
8899
8976
|
const http3 = await import("http");
|
|
8900
8977
|
const postData = JSON.stringify(body);
|
|
8901
|
-
const result = await new Promise((
|
|
8978
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8902
8979
|
const req = http3.request({
|
|
8903
8980
|
hostname: "127.0.0.1",
|
|
8904
8981
|
port: 19280,
|
|
@@ -8910,9 +8987,9 @@ var DaemonCommandHandler = class {
|
|
|
8910
8987
|
res.on("data", (chunk) => data += chunk);
|
|
8911
8988
|
res.on("end", () => {
|
|
8912
8989
|
try {
|
|
8913
|
-
|
|
8990
|
+
resolve12(JSON.parse(data));
|
|
8914
8991
|
} catch {
|
|
8915
|
-
|
|
8992
|
+
resolve12({ raw: data });
|
|
8916
8993
|
}
|
|
8917
8994
|
});
|
|
8918
8995
|
});
|
|
@@ -8930,15 +9007,15 @@ var DaemonCommandHandler = class {
|
|
|
8930
9007
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
8931
9008
|
try {
|
|
8932
9009
|
const http3 = await import("http");
|
|
8933
|
-
const result = await new Promise((
|
|
9010
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8934
9011
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
8935
9012
|
let data = "";
|
|
8936
9013
|
res.on("data", (chunk) => data += chunk);
|
|
8937
9014
|
res.on("end", () => {
|
|
8938
9015
|
try {
|
|
8939
|
-
|
|
9016
|
+
resolve12(JSON.parse(data));
|
|
8940
9017
|
} catch {
|
|
8941
|
-
|
|
9018
|
+
resolve12({ raw: data });
|
|
8942
9019
|
}
|
|
8943
9020
|
});
|
|
8944
9021
|
}).on("error", reject);
|
|
@@ -8952,7 +9029,7 @@ var DaemonCommandHandler = class {
|
|
|
8952
9029
|
try {
|
|
8953
9030
|
const http3 = await import("http");
|
|
8954
9031
|
const postData = JSON.stringify(args || {});
|
|
8955
|
-
const result = await new Promise((
|
|
9032
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8956
9033
|
const req = http3.request({
|
|
8957
9034
|
hostname: "127.0.0.1",
|
|
8958
9035
|
port: 19280,
|
|
@@ -8964,9 +9041,9 @@ var DaemonCommandHandler = class {
|
|
|
8964
9041
|
res.on("data", (chunk) => data += chunk);
|
|
8965
9042
|
res.on("end", () => {
|
|
8966
9043
|
try {
|
|
8967
|
-
|
|
9044
|
+
resolve12(JSON.parse(data));
|
|
8968
9045
|
} catch {
|
|
8969
|
-
|
|
9046
|
+
resolve12({ raw: data });
|
|
8970
9047
|
}
|
|
8971
9048
|
});
|
|
8972
9049
|
});
|
|
@@ -8983,7 +9060,7 @@ var DaemonCommandHandler = class {
|
|
|
8983
9060
|
|
|
8984
9061
|
// src/commands/cli-manager.ts
|
|
8985
9062
|
var os10 = __toESM(require("os"));
|
|
8986
|
-
var
|
|
9063
|
+
var path11 = __toESM(require("path"));
|
|
8987
9064
|
var crypto4 = __toESM(require("crypto"));
|
|
8988
9065
|
var import_chalk = __toESM(require("chalk"));
|
|
8989
9066
|
init_provider_cli_adapter();
|
|
@@ -8991,7 +9068,7 @@ init_config();
|
|
|
8991
9068
|
|
|
8992
9069
|
// src/providers/cli-provider-instance.ts
|
|
8993
9070
|
var os9 = __toESM(require("os"));
|
|
8994
|
-
var
|
|
9071
|
+
var path10 = __toESM(require("path"));
|
|
8995
9072
|
var crypto3 = __toESM(require("crypto"));
|
|
8996
9073
|
var fs5 = __toESM(require("fs"));
|
|
8997
9074
|
var import_node_module = require("module");
|
|
@@ -9000,7 +9077,7 @@ init_logger();
|
|
|
9000
9077
|
var CachedDatabaseSync = null;
|
|
9001
9078
|
function getDatabaseSync() {
|
|
9002
9079
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
9003
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
9080
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
9004
9081
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
9005
9082
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
9006
9083
|
if (!CachedDatabaseSync) {
|
|
@@ -9829,8 +9906,9 @@ var AcpProviderInstance = class {
|
|
|
9829
9906
|
async setConfigOption(category, value) {
|
|
9830
9907
|
const opt = this.configOptions.find((c) => c.category === category);
|
|
9831
9908
|
if (!opt) {
|
|
9832
|
-
|
|
9833
|
-
|
|
9909
|
+
const message = `[${this.type}] No config option for category: ${category}`;
|
|
9910
|
+
this.log.warn(message);
|
|
9911
|
+
throw new Error(message);
|
|
9834
9912
|
}
|
|
9835
9913
|
if (this.useStaticConfig) {
|
|
9836
9914
|
opt.currentValue = value;
|
|
@@ -9842,8 +9920,9 @@ var AcpProviderInstance = class {
|
|
|
9842
9920
|
return;
|
|
9843
9921
|
}
|
|
9844
9922
|
if (!this.connection || !this.sessionId) {
|
|
9845
|
-
|
|
9846
|
-
|
|
9923
|
+
const message = `[${this.type}] Cannot set config: no active connection/session`;
|
|
9924
|
+
this.log.warn(message);
|
|
9925
|
+
throw new Error(message);
|
|
9847
9926
|
}
|
|
9848
9927
|
try {
|
|
9849
9928
|
this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
|
|
@@ -9857,7 +9936,9 @@ var AcpProviderInstance = class {
|
|
|
9857
9936
|
if (result?.configOptions) this.parseConfigOptions(result.configOptions);
|
|
9858
9937
|
this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
|
|
9859
9938
|
} catch (e) {
|
|
9860
|
-
|
|
9939
|
+
const message = e?.message || "Unknown ACP config error";
|
|
9940
|
+
this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
|
|
9941
|
+
throw new Error(message);
|
|
9861
9942
|
}
|
|
9862
9943
|
}
|
|
9863
9944
|
async setMode(modeId) {
|
|
@@ -9873,8 +9954,9 @@ var AcpProviderInstance = class {
|
|
|
9873
9954
|
return;
|
|
9874
9955
|
}
|
|
9875
9956
|
if (!this.connection || !this.sessionId) {
|
|
9876
|
-
|
|
9877
|
-
|
|
9957
|
+
const message = `[${this.type}] Cannot set mode: no active connection/session`;
|
|
9958
|
+
this.log.warn(message);
|
|
9959
|
+
throw new Error(message);
|
|
9878
9960
|
}
|
|
9879
9961
|
try {
|
|
9880
9962
|
await this.connection.setSessionMode({
|
|
@@ -9884,7 +9966,9 @@ var AcpProviderInstance = class {
|
|
|
9884
9966
|
this.currentMode = modeId;
|
|
9885
9967
|
this.log.info(`[${this.type}] Mode set to: ${modeId}`);
|
|
9886
9968
|
} catch (e) {
|
|
9887
|
-
|
|
9969
|
+
const message = e?.message || "Unknown ACP mode error";
|
|
9970
|
+
this.log.warn(`[${this.type}] set_mode failed: ${message}`);
|
|
9971
|
+
throw new Error(message);
|
|
9888
9972
|
}
|
|
9889
9973
|
}
|
|
9890
9974
|
/** Static config: kill process and restart with new args */
|
|
@@ -9932,7 +10016,7 @@ var AcpProviderInstance = class {
|
|
|
9932
10016
|
if (!spawnConfig) {
|
|
9933
10017
|
throw new Error(`[ACP:${this.type}] No spawn config defined`);
|
|
9934
10018
|
}
|
|
9935
|
-
const command = spawnConfig.command;
|
|
10019
|
+
const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
|
|
9936
10020
|
let baseArgs = spawnConfig.args || [];
|
|
9937
10021
|
if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
|
|
9938
10022
|
baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
|
|
@@ -10048,13 +10132,13 @@ var AcpProviderInstance = class {
|
|
|
10048
10132
|
}
|
|
10049
10133
|
this.currentStatus = "waiting_approval";
|
|
10050
10134
|
this.detectStatusTransition();
|
|
10051
|
-
const approved = await new Promise((
|
|
10052
|
-
this.permissionResolvers.push(
|
|
10135
|
+
const approved = await new Promise((resolve12) => {
|
|
10136
|
+
this.permissionResolvers.push(resolve12);
|
|
10053
10137
|
setTimeout(() => {
|
|
10054
|
-
const idx = this.permissionResolvers.indexOf(
|
|
10138
|
+
const idx = this.permissionResolvers.indexOf(resolve12);
|
|
10055
10139
|
if (idx >= 0) {
|
|
10056
10140
|
this.permissionResolvers.splice(idx, 1);
|
|
10057
|
-
|
|
10141
|
+
resolve12(false);
|
|
10058
10142
|
}
|
|
10059
10143
|
}, 3e5);
|
|
10060
10144
|
});
|
|
@@ -10761,7 +10845,7 @@ var DaemonCliManager = class {
|
|
|
10761
10845
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
10762
10846
|
const trimmed = (workingDir || "").trim();
|
|
10763
10847
|
if (!trimmed) throw new Error("working directory required");
|
|
10764
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) :
|
|
10848
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
|
|
10765
10849
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10766
10850
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10767
10851
|
const key = crypto4.randomUUID();
|
|
@@ -10848,10 +10932,10 @@ ${installInfo}`
|
|
|
10848
10932
|
if (!cliInfo) {
|
|
10849
10933
|
const installHint = provider?.install || "";
|
|
10850
10934
|
const displayName = provider?.displayName || provider?.name || cliType;
|
|
10851
|
-
const spawnCmd = provider?.spawn?.command || cliType;
|
|
10935
|
+
const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
|
|
10852
10936
|
throw new Error(
|
|
10853
10937
|
`${displayName} is not installed.
|
|
10854
|
-
Command '${spawnCmd}' not
|
|
10938
|
+
Command '${spawnCmd}' is not available.
|
|
10855
10939
|
` + (installHint ? `
|
|
10856
10940
|
${installHint}
|
|
10857
10941
|
` : "") + `
|
|
@@ -11211,16 +11295,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
11211
11295
|
var import_child_process6 = require("child_process");
|
|
11212
11296
|
var net = __toESM(require("net"));
|
|
11213
11297
|
var os12 = __toESM(require("os"));
|
|
11214
|
-
var
|
|
11298
|
+
var path13 = __toESM(require("path"));
|
|
11215
11299
|
|
|
11216
11300
|
// src/providers/provider-loader.ts
|
|
11217
11301
|
var fs6 = __toESM(require("fs"));
|
|
11218
|
-
var
|
|
11302
|
+
var path12 = __toESM(require("path"));
|
|
11219
11303
|
var os11 = __toESM(require("os"));
|
|
11220
11304
|
var chokidar = __toESM(require("chokidar"));
|
|
11221
11305
|
init_logger();
|
|
11222
11306
|
var ProviderLoader = class _ProviderLoader {
|
|
11223
11307
|
providers = /* @__PURE__ */ new Map();
|
|
11308
|
+
providerAvailability = /* @__PURE__ */ new Map();
|
|
11224
11309
|
userDir;
|
|
11225
11310
|
upstreamDir;
|
|
11226
11311
|
disableUpstream;
|
|
@@ -11236,12 +11321,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11236
11321
|
static META_FILE = ".meta.json";
|
|
11237
11322
|
constructor(options) {
|
|
11238
11323
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
11239
|
-
const defaultProvidersDir =
|
|
11324
|
+
const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
|
|
11240
11325
|
if (options?.userDir) {
|
|
11241
11326
|
this.userDir = options.userDir;
|
|
11242
11327
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
11243
11328
|
} else {
|
|
11244
|
-
const localRepoPath =
|
|
11329
|
+
const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
|
|
11245
11330
|
if (fs6.existsSync(localRepoPath)) {
|
|
11246
11331
|
this.userDir = localRepoPath;
|
|
11247
11332
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -11250,7 +11335,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11250
11335
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
11251
11336
|
}
|
|
11252
11337
|
}
|
|
11253
|
-
this.upstreamDir =
|
|
11338
|
+
this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
|
|
11254
11339
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
11255
11340
|
}
|
|
11256
11341
|
log(msg) {
|
|
@@ -11280,7 +11365,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11280
11365
|
* Canonical provider directory shape for a given root.
|
|
11281
11366
|
*/
|
|
11282
11367
|
getProviderDir(root, category, type) {
|
|
11283
|
-
return
|
|
11368
|
+
return path12.join(root, category, type);
|
|
11284
11369
|
}
|
|
11285
11370
|
/**
|
|
11286
11371
|
* Canonical user override directory for a provider.
|
|
@@ -11307,7 +11392,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11307
11392
|
resolveProviderFile(type, ...segments) {
|
|
11308
11393
|
const dir = this.findProviderDirInternal(type);
|
|
11309
11394
|
if (!dir) return null;
|
|
11310
|
-
return
|
|
11395
|
+
return path12.join(dir, ...segments);
|
|
11311
11396
|
}
|
|
11312
11397
|
/**
|
|
11313
11398
|
* Load all providers (3-tier priority)
|
|
@@ -11318,6 +11403,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11318
11403
|
*/
|
|
11319
11404
|
loadAll() {
|
|
11320
11405
|
this.providers.clear();
|
|
11406
|
+
this.providerAvailability.clear();
|
|
11321
11407
|
let upstreamCount = 0;
|
|
11322
11408
|
if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
|
|
11323
11409
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
@@ -11345,7 +11431,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11345
11431
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
11346
11432
|
try {
|
|
11347
11433
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
11348
|
-
(d) => fs6.statSync(
|
|
11434
|
+
(d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
|
|
11349
11435
|
);
|
|
11350
11436
|
} catch {
|
|
11351
11437
|
return false;
|
|
@@ -11388,11 +11474,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11388
11474
|
if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
|
|
11389
11475
|
const verCmdConfig = p.versionCommand;
|
|
11390
11476
|
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
|
|
11477
|
+
const command = this.getSpawnCommand(p.type, p.spawn.command);
|
|
11391
11478
|
result.push({
|
|
11392
11479
|
id: p.type,
|
|
11393
11480
|
displayName: p.displayName || p.name,
|
|
11394
11481
|
icon: p.icon || "\u{1F527}",
|
|
11395
|
-
command
|
|
11482
|
+
command,
|
|
11396
11483
|
category: p.category,
|
|
11397
11484
|
...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
|
|
11398
11485
|
});
|
|
@@ -11521,6 +11608,71 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11521
11608
|
getAvailableIdeTypes() {
|
|
11522
11609
|
return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
|
|
11523
11610
|
}
|
|
11611
|
+
getSpawnCommand(type, fallback) {
|
|
11612
|
+
const override = this.getOptionalStringSetting(type, "executablePath");
|
|
11613
|
+
if (override) return override;
|
|
11614
|
+
return fallback || this.providers.get(type)?.spawn?.command || type;
|
|
11615
|
+
}
|
|
11616
|
+
getIdeCliCommand(type, fallback) {
|
|
11617
|
+
const override = this.getOptionalStringSetting(type, "cliPathOverride");
|
|
11618
|
+
if (override) return override;
|
|
11619
|
+
return fallback || this.providers.get(type)?.cli || null;
|
|
11620
|
+
}
|
|
11621
|
+
getIdePathCandidates(type, fallback) {
|
|
11622
|
+
const override = this.getOptionalStringSetting(type, "appPathOverride");
|
|
11623
|
+
if (override) return [override];
|
|
11624
|
+
if (fallback && fallback.length > 0) return fallback;
|
|
11625
|
+
const osPaths = this.providers.get(type)?.paths?.[process.platform];
|
|
11626
|
+
return Array.isArray(osPaths) ? [...osPaths] : [];
|
|
11627
|
+
}
|
|
11628
|
+
setProviderAvailability(type, state) {
|
|
11629
|
+
this.providerAvailability.set(type, {
|
|
11630
|
+
installed: !!state.installed,
|
|
11631
|
+
detectedPath: state.detectedPath ?? null
|
|
11632
|
+
});
|
|
11633
|
+
}
|
|
11634
|
+
setCliDetectionResults(results, replace = true) {
|
|
11635
|
+
if (replace) {
|
|
11636
|
+
for (const provider of this.providers.values()) {
|
|
11637
|
+
if (provider.category === "cli" || provider.category === "acp") {
|
|
11638
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
11639
|
+
}
|
|
11640
|
+
}
|
|
11641
|
+
}
|
|
11642
|
+
for (const result of results) {
|
|
11643
|
+
this.setProviderAvailability(result.id, {
|
|
11644
|
+
installed: !!result.installed,
|
|
11645
|
+
detectedPath: result.path || null
|
|
11646
|
+
});
|
|
11647
|
+
}
|
|
11648
|
+
}
|
|
11649
|
+
setIdeDetectionResults(results, replace = true) {
|
|
11650
|
+
if (replace) {
|
|
11651
|
+
for (const provider of this.providers.values()) {
|
|
11652
|
+
if (provider.category === "ide") {
|
|
11653
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
11654
|
+
}
|
|
11655
|
+
}
|
|
11656
|
+
}
|
|
11657
|
+
for (const result of results) {
|
|
11658
|
+
this.setProviderAvailability(result.id, {
|
|
11659
|
+
installed: !!result.installed,
|
|
11660
|
+
detectedPath: result.cliCommand || result.path || null
|
|
11661
|
+
});
|
|
11662
|
+
}
|
|
11663
|
+
}
|
|
11664
|
+
getAvailableProviderInfos() {
|
|
11665
|
+
return this.getAll().map((provider) => {
|
|
11666
|
+
const availability = this.providerAvailability.get(provider.type);
|
|
11667
|
+
return {
|
|
11668
|
+
...provider,
|
|
11669
|
+
...availability ? {
|
|
11670
|
+
installed: availability.installed,
|
|
11671
|
+
detectedPath: availability.detectedPath
|
|
11672
|
+
} : {}
|
|
11673
|
+
};
|
|
11674
|
+
});
|
|
11675
|
+
}
|
|
11524
11676
|
/**
|
|
11525
11677
|
* Register IDE providers to core/detector registry
|
|
11526
11678
|
* → Enables detectIDEs() to detect provider.js-based IDEs
|
|
@@ -11595,8 +11747,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11595
11747
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
11596
11748
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
11597
11749
|
if (providerDir) {
|
|
11598
|
-
const fullDir =
|
|
11599
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11750
|
+
const fullDir = path12.join(providerDir, entry.scriptDir);
|
|
11751
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11600
11752
|
}
|
|
11601
11753
|
matched = true;
|
|
11602
11754
|
}
|
|
@@ -11611,8 +11763,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11611
11763
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11612
11764
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
11613
11765
|
if (providerDir) {
|
|
11614
|
-
const fullDir =
|
|
11615
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11766
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
11767
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11616
11768
|
}
|
|
11617
11769
|
}
|
|
11618
11770
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -11629,8 +11781,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11629
11781
|
resolved._resolvedScriptDir = dirOverride;
|
|
11630
11782
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
11631
11783
|
if (providerDir) {
|
|
11632
|
-
const fullDir =
|
|
11633
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11784
|
+
const fullDir = path12.join(providerDir, dirOverride);
|
|
11785
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11634
11786
|
}
|
|
11635
11787
|
}
|
|
11636
11788
|
} else if (override.scripts) {
|
|
@@ -11646,8 +11798,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11646
11798
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11647
11799
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
11648
11800
|
if (providerDir) {
|
|
11649
|
-
const fullDir =
|
|
11650
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
11801
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
11802
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
11651
11803
|
}
|
|
11652
11804
|
}
|
|
11653
11805
|
}
|
|
@@ -11672,14 +11824,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11672
11824
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
11673
11825
|
return null;
|
|
11674
11826
|
}
|
|
11675
|
-
const dir =
|
|
11827
|
+
const dir = path12.join(providerDir, scriptDir);
|
|
11676
11828
|
if (!fs6.existsSync(dir)) {
|
|
11677
11829
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
11678
11830
|
return null;
|
|
11679
11831
|
}
|
|
11680
11832
|
const cached = this.scriptsCache.get(dir);
|
|
11681
11833
|
if (cached) return cached;
|
|
11682
|
-
const scriptsJs =
|
|
11834
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
11683
11835
|
if (fs6.existsSync(scriptsJs)) {
|
|
11684
11836
|
try {
|
|
11685
11837
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -11721,7 +11873,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11721
11873
|
return;
|
|
11722
11874
|
}
|
|
11723
11875
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
11724
|
-
this.log(`File changed: ${
|
|
11876
|
+
this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
|
|
11725
11877
|
this.reload();
|
|
11726
11878
|
}
|
|
11727
11879
|
};
|
|
@@ -11776,7 +11928,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11776
11928
|
}
|
|
11777
11929
|
const https = require("https");
|
|
11778
11930
|
const { execSync: execSync7 } = require("child_process");
|
|
11779
|
-
const metaPath =
|
|
11931
|
+
const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
11780
11932
|
let prevEtag = "";
|
|
11781
11933
|
let prevTimestamp = 0;
|
|
11782
11934
|
try {
|
|
@@ -11793,7 +11945,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11793
11945
|
return { updated: false };
|
|
11794
11946
|
}
|
|
11795
11947
|
try {
|
|
11796
|
-
const etag = await new Promise((
|
|
11948
|
+
const etag = await new Promise((resolve12, reject) => {
|
|
11797
11949
|
const options = {
|
|
11798
11950
|
method: "HEAD",
|
|
11799
11951
|
hostname: "github.com",
|
|
@@ -11811,7 +11963,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11811
11963
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
11812
11964
|
timeout: 1e4
|
|
11813
11965
|
}, (res2) => {
|
|
11814
|
-
|
|
11966
|
+
resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
11815
11967
|
});
|
|
11816
11968
|
req2.on("error", reject);
|
|
11817
11969
|
req2.on("timeout", () => {
|
|
@@ -11820,7 +11972,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11820
11972
|
});
|
|
11821
11973
|
req2.end();
|
|
11822
11974
|
} else {
|
|
11823
|
-
|
|
11975
|
+
resolve12(res.headers.etag || res.headers["last-modified"] || "");
|
|
11824
11976
|
}
|
|
11825
11977
|
});
|
|
11826
11978
|
req.on("error", reject);
|
|
@@ -11836,17 +11988,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11836
11988
|
return { updated: false };
|
|
11837
11989
|
}
|
|
11838
11990
|
this.log("Downloading latest providers from GitHub...");
|
|
11839
|
-
const tmpTar =
|
|
11840
|
-
const tmpExtract =
|
|
11991
|
+
const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
11992
|
+
const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
11841
11993
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
11842
11994
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
11843
11995
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
11844
11996
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
11845
11997
|
const rootDir = extracted.find(
|
|
11846
|
-
(d) => fs6.statSync(
|
|
11998
|
+
(d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
11847
11999
|
);
|
|
11848
12000
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
11849
|
-
const sourceDir =
|
|
12001
|
+
const sourceDir = path12.join(tmpExtract, rootDir);
|
|
11850
12002
|
const backupDir = this.upstreamDir + ".bak";
|
|
11851
12003
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
11852
12004
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -11884,7 +12036,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11884
12036
|
downloadFile(url, destPath) {
|
|
11885
12037
|
const https = require("https");
|
|
11886
12038
|
const http3 = require("http");
|
|
11887
|
-
return new Promise((
|
|
12039
|
+
return new Promise((resolve12, reject) => {
|
|
11888
12040
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
11889
12041
|
if (redirectCount > 5) {
|
|
11890
12042
|
reject(new Error("Too many redirects"));
|
|
@@ -11904,7 +12056,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11904
12056
|
res.pipe(ws);
|
|
11905
12057
|
ws.on("finish", () => {
|
|
11906
12058
|
ws.close();
|
|
11907
|
-
|
|
12059
|
+
resolve12();
|
|
11908
12060
|
});
|
|
11909
12061
|
ws.on("error", reject);
|
|
11910
12062
|
});
|
|
@@ -11921,8 +12073,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11921
12073
|
copyDirRecursive(src, dest) {
|
|
11922
12074
|
fs6.mkdirSync(dest, { recursive: true });
|
|
11923
12075
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
11924
|
-
const srcPath =
|
|
11925
|
-
const destPath =
|
|
12076
|
+
const srcPath = path12.join(src, entry.name);
|
|
12077
|
+
const destPath = path12.join(dest, entry.name);
|
|
11926
12078
|
if (entry.isDirectory()) {
|
|
11927
12079
|
this.copyDirRecursive(srcPath, destPath);
|
|
11928
12080
|
} else {
|
|
@@ -11933,7 +12085,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11933
12085
|
/** .meta.json save */
|
|
11934
12086
|
writeMeta(metaPath, etag, timestamp) {
|
|
11935
12087
|
try {
|
|
11936
|
-
fs6.mkdirSync(
|
|
12088
|
+
fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
|
|
11937
12089
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
11938
12090
|
etag,
|
|
11939
12091
|
timestamp,
|
|
@@ -11950,7 +12102,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11950
12102
|
const scan = (d) => {
|
|
11951
12103
|
try {
|
|
11952
12104
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
11953
|
-
if (entry.isDirectory()) scan(
|
|
12105
|
+
if (entry.isDirectory()) scan(path12.join(d, entry.name));
|
|
11954
12106
|
else if (entry.name === "provider.json") count++;
|
|
11955
12107
|
}
|
|
11956
12108
|
} catch {
|
|
@@ -11964,9 +12116,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11964
12116
|
* Get public settings schema for a provider (for dashboard UI rendering)
|
|
11965
12117
|
*/
|
|
11966
12118
|
getPublicSettings(type) {
|
|
11967
|
-
const
|
|
11968
|
-
|
|
11969
|
-
return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
12119
|
+
const settings = this.getSettingsSchema(type);
|
|
12120
|
+
return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
11970
12121
|
}
|
|
11971
12122
|
/**
|
|
11972
12123
|
* Get public settings schema for all providers
|
|
@@ -11983,8 +12134,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11983
12134
|
* Resolved setting value for a provider (default + user override)
|
|
11984
12135
|
*/
|
|
11985
12136
|
getSettingValue(type, key) {
|
|
11986
|
-
const
|
|
11987
|
-
const schemaDef = provider?.settings?.[key];
|
|
12137
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
11988
12138
|
const defaultVal = schemaDef ? schemaDef.default : void 0;
|
|
11989
12139
|
try {
|
|
11990
12140
|
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
@@ -11999,10 +12149,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11999
12149
|
* All resolved settings for a provider (default + user override)
|
|
12000
12150
|
*/
|
|
12001
12151
|
getSettings(type) {
|
|
12002
|
-
const
|
|
12003
|
-
if (!provider?.settings) return {};
|
|
12152
|
+
const settings = this.getSettingsSchema(type);
|
|
12004
12153
|
const result = {};
|
|
12005
|
-
for (const [key
|
|
12154
|
+
for (const [key] of Object.entries(settings)) {
|
|
12006
12155
|
result[key] = this.getSettingValue(type, key);
|
|
12007
12156
|
}
|
|
12008
12157
|
return result;
|
|
@@ -12011,11 +12160,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12011
12160
|
* Save provider setting value (writes to config.json)
|
|
12012
12161
|
*/
|
|
12013
12162
|
setSetting(type, key, value) {
|
|
12014
|
-
const
|
|
12015
|
-
const schemaDef = provider?.settings?.[key];
|
|
12163
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
12016
12164
|
if (!schemaDef) return false;
|
|
12017
12165
|
if (!schemaDef.public) return false;
|
|
12018
12166
|
if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
|
|
12167
|
+
if (schemaDef.type === "string" && typeof value !== "string") return false;
|
|
12019
12168
|
if (schemaDef.type === "number") {
|
|
12020
12169
|
if (typeof value !== "number") return false;
|
|
12021
12170
|
if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
|
|
@@ -12036,6 +12185,53 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12036
12185
|
return false;
|
|
12037
12186
|
}
|
|
12038
12187
|
}
|
|
12188
|
+
getOptionalStringSetting(type, key) {
|
|
12189
|
+
const value = this.getSettingValue(type, key);
|
|
12190
|
+
if (typeof value !== "string") return null;
|
|
12191
|
+
const trimmed = value.trim();
|
|
12192
|
+
return trimmed ? trimmed : null;
|
|
12193
|
+
}
|
|
12194
|
+
getSettingsSchema(type) {
|
|
12195
|
+
const provider = this.providers.get(type);
|
|
12196
|
+
if (!provider) return {};
|
|
12197
|
+
return {
|
|
12198
|
+
...this.getSyntheticSettings(type, provider),
|
|
12199
|
+
...provider.settings || {}
|
|
12200
|
+
};
|
|
12201
|
+
}
|
|
12202
|
+
getSyntheticSettings(type, provider) {
|
|
12203
|
+
const result = {};
|
|
12204
|
+
if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
|
|
12205
|
+
result.executablePath = {
|
|
12206
|
+
type: "string",
|
|
12207
|
+
default: "",
|
|
12208
|
+
public: true,
|
|
12209
|
+
label: "Executable path",
|
|
12210
|
+
description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
|
|
12211
|
+
};
|
|
12212
|
+
}
|
|
12213
|
+
if (provider.category === "ide") {
|
|
12214
|
+
if (provider.cli && !provider.settings?.cliPathOverride) {
|
|
12215
|
+
result.cliPathOverride = {
|
|
12216
|
+
type: "string",
|
|
12217
|
+
default: "",
|
|
12218
|
+
public: true,
|
|
12219
|
+
label: "CLI path override",
|
|
12220
|
+
description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
|
|
12221
|
+
};
|
|
12222
|
+
}
|
|
12223
|
+
if (provider.paths && !provider.settings?.appPathOverride) {
|
|
12224
|
+
result.appPathOverride = {
|
|
12225
|
+
type: "string",
|
|
12226
|
+
default: "",
|
|
12227
|
+
public: true,
|
|
12228
|
+
label: "App path override",
|
|
12229
|
+
description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
|
|
12230
|
+
};
|
|
12231
|
+
}
|
|
12232
|
+
}
|
|
12233
|
+
return result;
|
|
12234
|
+
}
|
|
12039
12235
|
// ─── Private ───────────────────────────────────
|
|
12040
12236
|
/**
|
|
12041
12237
|
* Find the on-disk directory for a provider by type.
|
|
@@ -12049,17 +12245,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12049
12245
|
for (const root of searchRoots) {
|
|
12050
12246
|
if (!fs6.existsSync(root)) continue;
|
|
12051
12247
|
const candidate = this.getProviderDir(root, cat, type);
|
|
12052
|
-
if (fs6.existsSync(
|
|
12053
|
-
const catDir =
|
|
12248
|
+
if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
|
|
12249
|
+
const catDir = path12.join(root, cat);
|
|
12054
12250
|
if (fs6.existsSync(catDir)) {
|
|
12055
12251
|
try {
|
|
12056
12252
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
12057
12253
|
if (!entry.isDirectory()) continue;
|
|
12058
|
-
const jsonPath =
|
|
12254
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
12059
12255
|
if (fs6.existsSync(jsonPath)) {
|
|
12060
12256
|
try {
|
|
12061
12257
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
12062
|
-
if (data.type === type) return
|
|
12258
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
12063
12259
|
} catch {
|
|
12064
12260
|
}
|
|
12065
12261
|
}
|
|
@@ -12076,7 +12272,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12076
12272
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
12077
12273
|
*/
|
|
12078
12274
|
buildScriptWrappersFromDir(dir) {
|
|
12079
|
-
const scriptsJs =
|
|
12275
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
12080
12276
|
if (fs6.existsSync(scriptsJs)) {
|
|
12081
12277
|
try {
|
|
12082
12278
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -12090,7 +12286,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12090
12286
|
for (const file of fs6.readdirSync(dir)) {
|
|
12091
12287
|
if (!file.endsWith(".js")) continue;
|
|
12092
12288
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
12093
|
-
const filePath =
|
|
12289
|
+
const filePath = path12.join(dir, file);
|
|
12094
12290
|
result[scriptName] = (...args) => {
|
|
12095
12291
|
try {
|
|
12096
12292
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -12150,7 +12346,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12150
12346
|
}
|
|
12151
12347
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
12152
12348
|
if (hasJson) {
|
|
12153
|
-
const jsonPath =
|
|
12349
|
+
const jsonPath = path12.join(d, "provider.json");
|
|
12154
12350
|
try {
|
|
12155
12351
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
12156
12352
|
const mod = JSON.parse(raw);
|
|
@@ -12163,7 +12359,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12163
12359
|
delete mod.extensionIdPattern_flags;
|
|
12164
12360
|
}
|
|
12165
12361
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
12166
|
-
const scriptsPath =
|
|
12362
|
+
const scriptsPath = path12.join(d, "scripts.js");
|
|
12167
12363
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
12168
12364
|
try {
|
|
12169
12365
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -12189,7 +12385,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12189
12385
|
if (!entry.isDirectory()) continue;
|
|
12190
12386
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
12191
12387
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
12192
|
-
scan(
|
|
12388
|
+
scan(path12.join(d, entry.name));
|
|
12193
12389
|
}
|
|
12194
12390
|
}
|
|
12195
12391
|
};
|
|
@@ -12285,17 +12481,17 @@ async function findFreePort(ports) {
|
|
|
12285
12481
|
throw new Error("No free port found");
|
|
12286
12482
|
}
|
|
12287
12483
|
function checkPortFree(port) {
|
|
12288
|
-
return new Promise((
|
|
12484
|
+
return new Promise((resolve12) => {
|
|
12289
12485
|
const server = net.createServer();
|
|
12290
12486
|
server.unref();
|
|
12291
|
-
server.on("error", () =>
|
|
12487
|
+
server.on("error", () => resolve12(false));
|
|
12292
12488
|
server.listen(port, "127.0.0.1", () => {
|
|
12293
|
-
server.close(() =>
|
|
12489
|
+
server.close(() => resolve12(true));
|
|
12294
12490
|
});
|
|
12295
12491
|
});
|
|
12296
12492
|
}
|
|
12297
12493
|
async function isCdpActive(port) {
|
|
12298
|
-
return new Promise((
|
|
12494
|
+
return new Promise((resolve12) => {
|
|
12299
12495
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
12300
12496
|
timeout: 2e3
|
|
12301
12497
|
}, (res) => {
|
|
@@ -12304,16 +12500,16 @@ async function isCdpActive(port) {
|
|
|
12304
12500
|
res.on("end", () => {
|
|
12305
12501
|
try {
|
|
12306
12502
|
const info = JSON.parse(data);
|
|
12307
|
-
|
|
12503
|
+
resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
12308
12504
|
} catch {
|
|
12309
|
-
|
|
12505
|
+
resolve12(false);
|
|
12310
12506
|
}
|
|
12311
12507
|
});
|
|
12312
12508
|
});
|
|
12313
|
-
req.on("error", () =>
|
|
12509
|
+
req.on("error", () => resolve12(false));
|
|
12314
12510
|
req.on("timeout", () => {
|
|
12315
12511
|
req.destroy();
|
|
12316
|
-
|
|
12512
|
+
resolve12(false);
|
|
12317
12513
|
});
|
|
12318
12514
|
});
|
|
12319
12515
|
}
|
|
@@ -12447,8 +12643,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12447
12643
|
const appNameMap = getMacAppIdentifiers();
|
|
12448
12644
|
const appName = appNameMap[ideId];
|
|
12449
12645
|
if (appName) {
|
|
12450
|
-
const storagePath =
|
|
12451
|
-
process.env.APPDATA ||
|
|
12646
|
+
const storagePath = path13.join(
|
|
12647
|
+
process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
|
|
12452
12648
|
appName,
|
|
12453
12649
|
"storage.json"
|
|
12454
12650
|
);
|
|
@@ -12472,7 +12668,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12472
12668
|
async function launchWithCdp(options = {}) {
|
|
12473
12669
|
const platform9 = os12.platform();
|
|
12474
12670
|
let targetIde;
|
|
12475
|
-
const ides = await detectIDEs();
|
|
12671
|
+
const ides = await detectIDEs(getProviderLoader());
|
|
12476
12672
|
if (options.ideId) {
|
|
12477
12673
|
targetIde = ides.find((i) => i.id === options.ideId && i.installed);
|
|
12478
12674
|
if (!targetIde) {
|
|
@@ -12626,9 +12822,9 @@ init_logger();
|
|
|
12626
12822
|
|
|
12627
12823
|
// src/logging/command-log.ts
|
|
12628
12824
|
var fs7 = __toESM(require("fs"));
|
|
12629
|
-
var
|
|
12825
|
+
var path14 = __toESM(require("path"));
|
|
12630
12826
|
var os13 = __toESM(require("os"));
|
|
12631
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
12827
|
+
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");
|
|
12632
12828
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
12633
12829
|
var MAX_DAYS = 7;
|
|
12634
12830
|
try {
|
|
@@ -12666,13 +12862,13 @@ function getDateStr2() {
|
|
|
12666
12862
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
12667
12863
|
}
|
|
12668
12864
|
var currentDate2 = getDateStr2();
|
|
12669
|
-
var currentFile =
|
|
12865
|
+
var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12670
12866
|
var writeCount2 = 0;
|
|
12671
12867
|
function checkRotation() {
|
|
12672
12868
|
const today = getDateStr2();
|
|
12673
12869
|
if (today !== currentDate2) {
|
|
12674
12870
|
currentDate2 = today;
|
|
12675
|
-
currentFile =
|
|
12871
|
+
currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12676
12872
|
cleanOldFiles();
|
|
12677
12873
|
}
|
|
12678
12874
|
}
|
|
@@ -12686,7 +12882,7 @@ function cleanOldFiles() {
|
|
|
12686
12882
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
12687
12883
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
12688
12884
|
try {
|
|
12689
|
-
fs7.unlinkSync(
|
|
12885
|
+
fs7.unlinkSync(path14.join(LOG_DIR2, file));
|
|
12690
12886
|
} catch {
|
|
12691
12887
|
}
|
|
12692
12888
|
}
|
|
@@ -12778,12 +12974,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
|
12778
12974
|
}));
|
|
12779
12975
|
}
|
|
12780
12976
|
function buildAvailableProviders(providerLoader) {
|
|
12781
|
-
|
|
12977
|
+
const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
|
|
12978
|
+
return providers.map((provider) => ({
|
|
12782
12979
|
type: provider.type,
|
|
12783
12980
|
name: provider.displayName || provider.type,
|
|
12784
12981
|
displayName: provider.displayName || provider.type,
|
|
12785
12982
|
icon: provider.icon || "\u{1F4BB}",
|
|
12786
|
-
category: provider.category
|
|
12983
|
+
category: provider.category,
|
|
12984
|
+
...provider.installed !== void 0 ? { installed: provider.installed } : {},
|
|
12985
|
+
...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
|
|
12787
12986
|
}));
|
|
12788
12987
|
}
|
|
12789
12988
|
function parseMessageTime(value) {
|
|
@@ -12911,13 +13110,13 @@ var import_child_process7 = require("child_process");
|
|
|
12911
13110
|
var import_child_process8 = require("child_process");
|
|
12912
13111
|
var fs8 = __toESM(require("fs"));
|
|
12913
13112
|
var os15 = __toESM(require("os"));
|
|
12914
|
-
var
|
|
13113
|
+
var path15 = __toESM(require("path"));
|
|
12915
13114
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
12916
13115
|
function getUpgradeLogPath() {
|
|
12917
13116
|
const home = os15.homedir();
|
|
12918
|
-
const dir =
|
|
13117
|
+
const dir = path15.join(home, ".adhdev");
|
|
12919
13118
|
fs8.mkdirSync(dir, { recursive: true });
|
|
12920
|
-
return
|
|
13119
|
+
return path15.join(dir, "daemon-upgrade.log");
|
|
12921
13120
|
}
|
|
12922
13121
|
function appendUpgradeLog(message) {
|
|
12923
13122
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -12950,14 +13149,14 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
12950
13149
|
while (Date.now() - start < timeoutMs) {
|
|
12951
13150
|
try {
|
|
12952
13151
|
process.kill(pid, 0);
|
|
12953
|
-
await new Promise((
|
|
13152
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
12954
13153
|
} catch {
|
|
12955
13154
|
return;
|
|
12956
13155
|
}
|
|
12957
13156
|
}
|
|
12958
13157
|
}
|
|
12959
13158
|
function stopSessionHostProcesses(appName) {
|
|
12960
|
-
const pidFile =
|
|
13159
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
12961
13160
|
try {
|
|
12962
13161
|
if (fs8.existsSync(pidFile)) {
|
|
12963
13162
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -12986,7 +13185,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
12986
13185
|
}
|
|
12987
13186
|
}
|
|
12988
13187
|
function removeDaemonPidFile() {
|
|
12989
|
-
const pidFile =
|
|
13188
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
|
|
12990
13189
|
try {
|
|
12991
13190
|
fs8.unlinkSync(pidFile);
|
|
12992
13191
|
} catch {
|
|
@@ -12997,7 +13196,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
12997
13196
|
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
12998
13197
|
if (!npmRoot) return;
|
|
12999
13198
|
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
13000
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
13199
|
+
const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
|
|
13001
13200
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
13002
13201
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
13003
13202
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -13005,25 +13204,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
13005
13204
|
}
|
|
13006
13205
|
if (pkgName.startsWith("@")) {
|
|
13007
13206
|
const [scope, name] = pkgName.split("/");
|
|
13008
|
-
const scopeDir =
|
|
13207
|
+
const scopeDir = path15.join(npmRoot, scope);
|
|
13009
13208
|
if (!fs8.existsSync(scopeDir)) return;
|
|
13010
13209
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
13011
13210
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
13012
|
-
fs8.rmSync(
|
|
13013
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
13211
|
+
fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
|
|
13212
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
|
|
13014
13213
|
}
|
|
13015
13214
|
} else {
|
|
13016
13215
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
13017
13216
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
13018
|
-
fs8.rmSync(
|
|
13019
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
13217
|
+
fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
|
|
13218
|
+
appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
|
|
13020
13219
|
}
|
|
13021
13220
|
}
|
|
13022
13221
|
if (fs8.existsSync(binDir)) {
|
|
13023
13222
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
13024
13223
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
13025
|
-
fs8.rmSync(
|
|
13026
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
13224
|
+
fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
|
|
13225
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
|
|
13027
13226
|
}
|
|
13028
13227
|
}
|
|
13029
13228
|
}
|
|
@@ -13065,7 +13264,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
13065
13264
|
appendUpgradeLog(installOutput.trim());
|
|
13066
13265
|
}
|
|
13067
13266
|
if (process.platform === "win32") {
|
|
13068
|
-
await new Promise((
|
|
13267
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
13069
13268
|
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
13070
13269
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
13071
13270
|
}
|
|
@@ -13343,6 +13542,12 @@ var DaemonCommandRouter = class {
|
|
|
13343
13542
|
if (!ideType) throw new Error("ideType required");
|
|
13344
13543
|
const killProcess = args?.killProcess !== false;
|
|
13345
13544
|
await this.stopIde(ideType, killProcess);
|
|
13545
|
+
try {
|
|
13546
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13547
|
+
this.deps.detectedIdes.value = results;
|
|
13548
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13549
|
+
} catch {
|
|
13550
|
+
}
|
|
13346
13551
|
return { success: true, ideType, stopped: true, processKilled: killProcess };
|
|
13347
13552
|
}
|
|
13348
13553
|
// ─── IDE restart ───
|
|
@@ -13385,6 +13590,12 @@ var DaemonCommandRouter = class {
|
|
|
13385
13590
|
}
|
|
13386
13591
|
}
|
|
13387
13592
|
this.deps.onIdeConnected?.();
|
|
13593
|
+
try {
|
|
13594
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13595
|
+
this.deps.detectedIdes.value = results;
|
|
13596
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13597
|
+
} catch {
|
|
13598
|
+
}
|
|
13388
13599
|
if (result.success && resolvedWorkspace) {
|
|
13389
13600
|
try {
|
|
13390
13601
|
const next = appendRecentActivity(loadState(), {
|
|
@@ -13412,8 +13623,9 @@ var DaemonCommandRouter = class {
|
|
|
13412
13623
|
}
|
|
13413
13624
|
// ─── Detect IDEs ───
|
|
13414
13625
|
case "detect_ides": {
|
|
13415
|
-
const results = await detectIDEs();
|
|
13626
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13416
13627
|
this.deps.detectedIdes.value = results;
|
|
13628
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13417
13629
|
return { success: true, detectedInfo: results };
|
|
13418
13630
|
}
|
|
13419
13631
|
// ─── Set User Name ───
|
|
@@ -13927,7 +14139,10 @@ var ProviderStreamAdapter = class {
|
|
|
13927
14139
|
const raw = await evaluate(script, 1e4);
|
|
13928
14140
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
13929
14141
|
if (data?.error) return [];
|
|
13930
|
-
|
|
14142
|
+
if (Array.isArray(data)) return data;
|
|
14143
|
+
if (Array.isArray(data?.sessions)) return data.sessions;
|
|
14144
|
+
if (Array.isArray(data?.chats)) return data.chats;
|
|
14145
|
+
return [];
|
|
13931
14146
|
} catch {
|
|
13932
14147
|
return [];
|
|
13933
14148
|
}
|
|
@@ -13935,7 +14150,17 @@ var ProviderStreamAdapter = class {
|
|
|
13935
14150
|
async switchSession(evaluate, sessionId) {
|
|
13936
14151
|
const script = this.callScript("switchSession", sessionId);
|
|
13937
14152
|
if (!script) return false;
|
|
13938
|
-
|
|
14153
|
+
const raw = await evaluate(script, 1e4);
|
|
14154
|
+
const data = this.parseMaybeJson(raw);
|
|
14155
|
+
if (data === true) return true;
|
|
14156
|
+
if (typeof data === "string") {
|
|
14157
|
+
const normalized = data.trim().toLowerCase();
|
|
14158
|
+
return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
|
|
14159
|
+
}
|
|
14160
|
+
if (data && typeof data === "object") {
|
|
14161
|
+
return data.switched === true || data.success === true || data.ok === true;
|
|
14162
|
+
}
|
|
14163
|
+
return false;
|
|
13939
14164
|
}
|
|
13940
14165
|
async focusEditor(evaluate) {
|
|
13941
14166
|
const script = this.callScript("focusEditor");
|
|
@@ -14625,11 +14850,11 @@ var ProviderInstanceManager = class {
|
|
|
14625
14850
|
|
|
14626
14851
|
// src/providers/version-archive.ts
|
|
14627
14852
|
var fs10 = __toESM(require("fs"));
|
|
14628
|
-
var
|
|
14853
|
+
var path16 = __toESM(require("path"));
|
|
14629
14854
|
var os16 = __toESM(require("os"));
|
|
14630
14855
|
var import_child_process9 = require("child_process");
|
|
14631
14856
|
var import_os3 = require("os");
|
|
14632
|
-
var ARCHIVE_PATH =
|
|
14857
|
+
var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
14633
14858
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
14634
14859
|
var VersionArchive = class {
|
|
14635
14860
|
history = {};
|
|
@@ -14676,7 +14901,7 @@ var VersionArchive = class {
|
|
|
14676
14901
|
}
|
|
14677
14902
|
save() {
|
|
14678
14903
|
try {
|
|
14679
|
-
fs10.mkdirSync(
|
|
14904
|
+
fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
|
|
14680
14905
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
14681
14906
|
} catch {
|
|
14682
14907
|
}
|
|
@@ -14717,7 +14942,7 @@ function checkPathExists2(paths) {
|
|
|
14717
14942
|
for (const p of paths) {
|
|
14718
14943
|
if (p.includes("*")) {
|
|
14719
14944
|
const home = os16.homedir();
|
|
14720
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
14945
|
+
const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
|
|
14721
14946
|
if (fs10.existsSync(resolved)) return resolved;
|
|
14722
14947
|
} else {
|
|
14723
14948
|
if (fs10.existsSync(p)) return p;
|
|
@@ -14727,7 +14952,7 @@ function checkPathExists2(paths) {
|
|
|
14727
14952
|
}
|
|
14728
14953
|
function getMacAppVersion(appPath) {
|
|
14729
14954
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
14730
|
-
const plistPath =
|
|
14955
|
+
const plistPath = path16.join(appPath, "Contents", "Info.plist");
|
|
14731
14956
|
if (!fs10.existsSync(plistPath)) return null;
|
|
14732
14957
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
14733
14958
|
return raw || null;
|
|
@@ -14754,7 +14979,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14754
14979
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
14755
14980
|
let resolvedBin = cliBin;
|
|
14756
14981
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
14757
|
-
const bundled =
|
|
14982
|
+
const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
14758
14983
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
14759
14984
|
}
|
|
14760
14985
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -14795,7 +15020,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14795
15020
|
// src/daemon/dev-server.ts
|
|
14796
15021
|
var http2 = __toESM(require("http"));
|
|
14797
15022
|
var fs14 = __toESM(require("fs"));
|
|
14798
|
-
var
|
|
15023
|
+
var path20 = __toESM(require("path"));
|
|
14799
15024
|
|
|
14800
15025
|
// src/daemon/scaffold-template.ts
|
|
14801
15026
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -15131,7 +15356,7 @@ init_logger();
|
|
|
15131
15356
|
|
|
15132
15357
|
// src/daemon/dev-cdp-handlers.ts
|
|
15133
15358
|
var fs11 = __toESM(require("fs"));
|
|
15134
|
-
var
|
|
15359
|
+
var path17 = __toESM(require("path"));
|
|
15135
15360
|
init_logger();
|
|
15136
15361
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
15137
15362
|
const body = await ctx.readBody(req);
|
|
@@ -15310,17 +15535,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
15310
15535
|
return;
|
|
15311
15536
|
}
|
|
15312
15537
|
let scriptsPath = "";
|
|
15313
|
-
const directScripts =
|
|
15538
|
+
const directScripts = path17.join(dir, "scripts.js");
|
|
15314
15539
|
if (fs11.existsSync(directScripts)) {
|
|
15315
15540
|
scriptsPath = directScripts;
|
|
15316
15541
|
} else {
|
|
15317
|
-
const scriptsDir =
|
|
15542
|
+
const scriptsDir = path17.join(dir, "scripts");
|
|
15318
15543
|
if (fs11.existsSync(scriptsDir)) {
|
|
15319
15544
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
15320
|
-
return fs11.statSync(
|
|
15545
|
+
return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
15321
15546
|
}).sort().reverse();
|
|
15322
15547
|
for (const ver of versions) {
|
|
15323
|
-
const p =
|
|
15548
|
+
const p = path17.join(scriptsDir, ver, "scripts.js");
|
|
15324
15549
|
if (fs11.existsSync(p)) {
|
|
15325
15550
|
scriptsPath = p;
|
|
15326
15551
|
break;
|
|
@@ -16139,7 +16364,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
16139
16364
|
|
|
16140
16365
|
// src/daemon/dev-cli-debug.ts
|
|
16141
16366
|
var fs12 = __toESM(require("fs"));
|
|
16142
|
-
var
|
|
16367
|
+
var path18 = __toESM(require("path"));
|
|
16143
16368
|
function slugifyFixtureName(value) {
|
|
16144
16369
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
16145
16370
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -16149,11 +16374,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
16149
16374
|
if (!providerDir) {
|
|
16150
16375
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
16151
16376
|
}
|
|
16152
|
-
return
|
|
16377
|
+
return path18.join(providerDir, "fixtures");
|
|
16153
16378
|
}
|
|
16154
16379
|
function readCliFixture(ctx, type, name) {
|
|
16155
16380
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
16156
|
-
const filePath =
|
|
16381
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
16157
16382
|
if (!fs12.existsSync(filePath)) {
|
|
16158
16383
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
16159
16384
|
}
|
|
@@ -16313,7 +16538,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
16313
16538
|
return { target, instance, adapter };
|
|
16314
16539
|
}
|
|
16315
16540
|
function sleep(ms) {
|
|
16316
|
-
return new Promise((
|
|
16541
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
16317
16542
|
}
|
|
16318
16543
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
16319
16544
|
const startedAt = Date.now();
|
|
@@ -16912,7 +17137,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
16912
17137
|
},
|
|
16913
17138
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
16914
17139
|
};
|
|
16915
|
-
const filePath =
|
|
17140
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
16916
17141
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
16917
17142
|
ctx.json(res, 200, {
|
|
16918
17143
|
saved: true,
|
|
@@ -16936,7 +17161,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
16936
17161
|
return;
|
|
16937
17162
|
}
|
|
16938
17163
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
16939
|
-
const fullPath =
|
|
17164
|
+
const fullPath = path18.join(fixtureDir, file);
|
|
16940
17165
|
try {
|
|
16941
17166
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
16942
17167
|
return {
|
|
@@ -17072,7 +17297,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
17072
17297
|
|
|
17073
17298
|
// src/daemon/dev-auto-implement.ts
|
|
17074
17299
|
var fs13 = __toESM(require("fs"));
|
|
17075
|
-
var
|
|
17300
|
+
var path19 = __toESM(require("path"));
|
|
17076
17301
|
var os17 = __toESM(require("os"));
|
|
17077
17302
|
function getAutoImplPid(ctx) {
|
|
17078
17303
|
const proc = ctx.autoImplProcess;
|
|
@@ -17112,22 +17337,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
17112
17337
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
17113
17338
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
17114
17339
|
try {
|
|
17115
|
-
return fs13.statSync(
|
|
17340
|
+
return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
|
|
17116
17341
|
} catch {
|
|
17117
17342
|
return false;
|
|
17118
17343
|
}
|
|
17119
17344
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
17120
17345
|
if (versions.length === 0) return null;
|
|
17121
|
-
return
|
|
17346
|
+
return path19.join(scriptsDir, versions[0]);
|
|
17122
17347
|
}
|
|
17123
17348
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
17124
|
-
const canonicalUserDir =
|
|
17125
|
-
const desiredDir = requestedDir ?
|
|
17126
|
-
const upstreamRoot =
|
|
17127
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
17349
|
+
const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
17350
|
+
const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
|
|
17351
|
+
const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
|
|
17352
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
|
|
17128
17353
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
17129
17354
|
}
|
|
17130
|
-
if (
|
|
17355
|
+
if (path19.basename(desiredDir) !== type) {
|
|
17131
17356
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
17132
17357
|
}
|
|
17133
17358
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -17135,11 +17360,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
17135
17360
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
17136
17361
|
}
|
|
17137
17362
|
if (!fs13.existsSync(desiredDir)) {
|
|
17138
|
-
fs13.mkdirSync(
|
|
17363
|
+
fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
|
|
17139
17364
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
17140
17365
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
17141
17366
|
}
|
|
17142
|
-
const providerJson =
|
|
17367
|
+
const providerJson = path19.join(desiredDir, "provider.json");
|
|
17143
17368
|
if (!fs13.existsSync(providerJson)) {
|
|
17144
17369
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
17145
17370
|
}
|
|
@@ -17162,13 +17387,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
17162
17387
|
const refDir = ctx.findProviderDir(referenceType);
|
|
17163
17388
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
17164
17389
|
const referenceScripts = {};
|
|
17165
|
-
const scriptsDir =
|
|
17390
|
+
const scriptsDir = path19.join(refDir, "scripts");
|
|
17166
17391
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
17167
17392
|
if (!latestDir) return referenceScripts;
|
|
17168
17393
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
17169
17394
|
if (!file.endsWith(".js")) continue;
|
|
17170
17395
|
try {
|
|
17171
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
17396
|
+
referenceScripts[file] = fs13.readFileSync(path19.join(latestDir, file), "utf-8");
|
|
17172
17397
|
} catch {
|
|
17173
17398
|
}
|
|
17174
17399
|
}
|
|
@@ -17276,9 +17501,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
17276
17501
|
});
|
|
17277
17502
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
17278
17503
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
17279
|
-
const tmpDir =
|
|
17504
|
+
const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
17280
17505
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
17281
|
-
const promptFile =
|
|
17506
|
+
const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
17282
17507
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
17283
17508
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
17284
17509
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -17705,7 +17930,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17705
17930
|
setMode: "set_mode.js"
|
|
17706
17931
|
};
|
|
17707
17932
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
17708
|
-
const scriptsDir =
|
|
17933
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
17709
17934
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
17710
17935
|
if (latestScriptsDir) {
|
|
17711
17936
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -17716,7 +17941,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17716
17941
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
17717
17942
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
17718
17943
|
try {
|
|
17719
|
-
const content = fs13.readFileSync(
|
|
17944
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17720
17945
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
17721
17946
|
lines.push("```javascript");
|
|
17722
17947
|
lines.push(content);
|
|
@@ -17733,7 +17958,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17733
17958
|
lines.push("");
|
|
17734
17959
|
for (const file of refFiles) {
|
|
17735
17960
|
try {
|
|
17736
|
-
const content = fs13.readFileSync(
|
|
17961
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17737
17962
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
17738
17963
|
lines.push("```javascript");
|
|
17739
17964
|
lines.push(content);
|
|
@@ -17774,10 +17999,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17774
17999
|
lines.push("");
|
|
17775
18000
|
}
|
|
17776
18001
|
}
|
|
17777
|
-
const docsDir =
|
|
18002
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
17778
18003
|
const loadGuide = (name) => {
|
|
17779
18004
|
try {
|
|
17780
|
-
const p =
|
|
18005
|
+
const p = path19.join(docsDir, name);
|
|
17781
18006
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
17782
18007
|
} catch {
|
|
17783
18008
|
}
|
|
@@ -18012,7 +18237,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18012
18237
|
parseApproval: "parse_approval.js"
|
|
18013
18238
|
};
|
|
18014
18239
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
18015
|
-
const scriptsDir =
|
|
18240
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
18016
18241
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
18017
18242
|
if (latestScriptsDir) {
|
|
18018
18243
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -18024,7 +18249,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18024
18249
|
if (!file.endsWith(".js")) continue;
|
|
18025
18250
|
if (!targetFileNames.has(file)) continue;
|
|
18026
18251
|
try {
|
|
18027
|
-
const content = fs13.readFileSync(
|
|
18252
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
18028
18253
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
18029
18254
|
lines.push("```javascript");
|
|
18030
18255
|
lines.push(content);
|
|
@@ -18040,7 +18265,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18040
18265
|
lines.push("");
|
|
18041
18266
|
for (const file of refFiles) {
|
|
18042
18267
|
try {
|
|
18043
|
-
const content = fs13.readFileSync(
|
|
18268
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
18044
18269
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
18045
18270
|
lines.push("```javascript");
|
|
18046
18271
|
lines.push(content);
|
|
@@ -18073,10 +18298,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
18073
18298
|
lines.push("");
|
|
18074
18299
|
}
|
|
18075
18300
|
}
|
|
18076
|
-
const docsDir =
|
|
18301
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
18077
18302
|
const loadGuide = (name) => {
|
|
18078
18303
|
try {
|
|
18079
|
-
const p =
|
|
18304
|
+
const p = path19.join(docsDir, name);
|
|
18080
18305
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
18081
18306
|
} catch {
|
|
18082
18307
|
}
|
|
@@ -18487,8 +18712,8 @@ var DevServer = class _DevServer {
|
|
|
18487
18712
|
}
|
|
18488
18713
|
getEndpointList() {
|
|
18489
18714
|
return this.routes.map((r) => {
|
|
18490
|
-
const
|
|
18491
|
-
return `${r.method.padEnd(5)} ${
|
|
18715
|
+
const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
18716
|
+
return `${r.method.padEnd(5)} ${path21}`;
|
|
18492
18717
|
});
|
|
18493
18718
|
}
|
|
18494
18719
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -18519,15 +18744,15 @@ var DevServer = class _DevServer {
|
|
|
18519
18744
|
this.json(res, 500, { error: e.message });
|
|
18520
18745
|
}
|
|
18521
18746
|
});
|
|
18522
|
-
return new Promise((
|
|
18747
|
+
return new Promise((resolve12, reject) => {
|
|
18523
18748
|
this.server.listen(port, "127.0.0.1", () => {
|
|
18524
18749
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
18525
|
-
|
|
18750
|
+
resolve12();
|
|
18526
18751
|
});
|
|
18527
18752
|
this.server.on("error", (e) => {
|
|
18528
18753
|
if (e.code === "EADDRINUSE") {
|
|
18529
18754
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
18530
|
-
|
|
18755
|
+
resolve12();
|
|
18531
18756
|
} else {
|
|
18532
18757
|
reject(e);
|
|
18533
18758
|
}
|
|
@@ -18610,20 +18835,20 @@ var DevServer = class _DevServer {
|
|
|
18610
18835
|
child.stderr?.on("data", (d) => {
|
|
18611
18836
|
stderr += d.toString().slice(0, 2e3);
|
|
18612
18837
|
});
|
|
18613
|
-
await new Promise((
|
|
18838
|
+
await new Promise((resolve12) => {
|
|
18614
18839
|
const timer = setTimeout(() => {
|
|
18615
18840
|
child.kill();
|
|
18616
|
-
|
|
18841
|
+
resolve12();
|
|
18617
18842
|
}, 3e3);
|
|
18618
18843
|
child.on("exit", () => {
|
|
18619
18844
|
clearTimeout(timer);
|
|
18620
|
-
|
|
18845
|
+
resolve12();
|
|
18621
18846
|
});
|
|
18622
18847
|
child.stdout?.once("data", () => {
|
|
18623
18848
|
setTimeout(() => {
|
|
18624
18849
|
child.kill();
|
|
18625
18850
|
clearTimeout(timer);
|
|
18626
|
-
|
|
18851
|
+
resolve12();
|
|
18627
18852
|
}, 500);
|
|
18628
18853
|
});
|
|
18629
18854
|
});
|
|
@@ -18770,12 +18995,12 @@ var DevServer = class _DevServer {
|
|
|
18770
18995
|
// ─── DevConsole SPA ───
|
|
18771
18996
|
getConsoleDistDir() {
|
|
18772
18997
|
const candidates = [
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18998
|
+
path20.resolve(__dirname, "../../web-devconsole/dist"),
|
|
18999
|
+
path20.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
19000
|
+
path20.join(process.cwd(), "packages/web-devconsole/dist")
|
|
18776
19001
|
];
|
|
18777
19002
|
for (const dir of candidates) {
|
|
18778
|
-
if (fs14.existsSync(
|
|
19003
|
+
if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
|
|
18779
19004
|
}
|
|
18780
19005
|
return null;
|
|
18781
19006
|
}
|
|
@@ -18785,7 +19010,7 @@ var DevServer = class _DevServer {
|
|
|
18785
19010
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
18786
19011
|
return;
|
|
18787
19012
|
}
|
|
18788
|
-
const htmlPath =
|
|
19013
|
+
const htmlPath = path20.join(distDir, "index.html");
|
|
18789
19014
|
try {
|
|
18790
19015
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
18791
19016
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -18810,15 +19035,15 @@ var DevServer = class _DevServer {
|
|
|
18810
19035
|
this.json(res, 404, { error: "Not found" });
|
|
18811
19036
|
return;
|
|
18812
19037
|
}
|
|
18813
|
-
const safePath =
|
|
18814
|
-
const filePath =
|
|
19038
|
+
const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
|
|
19039
|
+
const filePath = path20.join(distDir, safePath);
|
|
18815
19040
|
if (!filePath.startsWith(distDir)) {
|
|
18816
19041
|
this.json(res, 403, { error: "Forbidden" });
|
|
18817
19042
|
return;
|
|
18818
19043
|
}
|
|
18819
19044
|
try {
|
|
18820
19045
|
const content = fs14.readFileSync(filePath);
|
|
18821
|
-
const ext =
|
|
19046
|
+
const ext = path20.extname(filePath);
|
|
18822
19047
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
18823
19048
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
18824
19049
|
res.end(content);
|
|
@@ -18931,9 +19156,9 @@ var DevServer = class _DevServer {
|
|
|
18931
19156
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18932
19157
|
if (entry.isDirectory()) {
|
|
18933
19158
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
18934
|
-
scan(
|
|
19159
|
+
scan(path20.join(d, entry.name), rel);
|
|
18935
19160
|
} else {
|
|
18936
|
-
const stat = fs14.statSync(
|
|
19161
|
+
const stat = fs14.statSync(path20.join(d, entry.name));
|
|
18937
19162
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
18938
19163
|
}
|
|
18939
19164
|
}
|
|
@@ -18956,7 +19181,7 @@ var DevServer = class _DevServer {
|
|
|
18956
19181
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18957
19182
|
return;
|
|
18958
19183
|
}
|
|
18959
|
-
const fullPath =
|
|
19184
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18960
19185
|
if (!fullPath.startsWith(dir)) {
|
|
18961
19186
|
this.json(res, 403, { error: "Forbidden" });
|
|
18962
19187
|
return;
|
|
@@ -18981,14 +19206,14 @@ var DevServer = class _DevServer {
|
|
|
18981
19206
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18982
19207
|
return;
|
|
18983
19208
|
}
|
|
18984
|
-
const fullPath =
|
|
19209
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18985
19210
|
if (!fullPath.startsWith(dir)) {
|
|
18986
19211
|
this.json(res, 403, { error: "Forbidden" });
|
|
18987
19212
|
return;
|
|
18988
19213
|
}
|
|
18989
19214
|
try {
|
|
18990
19215
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
18991
|
-
fs14.mkdirSync(
|
|
19216
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
18992
19217
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
18993
19218
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
18994
19219
|
this.providerLoader.reload();
|
|
@@ -19005,7 +19230,7 @@ var DevServer = class _DevServer {
|
|
|
19005
19230
|
return;
|
|
19006
19231
|
}
|
|
19007
19232
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
19008
|
-
const p =
|
|
19233
|
+
const p = path20.join(dir, name);
|
|
19009
19234
|
if (fs14.existsSync(p)) {
|
|
19010
19235
|
const source = fs14.readFileSync(p, "utf-8");
|
|
19011
19236
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -19026,8 +19251,8 @@ var DevServer = class _DevServer {
|
|
|
19026
19251
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
19027
19252
|
return;
|
|
19028
19253
|
}
|
|
19029
|
-
const target = fs14.existsSync(
|
|
19030
|
-
const targetPath =
|
|
19254
|
+
const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
19255
|
+
const targetPath = path20.join(dir, target);
|
|
19031
19256
|
try {
|
|
19032
19257
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
19033
19258
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -19132,14 +19357,14 @@ var DevServer = class _DevServer {
|
|
|
19132
19357
|
child.stderr?.on("data", (d) => {
|
|
19133
19358
|
stderr += d.toString();
|
|
19134
19359
|
});
|
|
19135
|
-
await new Promise((
|
|
19360
|
+
await new Promise((resolve12) => {
|
|
19136
19361
|
const timer = setTimeout(() => {
|
|
19137
19362
|
child.kill();
|
|
19138
|
-
|
|
19363
|
+
resolve12();
|
|
19139
19364
|
}, timeout);
|
|
19140
19365
|
child.on("exit", () => {
|
|
19141
19366
|
clearTimeout(timer);
|
|
19142
|
-
|
|
19367
|
+
resolve12();
|
|
19143
19368
|
});
|
|
19144
19369
|
});
|
|
19145
19370
|
const elapsed = Date.now() - start;
|
|
@@ -19187,7 +19412,7 @@ var DevServer = class _DevServer {
|
|
|
19187
19412
|
}
|
|
19188
19413
|
let targetDir;
|
|
19189
19414
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
19190
|
-
const jsonPath =
|
|
19415
|
+
const jsonPath = path20.join(targetDir, "provider.json");
|
|
19191
19416
|
if (fs14.existsSync(jsonPath)) {
|
|
19192
19417
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
19193
19418
|
return;
|
|
@@ -19199,8 +19424,8 @@ var DevServer = class _DevServer {
|
|
|
19199
19424
|
const createdFiles = ["provider.json"];
|
|
19200
19425
|
if (result.files) {
|
|
19201
19426
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
19202
|
-
const fullPath =
|
|
19203
|
-
fs14.mkdirSync(
|
|
19427
|
+
const fullPath = path20.join(targetDir, relPath);
|
|
19428
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
19204
19429
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
19205
19430
|
createdFiles.push(relPath);
|
|
19206
19431
|
}
|
|
@@ -19253,22 +19478,22 @@ var DevServer = class _DevServer {
|
|
|
19253
19478
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
19254
19479
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
19255
19480
|
try {
|
|
19256
|
-
return fs14.statSync(
|
|
19481
|
+
return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
19257
19482
|
} catch {
|
|
19258
19483
|
return false;
|
|
19259
19484
|
}
|
|
19260
19485
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
19261
19486
|
if (versions.length === 0) return null;
|
|
19262
|
-
return
|
|
19487
|
+
return path20.join(scriptsDir, versions[0]);
|
|
19263
19488
|
}
|
|
19264
19489
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
19265
|
-
const canonicalUserDir =
|
|
19266
|
-
const desiredDir = requestedDir ?
|
|
19267
|
-
const upstreamRoot =
|
|
19268
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
19490
|
+
const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
19491
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
19492
|
+
const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
|
|
19493
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
19269
19494
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
19270
19495
|
}
|
|
19271
|
-
if (
|
|
19496
|
+
if (path20.basename(desiredDir) !== type) {
|
|
19272
19497
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
19273
19498
|
}
|
|
19274
19499
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -19276,11 +19501,11 @@ var DevServer = class _DevServer {
|
|
|
19276
19501
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
19277
19502
|
}
|
|
19278
19503
|
if (!fs14.existsSync(desiredDir)) {
|
|
19279
|
-
fs14.mkdirSync(
|
|
19504
|
+
fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
19280
19505
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
19281
19506
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
19282
19507
|
}
|
|
19283
|
-
const providerJson =
|
|
19508
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
19284
19509
|
if (!fs14.existsSync(providerJson)) {
|
|
19285
19510
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
19286
19511
|
}
|
|
@@ -19328,7 +19553,7 @@ var DevServer = class _DevServer {
|
|
|
19328
19553
|
setMode: "set_mode.js"
|
|
19329
19554
|
};
|
|
19330
19555
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19331
|
-
const scriptsDir =
|
|
19556
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19332
19557
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19333
19558
|
if (latestScriptsDir) {
|
|
19334
19559
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19339,7 +19564,7 @@ var DevServer = class _DevServer {
|
|
|
19339
19564
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
19340
19565
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
19341
19566
|
try {
|
|
19342
|
-
const content = fs14.readFileSync(
|
|
19567
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19343
19568
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19344
19569
|
lines.push("```javascript");
|
|
19345
19570
|
lines.push(content);
|
|
@@ -19356,7 +19581,7 @@ var DevServer = class _DevServer {
|
|
|
19356
19581
|
lines.push("");
|
|
19357
19582
|
for (const file of refFiles) {
|
|
19358
19583
|
try {
|
|
19359
|
-
const content = fs14.readFileSync(
|
|
19584
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19360
19585
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19361
19586
|
lines.push("```javascript");
|
|
19362
19587
|
lines.push(content);
|
|
@@ -19397,10 +19622,10 @@ var DevServer = class _DevServer {
|
|
|
19397
19622
|
lines.push("");
|
|
19398
19623
|
}
|
|
19399
19624
|
}
|
|
19400
|
-
const docsDir =
|
|
19625
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19401
19626
|
const loadGuide = (name) => {
|
|
19402
19627
|
try {
|
|
19403
|
-
const p =
|
|
19628
|
+
const p = path20.join(docsDir, name);
|
|
19404
19629
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19405
19630
|
} catch {
|
|
19406
19631
|
}
|
|
@@ -19574,7 +19799,7 @@ var DevServer = class _DevServer {
|
|
|
19574
19799
|
parseApproval: "parse_approval.js"
|
|
19575
19800
|
};
|
|
19576
19801
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19577
|
-
const scriptsDir =
|
|
19802
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19578
19803
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19579
19804
|
if (latestScriptsDir) {
|
|
19580
19805
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19586,7 +19811,7 @@ var DevServer = class _DevServer {
|
|
|
19586
19811
|
if (!file.endsWith(".js")) continue;
|
|
19587
19812
|
if (!targetFileNames.has(file)) continue;
|
|
19588
19813
|
try {
|
|
19589
|
-
const content = fs14.readFileSync(
|
|
19814
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19590
19815
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19591
19816
|
lines.push("```javascript");
|
|
19592
19817
|
lines.push(content);
|
|
@@ -19602,7 +19827,7 @@ var DevServer = class _DevServer {
|
|
|
19602
19827
|
lines.push("");
|
|
19603
19828
|
for (const file of refFiles) {
|
|
19604
19829
|
try {
|
|
19605
|
-
const content = fs14.readFileSync(
|
|
19830
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19606
19831
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19607
19832
|
lines.push("```javascript");
|
|
19608
19833
|
lines.push(content);
|
|
@@ -19635,10 +19860,10 @@ var DevServer = class _DevServer {
|
|
|
19635
19860
|
lines.push("");
|
|
19636
19861
|
}
|
|
19637
19862
|
}
|
|
19638
|
-
const docsDir =
|
|
19863
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19639
19864
|
const loadGuide = (name) => {
|
|
19640
19865
|
try {
|
|
19641
|
-
const p =
|
|
19866
|
+
const p = path20.join(docsDir, name);
|
|
19642
19867
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19643
19868
|
} catch {
|
|
19644
19869
|
}
|
|
@@ -19814,14 +20039,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
19814
20039
|
res.end(JSON.stringify(data, null, 2));
|
|
19815
20040
|
}
|
|
19816
20041
|
async readBody(req) {
|
|
19817
|
-
return new Promise((
|
|
20042
|
+
return new Promise((resolve12) => {
|
|
19818
20043
|
let body = "";
|
|
19819
20044
|
req.on("data", (chunk) => body += chunk);
|
|
19820
20045
|
req.on("end", () => {
|
|
19821
20046
|
try {
|
|
19822
|
-
|
|
20047
|
+
resolve12(JSON.parse(body));
|
|
19823
20048
|
} catch {
|
|
19824
|
-
|
|
20049
|
+
resolve12({});
|
|
19825
20050
|
}
|
|
19826
20051
|
});
|
|
19827
20052
|
});
|
|
@@ -20289,7 +20514,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
20289
20514
|
const deadline = Date.now() + timeoutMs;
|
|
20290
20515
|
while (Date.now() < deadline) {
|
|
20291
20516
|
if (await canConnect(endpoint)) return;
|
|
20292
|
-
await new Promise((
|
|
20517
|
+
await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
|
|
20293
20518
|
}
|
|
20294
20519
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
20295
20520
|
}
|
|
@@ -20445,10 +20670,10 @@ async function installExtension(ide, extension) {
|
|
|
20445
20670
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
20446
20671
|
const fs15 = await import("fs");
|
|
20447
20672
|
fs15.writeFileSync(vsixPath, buffer);
|
|
20448
|
-
return new Promise((
|
|
20673
|
+
return new Promise((resolve12) => {
|
|
20449
20674
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
20450
20675
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
20451
|
-
|
|
20676
|
+
resolve12({
|
|
20452
20677
|
extensionId: extension.id,
|
|
20453
20678
|
marketplaceId: extension.marketplaceId,
|
|
20454
20679
|
success: !error,
|
|
@@ -20461,11 +20686,11 @@ async function installExtension(ide, extension) {
|
|
|
20461
20686
|
} catch (e) {
|
|
20462
20687
|
}
|
|
20463
20688
|
}
|
|
20464
|
-
return new Promise((
|
|
20689
|
+
return new Promise((resolve12) => {
|
|
20465
20690
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
20466
20691
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
20467
20692
|
if (error) {
|
|
20468
|
-
|
|
20693
|
+
resolve12({
|
|
20469
20694
|
extensionId: extension.id,
|
|
20470
20695
|
marketplaceId: extension.marketplaceId,
|
|
20471
20696
|
success: false,
|
|
@@ -20473,7 +20698,7 @@ async function installExtension(ide, extension) {
|
|
|
20473
20698
|
error: stderr || error.message
|
|
20474
20699
|
});
|
|
20475
20700
|
} else {
|
|
20476
|
-
|
|
20701
|
+
resolve12({
|
|
20477
20702
|
extensionId: extension.id,
|
|
20478
20703
|
marketplaceId: extension.marketplaceId,
|
|
20479
20704
|
success: true,
|
|
@@ -20609,13 +20834,32 @@ async function initDaemonComponents(config) {
|
|
|
20609
20834
|
const detectedIdesRef = { value: [] };
|
|
20610
20835
|
let agentStreamManager = null;
|
|
20611
20836
|
let poller = null;
|
|
20837
|
+
const refreshProviderAvailability = async (providerType) => {
|
|
20838
|
+
const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
|
|
20839
|
+
const targetCategory = targetProvider?.category;
|
|
20840
|
+
if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
|
|
20841
|
+
if (providerType && targetProvider) {
|
|
20842
|
+
const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
|
|
20843
|
+
providerLoader.setProviderAvailability(targetProvider.type, {
|
|
20844
|
+
installed: !!detected,
|
|
20845
|
+
detectedPath: detected?.path || null
|
|
20846
|
+
});
|
|
20847
|
+
} else {
|
|
20848
|
+
providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
|
|
20849
|
+
}
|
|
20850
|
+
}
|
|
20851
|
+
if (!providerType || targetCategory === "ide") {
|
|
20852
|
+
detectedIdesRef.value = await detectIDEs(providerLoader);
|
|
20853
|
+
providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
|
|
20854
|
+
}
|
|
20855
|
+
};
|
|
20612
20856
|
const cliManager = new DaemonCliManager({
|
|
20613
20857
|
...config.cliManagerDeps,
|
|
20614
20858
|
getInstanceManager: () => instanceManager,
|
|
20615
20859
|
getSessionRegistry: () => sessionRegistry
|
|
20616
20860
|
}, providerLoader);
|
|
20617
20861
|
LOG.info("Init", "Detecting IDEs...");
|
|
20618
|
-
|
|
20862
|
+
await refreshProviderAvailability();
|
|
20619
20863
|
const installed = detectedIdesRef.value.filter((i) => i.installed);
|
|
20620
20864
|
LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
|
|
20621
20865
|
const cdpSetupContext = {
|
|
@@ -20655,7 +20899,11 @@ async function initDaemonComponents(config) {
|
|
|
20655
20899
|
adapters: cliManager.adapters,
|
|
20656
20900
|
providerLoader,
|
|
20657
20901
|
instanceManager,
|
|
20658
|
-
sessionRegistry
|
|
20902
|
+
sessionRegistry,
|
|
20903
|
+
onProviderSettingChanged: async (providerType) => {
|
|
20904
|
+
await refreshProviderAvailability(providerType);
|
|
20905
|
+
config.onStatusChange?.();
|
|
20906
|
+
}
|
|
20659
20907
|
});
|
|
20660
20908
|
agentStreamManager = new DaemonAgentStreamManager(
|
|
20661
20909
|
LOG.forComponent("AgentStream").asLogFn(),
|