@adhdev/daemon-core 0.8.25 → 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/agent-stream/provider-adapter.d.ts +1 -0
- package/dist/boot/daemon-lifecycle.d.ts +2 -0
- package/dist/cli-adapters/pty-transport.d.ts +3 -0
- package/dist/commands/handler.d.ts +1 -0
- package/dist/commands/router.d.ts +24 -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 +824 -369
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +822 -367
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +1 -1
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/dist/providers/extension-provider-instance.d.ts +7 -0
- package/dist/providers/provider-loader.d.ts +26 -0
- package/dist/shared-types.d.ts +2 -0
- package/dist/status/normalize.js +14 -2
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +14 -2
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/snapshot.d.ts +8 -2
- package/node_modules/@adhdev/session-host-core/dist/index.d.mts +72 -1
- package/node_modules/@adhdev/session-host-core/dist/index.d.ts +72 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/provider-adapter.ts +45 -3
- package/src/boot/daemon-lifecycle.ts +31 -1
- package/src/cli-adapters/provider-cli-adapter.ts +14 -3
- package/src/cli-adapters/pty-transport.ts +3 -0
- package/src/cli-adapters/session-host-transport.ts +8 -0
- package/src/commands/chat-commands.ts +38 -9
- package/src/commands/cli-manager.ts +2 -2
- package/src/commands/handler.ts +26 -3
- package/src/commands/router.ts +144 -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/cli-provider-instance.ts +29 -1
- package/src/providers/extension-provider-instance.ts +24 -1
- package/src/providers/provider-loader.ts +144 -11
- package/src/shared-types.ts +2 -0
- package/src/status/normalize.ts +19 -2
- package/src/status/snapshot.ts +25 -14
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) {
|
|
@@ -5201,6 +5249,7 @@ var ExtensionProviderInstance = class {
|
|
|
5201
5249
|
currentStatus = "idle";
|
|
5202
5250
|
agentStreams = [];
|
|
5203
5251
|
messages = [];
|
|
5252
|
+
prevMessageHashes = /* @__PURE__ */ new Map();
|
|
5204
5253
|
activeModal = null;
|
|
5205
5254
|
currentModel = "";
|
|
5206
5255
|
currentMode = "";
|
|
@@ -5266,7 +5315,7 @@ var ExtensionProviderInstance = class {
|
|
|
5266
5315
|
onEvent(event, data) {
|
|
5267
5316
|
if (event === "stream_update") {
|
|
5268
5317
|
if (data?.streams) this.agentStreams = data.streams;
|
|
5269
|
-
if (data?.messages) this.messages = data.messages;
|
|
5318
|
+
if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
|
|
5270
5319
|
if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
|
|
5271
5320
|
if (data?.model) this.currentModel = data.model;
|
|
5272
5321
|
if (data?.mode) this.currentMode = data.mode;
|
|
@@ -5292,6 +5341,7 @@ var ExtensionProviderInstance = class {
|
|
|
5292
5341
|
dispose() {
|
|
5293
5342
|
this.agentStreams = [];
|
|
5294
5343
|
this.messages = [];
|
|
5344
|
+
this.prevMessageHashes.clear();
|
|
5295
5345
|
this.monitor.reset();
|
|
5296
5346
|
this.appliedEffectKeys.clear();
|
|
5297
5347
|
this.runtimeMessages = [];
|
|
@@ -5447,6 +5497,23 @@ var ExtensionProviderInstance = class {
|
|
|
5447
5497
|
this.chatId || this.instanceId
|
|
5448
5498
|
);
|
|
5449
5499
|
}
|
|
5500
|
+
/**
|
|
5501
|
+
* Assign stable receivedAt to extension messages.
|
|
5502
|
+
* Same pattern as IdeProviderInstance.readChat() prevByHash —
|
|
5503
|
+
* preserves first-seen timestamp across polling cycles.
|
|
5504
|
+
*/
|
|
5505
|
+
assignReceivedAt(messages) {
|
|
5506
|
+
const now = Date.now();
|
|
5507
|
+
const nextHashes = /* @__PURE__ */ new Map();
|
|
5508
|
+
for (const msg of messages) {
|
|
5509
|
+
const hash = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
|
|
5510
|
+
const prevTime = this.prevMessageHashes.get(hash);
|
|
5511
|
+
msg.receivedAt = prevTime || now;
|
|
5512
|
+
nextHashes.set(hash, msg.receivedAt);
|
|
5513
|
+
}
|
|
5514
|
+
this.prevMessageHashes = nextHashes;
|
|
5515
|
+
return messages;
|
|
5516
|
+
}
|
|
5450
5517
|
mergeConversationMessages(messages) {
|
|
5451
5518
|
if (this.runtimeMessages.length === 0) return messages;
|
|
5452
5519
|
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
|
|
@@ -5503,6 +5570,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
5503
5570
|
}
|
|
5504
5571
|
this.agentStreams = [];
|
|
5505
5572
|
this.messages = [];
|
|
5573
|
+
this.prevMessageHashes.clear();
|
|
5506
5574
|
this.activeModal = null;
|
|
5507
5575
|
this.currentModel = "";
|
|
5508
5576
|
this.currentMode = "";
|
|
@@ -6488,16 +6556,28 @@ function trimMessageForStatus(message, stringLimit) {
|
|
|
6488
6556
|
if (!message || typeof message !== "object") return message;
|
|
6489
6557
|
return trimStructuredStrings(message, stringLimit);
|
|
6490
6558
|
}
|
|
6559
|
+
function normalizeMessageTime(message) {
|
|
6560
|
+
if (!message || typeof message !== "object") return message;
|
|
6561
|
+
const msg = message;
|
|
6562
|
+
if (msg.receivedAt == null) {
|
|
6563
|
+
const fallback = msg.timestamp ?? msg.createdAt;
|
|
6564
|
+
if (fallback != null) {
|
|
6565
|
+
const ts2 = typeof fallback === "string" ? Date.parse(fallback) : Number(fallback);
|
|
6566
|
+
if (Number.isFinite(ts2) && ts2 > 0) msg.receivedAt = ts2;
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
return msg;
|
|
6570
|
+
}
|
|
6491
6571
|
function trimMessagesForStatus(messages) {
|
|
6492
6572
|
if (!Array.isArray(messages) || messages.length === 0) return [];
|
|
6493
6573
|
const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
|
|
6494
6574
|
const kept = [];
|
|
6495
6575
|
let totalBytes = 0;
|
|
6496
6576
|
for (let i = recent.length - 1; i >= 0; i -= 1) {
|
|
6497
|
-
let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
|
|
6577
|
+
let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT));
|
|
6498
6578
|
let size = estimateBytes(normalized);
|
|
6499
6579
|
if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
6500
|
-
normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
|
|
6580
|
+
normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT));
|
|
6501
6581
|
size = estimateBytes(normalized);
|
|
6502
6582
|
}
|
|
6503
6583
|
if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
@@ -7120,7 +7200,7 @@ async function handleSendChat(h, args) {
|
|
|
7120
7200
|
if (isExtensionTransport(transport)) {
|
|
7121
7201
|
_log(`Extension: ${provider?.type || "unknown_extension"}`);
|
|
7122
7202
|
try {
|
|
7123
|
-
const evalResult = await h.evaluateProviderScript("sendMessage", {
|
|
7203
|
+
const evalResult = await h.evaluateProviderScript("sendMessage", { message: text }, 3e4);
|
|
7124
7204
|
if (evalResult?.result) {
|
|
7125
7205
|
const parsed = parseMaybeJson(evalResult.result);
|
|
7126
7206
|
if (didProviderConfirmSend(parsed)) {
|
|
@@ -7151,7 +7231,7 @@ async function handleSendChat(h, args) {
|
|
|
7151
7231
|
return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
|
|
7152
7232
|
}
|
|
7153
7233
|
_log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
|
|
7154
|
-
const sendScript = h.getProviderScript("sendMessage", {
|
|
7234
|
+
const sendScript = h.getProviderScript("sendMessage", { message: text });
|
|
7155
7235
|
if (sendScript) {
|
|
7156
7236
|
try {
|
|
7157
7237
|
const result = await targetCdp.evaluate(sendScript, 3e4);
|
|
@@ -7291,6 +7371,14 @@ async function handleListChats(h, args) {
|
|
|
7291
7371
|
} catch {
|
|
7292
7372
|
}
|
|
7293
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
|
+
}
|
|
7294
7382
|
if (Array.isArray(parsed)) {
|
|
7295
7383
|
LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
|
|
7296
7384
|
return { success: true, chats: parsed };
|
|
@@ -7360,7 +7448,13 @@ async function handleSwitchChat(h, args) {
|
|
|
7360
7448
|
} catch (e) {
|
|
7361
7449
|
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
7362
7450
|
}
|
|
7363
|
-
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);
|
|
7364
7458
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
7365
7459
|
try {
|
|
7366
7460
|
const raw = await cdp.evaluate(script, 15e3);
|
|
@@ -7439,8 +7533,8 @@ async function handleSetMode(h, args) {
|
|
|
7439
7533
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
7440
7534
|
if (adapter) {
|
|
7441
7535
|
const acpInstance = adapter._acpInstance;
|
|
7442
|
-
if (acpInstance && typeof acpInstance.
|
|
7443
|
-
acpInstance.
|
|
7536
|
+
if (acpInstance && typeof acpInstance.setMode === "function") {
|
|
7537
|
+
await acpInstance.setMode(mode);
|
|
7444
7538
|
return { success: true, mode };
|
|
7445
7539
|
}
|
|
7446
7540
|
}
|
|
@@ -7497,9 +7591,9 @@ async function handleChangeModel(h, args) {
|
|
|
7497
7591
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
7498
7592
|
if (adapter) {
|
|
7499
7593
|
const acpInstance = adapter._acpInstance;
|
|
7500
|
-
if (acpInstance && typeof acpInstance.
|
|
7501
|
-
acpInstance.
|
|
7502
|
-
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}`);
|
|
7503
7597
|
return { success: true, model };
|
|
7504
7598
|
}
|
|
7505
7599
|
}
|
|
@@ -7619,6 +7713,18 @@ async function handleResolveAction(h, args) {
|
|
|
7619
7713
|
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
7620
7714
|
return { success: ok };
|
|
7621
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
|
+
}
|
|
7622
7728
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
7623
7729
|
const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
7624
7730
|
if (script) {
|
|
@@ -7697,7 +7803,7 @@ async function handleResolveAction(h, args) {
|
|
|
7697
7803
|
|
|
7698
7804
|
// src/commands/cdp-commands.ts
|
|
7699
7805
|
var fs4 = __toESM(require("fs"));
|
|
7700
|
-
var
|
|
7806
|
+
var path8 = __toESM(require("path"));
|
|
7701
7807
|
var os6 = __toESM(require("os"));
|
|
7702
7808
|
var KEY_TO_VK = {
|
|
7703
7809
|
Backspace: 8,
|
|
@@ -7949,25 +8055,25 @@ function resolveSafePath(requestedPath) {
|
|
|
7949
8055
|
const inputPath = rawPath || ".";
|
|
7950
8056
|
const home = os6.homedir();
|
|
7951
8057
|
if (inputPath.startsWith("~")) {
|
|
7952
|
-
return
|
|
8058
|
+
return path8.resolve(path8.join(home, inputPath.slice(1)));
|
|
7953
8059
|
}
|
|
7954
8060
|
if (process.platform === "win32") {
|
|
7955
8061
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
7956
|
-
if (
|
|
7957
|
-
return
|
|
8062
|
+
if (path8.win32.isAbsolute(normalized)) {
|
|
8063
|
+
return path8.win32.normalize(normalized);
|
|
7958
8064
|
}
|
|
7959
|
-
return
|
|
8065
|
+
return path8.win32.resolve(normalized);
|
|
7960
8066
|
}
|
|
7961
|
-
if (
|
|
7962
|
-
return
|
|
8067
|
+
if (path8.isAbsolute(inputPath)) {
|
|
8068
|
+
return path8.normalize(inputPath);
|
|
7963
8069
|
}
|
|
7964
|
-
return
|
|
8070
|
+
return path8.resolve(inputPath);
|
|
7965
8071
|
}
|
|
7966
8072
|
function listDirectoryEntriesSafe(dirPath) {
|
|
7967
8073
|
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
7968
8074
|
const files = [];
|
|
7969
8075
|
for (const entry of entries) {
|
|
7970
|
-
const entryPath =
|
|
8076
|
+
const entryPath = path8.join(dirPath, entry.name);
|
|
7971
8077
|
try {
|
|
7972
8078
|
if (entry.isDirectory()) {
|
|
7973
8079
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -8006,7 +8112,7 @@ async function handleFileRead(h, args) {
|
|
|
8006
8112
|
async function handleFileWrite(h, args) {
|
|
8007
8113
|
try {
|
|
8008
8114
|
const filePath = resolveSafePath(args?.path);
|
|
8009
|
-
fs4.mkdirSync(
|
|
8115
|
+
fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
|
|
8010
8116
|
fs4.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
8011
8117
|
return { success: true, path: filePath };
|
|
8012
8118
|
} catch (e) {
|
|
@@ -8094,7 +8200,7 @@ function handleGetProviderSettings(h, args) {
|
|
|
8094
8200
|
}
|
|
8095
8201
|
return { success: true, settings: allSettings, values: allValues };
|
|
8096
8202
|
}
|
|
8097
|
-
function handleSetProviderSetting(h, args) {
|
|
8203
|
+
async function handleSetProviderSetting(h, args) {
|
|
8098
8204
|
const loader = h.ctx.providerLoader;
|
|
8099
8205
|
const { providerType, key, value } = args || {};
|
|
8100
8206
|
if (!providerType || !key || value === void 0) {
|
|
@@ -8107,6 +8213,7 @@ function handleSetProviderSetting(h, args) {
|
|
|
8107
8213
|
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
8108
8214
|
LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
|
|
8109
8215
|
}
|
|
8216
|
+
await h.ctx.onProviderSettingChanged?.(providerType, key, value);
|
|
8110
8217
|
return { success: true, providerType, key, value };
|
|
8111
8218
|
}
|
|
8112
8219
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
@@ -8144,10 +8251,10 @@ function getCliScriptCommand(payload) {
|
|
|
8144
8251
|
}
|
|
8145
8252
|
const command = payload.command;
|
|
8146
8253
|
if (!command || typeof command !== "object") return null;
|
|
8147
|
-
if (command.type !== "send_message") return null;
|
|
8254
|
+
if (command.type !== "send_message" && command.type !== "pty_write") return null;
|
|
8148
8255
|
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
8149
8256
|
if (!text) return null;
|
|
8150
|
-
return { type:
|
|
8257
|
+
return { type: command.type, text };
|
|
8151
8258
|
}
|
|
8152
8259
|
function applyProviderPatch(h, args, payload) {
|
|
8153
8260
|
if (!payload || typeof payload !== "object") return;
|
|
@@ -8188,6 +8295,8 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8188
8295
|
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
8189
8296
|
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
8190
8297
|
await adapter.sendMessage(cliCommand.text);
|
|
8298
|
+
} else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
|
|
8299
|
+
adapter.writeRaw(cliCommand.text + "\r");
|
|
8191
8300
|
}
|
|
8192
8301
|
applyProviderPatch(h, args, parsed.payload);
|
|
8193
8302
|
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
@@ -8553,9 +8662,26 @@ var DaemonCommandHandler = class {
|
|
|
8553
8662
|
if (provider?.scripts) {
|
|
8554
8663
|
const fn = provider.scripts[scriptName];
|
|
8555
8664
|
if (typeof fn === "function") {
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8665
|
+
if (params && Object.keys(params).length > 0) {
|
|
8666
|
+
const firstVal = Object.values(params)[0];
|
|
8667
|
+
if (scriptName === "sendMessage" && typeof firstVal === "string") {
|
|
8668
|
+
const legacyScript = fn(firstVal);
|
|
8669
|
+
if (legacyScript) return legacyScript;
|
|
8670
|
+
}
|
|
8671
|
+
const script = fn(params);
|
|
8672
|
+
if (script) {
|
|
8673
|
+
const likelyLegacyObjectLeak = typeof script === "string" && script.includes("[object Object]") && typeof firstVal === "string";
|
|
8674
|
+
if (!likelyLegacyObjectLeak) return script;
|
|
8675
|
+
}
|
|
8676
|
+
if (firstVal !== void 0) {
|
|
8677
|
+
const legacyScript = fn(firstVal);
|
|
8678
|
+
if (legacyScript) return legacyScript;
|
|
8679
|
+
}
|
|
8680
|
+
if (script) return script;
|
|
8681
|
+
} else {
|
|
8682
|
+
const script = fn();
|
|
8683
|
+
if (script) return script;
|
|
8684
|
+
}
|
|
8559
8685
|
}
|
|
8560
8686
|
}
|
|
8561
8687
|
return null;
|
|
@@ -8849,7 +8975,7 @@ var DaemonCommandHandler = class {
|
|
|
8849
8975
|
try {
|
|
8850
8976
|
const http3 = await import("http");
|
|
8851
8977
|
const postData = JSON.stringify(body);
|
|
8852
|
-
const result = await new Promise((
|
|
8978
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8853
8979
|
const req = http3.request({
|
|
8854
8980
|
hostname: "127.0.0.1",
|
|
8855
8981
|
port: 19280,
|
|
@@ -8861,9 +8987,9 @@ var DaemonCommandHandler = class {
|
|
|
8861
8987
|
res.on("data", (chunk) => data += chunk);
|
|
8862
8988
|
res.on("end", () => {
|
|
8863
8989
|
try {
|
|
8864
|
-
|
|
8990
|
+
resolve12(JSON.parse(data));
|
|
8865
8991
|
} catch {
|
|
8866
|
-
|
|
8992
|
+
resolve12({ raw: data });
|
|
8867
8993
|
}
|
|
8868
8994
|
});
|
|
8869
8995
|
});
|
|
@@ -8881,15 +9007,15 @@ var DaemonCommandHandler = class {
|
|
|
8881
9007
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
8882
9008
|
try {
|
|
8883
9009
|
const http3 = await import("http");
|
|
8884
|
-
const result = await new Promise((
|
|
9010
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8885
9011
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
8886
9012
|
let data = "";
|
|
8887
9013
|
res.on("data", (chunk) => data += chunk);
|
|
8888
9014
|
res.on("end", () => {
|
|
8889
9015
|
try {
|
|
8890
|
-
|
|
9016
|
+
resolve12(JSON.parse(data));
|
|
8891
9017
|
} catch {
|
|
8892
|
-
|
|
9018
|
+
resolve12({ raw: data });
|
|
8893
9019
|
}
|
|
8894
9020
|
});
|
|
8895
9021
|
}).on("error", reject);
|
|
@@ -8903,7 +9029,7 @@ var DaemonCommandHandler = class {
|
|
|
8903
9029
|
try {
|
|
8904
9030
|
const http3 = await import("http");
|
|
8905
9031
|
const postData = JSON.stringify(args || {});
|
|
8906
|
-
const result = await new Promise((
|
|
9032
|
+
const result = await new Promise((resolve12, reject) => {
|
|
8907
9033
|
const req = http3.request({
|
|
8908
9034
|
hostname: "127.0.0.1",
|
|
8909
9035
|
port: 19280,
|
|
@@ -8915,9 +9041,9 @@ var DaemonCommandHandler = class {
|
|
|
8915
9041
|
res.on("data", (chunk) => data += chunk);
|
|
8916
9042
|
res.on("end", () => {
|
|
8917
9043
|
try {
|
|
8918
|
-
|
|
9044
|
+
resolve12(JSON.parse(data));
|
|
8919
9045
|
} catch {
|
|
8920
|
-
|
|
9046
|
+
resolve12({ raw: data });
|
|
8921
9047
|
}
|
|
8922
9048
|
});
|
|
8923
9049
|
});
|
|
@@ -8934,7 +9060,7 @@ var DaemonCommandHandler = class {
|
|
|
8934
9060
|
|
|
8935
9061
|
// src/commands/cli-manager.ts
|
|
8936
9062
|
var os10 = __toESM(require("os"));
|
|
8937
|
-
var
|
|
9063
|
+
var path11 = __toESM(require("path"));
|
|
8938
9064
|
var crypto4 = __toESM(require("crypto"));
|
|
8939
9065
|
var import_chalk = __toESM(require("chalk"));
|
|
8940
9066
|
init_provider_cli_adapter();
|
|
@@ -8942,7 +9068,7 @@ init_config();
|
|
|
8942
9068
|
|
|
8943
9069
|
// src/providers/cli-provider-instance.ts
|
|
8944
9070
|
var os9 = __toESM(require("os"));
|
|
8945
|
-
var
|
|
9071
|
+
var path10 = __toESM(require("path"));
|
|
8946
9072
|
var crypto3 = __toESM(require("crypto"));
|
|
8947
9073
|
var fs5 = __toESM(require("fs"));
|
|
8948
9074
|
var import_node_module = require("module");
|
|
@@ -8951,7 +9077,7 @@ init_logger();
|
|
|
8951
9077
|
var CachedDatabaseSync = null;
|
|
8952
9078
|
function getDatabaseSync() {
|
|
8953
9079
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
8954
|
-
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"));
|
|
8955
9081
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
8956
9082
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
8957
9083
|
if (!CachedDatabaseSync) {
|
|
@@ -9016,6 +9142,7 @@ var CliProviderInstance = class {
|
|
|
9016
9142
|
this.detectStatusTransition();
|
|
9017
9143
|
});
|
|
9018
9144
|
await this.adapter.spawn();
|
|
9145
|
+
this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
|
|
9019
9146
|
if (this.providerSessionId) {
|
|
9020
9147
|
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
9021
9148
|
if (restoredHistory.messages.length > 0) {
|
|
@@ -9110,6 +9237,7 @@ var CliProviderInstance = class {
|
|
|
9110
9237
|
this.promoteProviderSessionId(parsedProviderSessionId);
|
|
9111
9238
|
}
|
|
9112
9239
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
9240
|
+
this.maybeAppendRuntimeRecoveryMessage(runtime);
|
|
9113
9241
|
const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
9114
9242
|
const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
|
|
9115
9243
|
if (controlValues) {
|
|
@@ -9436,6 +9564,28 @@ ${effect.notification.body || ""}`.trim();
|
|
|
9436
9564
|
const pad = (value) => String(value).padStart(2, "0");
|
|
9437
9565
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
9438
9566
|
}
|
|
9567
|
+
maybeAppendRuntimeRecoveryMessage(runtime) {
|
|
9568
|
+
if (!runtime?.restoredFromStorage || !runtime.runtimeId) return;
|
|
9569
|
+
const recoveryState = String(runtime.recoveryState || "").trim();
|
|
9570
|
+
if (!recoveryState) return;
|
|
9571
|
+
let content = "";
|
|
9572
|
+
if (recoveryState === "auto_resumed") {
|
|
9573
|
+
content = "Session host restored this CLI after restart and reattached it from a saved snapshot.";
|
|
9574
|
+
} else if (recoveryState === "resume_failed") {
|
|
9575
|
+
const errorSuffix = runtime.recoveryError ? ` Resume failed: ${runtime.recoveryError}` : "";
|
|
9576
|
+
content = `Session host found this CLI after restart, but automatic resume failed.${errorSuffix}`;
|
|
9577
|
+
} else if (recoveryState === "host_restart_interrupted") {
|
|
9578
|
+
content = "Session host found this CLI in interrupted state after restart and is attempting to resume it.";
|
|
9579
|
+
} else if (recoveryState === "orphan_snapshot") {
|
|
9580
|
+
content = "Session host restored the last snapshot for this CLI, but the original runtime was not resumed automatically.";
|
|
9581
|
+
} else {
|
|
9582
|
+
content = `Session host restored this CLI after restart (${recoveryState}).`;
|
|
9583
|
+
}
|
|
9584
|
+
this.appendRuntimeSystemMessage(
|
|
9585
|
+
content,
|
|
9586
|
+
`runtime_recovery:${runtime.runtimeId}:${recoveryState}`
|
|
9587
|
+
);
|
|
9588
|
+
}
|
|
9439
9589
|
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
9440
9590
|
const normalizedContent = String(content || "").trim();
|
|
9441
9591
|
if (!normalizedContent) return;
|
|
@@ -9756,8 +9906,9 @@ var AcpProviderInstance = class {
|
|
|
9756
9906
|
async setConfigOption(category, value) {
|
|
9757
9907
|
const opt = this.configOptions.find((c) => c.category === category);
|
|
9758
9908
|
if (!opt) {
|
|
9759
|
-
|
|
9760
|
-
|
|
9909
|
+
const message = `[${this.type}] No config option for category: ${category}`;
|
|
9910
|
+
this.log.warn(message);
|
|
9911
|
+
throw new Error(message);
|
|
9761
9912
|
}
|
|
9762
9913
|
if (this.useStaticConfig) {
|
|
9763
9914
|
opt.currentValue = value;
|
|
@@ -9769,8 +9920,9 @@ var AcpProviderInstance = class {
|
|
|
9769
9920
|
return;
|
|
9770
9921
|
}
|
|
9771
9922
|
if (!this.connection || !this.sessionId) {
|
|
9772
|
-
|
|
9773
|
-
|
|
9923
|
+
const message = `[${this.type}] Cannot set config: no active connection/session`;
|
|
9924
|
+
this.log.warn(message);
|
|
9925
|
+
throw new Error(message);
|
|
9774
9926
|
}
|
|
9775
9927
|
try {
|
|
9776
9928
|
this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
|
|
@@ -9784,7 +9936,9 @@ var AcpProviderInstance = class {
|
|
|
9784
9936
|
if (result?.configOptions) this.parseConfigOptions(result.configOptions);
|
|
9785
9937
|
this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
|
|
9786
9938
|
} catch (e) {
|
|
9787
|
-
|
|
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);
|
|
9788
9942
|
}
|
|
9789
9943
|
}
|
|
9790
9944
|
async setMode(modeId) {
|
|
@@ -9800,8 +9954,9 @@ var AcpProviderInstance = class {
|
|
|
9800
9954
|
return;
|
|
9801
9955
|
}
|
|
9802
9956
|
if (!this.connection || !this.sessionId) {
|
|
9803
|
-
|
|
9804
|
-
|
|
9957
|
+
const message = `[${this.type}] Cannot set mode: no active connection/session`;
|
|
9958
|
+
this.log.warn(message);
|
|
9959
|
+
throw new Error(message);
|
|
9805
9960
|
}
|
|
9806
9961
|
try {
|
|
9807
9962
|
await this.connection.setSessionMode({
|
|
@@ -9811,7 +9966,9 @@ var AcpProviderInstance = class {
|
|
|
9811
9966
|
this.currentMode = modeId;
|
|
9812
9967
|
this.log.info(`[${this.type}] Mode set to: ${modeId}`);
|
|
9813
9968
|
} catch (e) {
|
|
9814
|
-
|
|
9969
|
+
const message = e?.message || "Unknown ACP mode error";
|
|
9970
|
+
this.log.warn(`[${this.type}] set_mode failed: ${message}`);
|
|
9971
|
+
throw new Error(message);
|
|
9815
9972
|
}
|
|
9816
9973
|
}
|
|
9817
9974
|
/** Static config: kill process and restart with new args */
|
|
@@ -9859,7 +10016,7 @@ var AcpProviderInstance = class {
|
|
|
9859
10016
|
if (!spawnConfig) {
|
|
9860
10017
|
throw new Error(`[ACP:${this.type}] No spawn config defined`);
|
|
9861
10018
|
}
|
|
9862
|
-
const command = spawnConfig.command;
|
|
10019
|
+
const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
|
|
9863
10020
|
let baseArgs = spawnConfig.args || [];
|
|
9864
10021
|
if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
|
|
9865
10022
|
baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
|
|
@@ -9975,13 +10132,13 @@ var AcpProviderInstance = class {
|
|
|
9975
10132
|
}
|
|
9976
10133
|
this.currentStatus = "waiting_approval";
|
|
9977
10134
|
this.detectStatusTransition();
|
|
9978
|
-
const approved = await new Promise((
|
|
9979
|
-
this.permissionResolvers.push(
|
|
10135
|
+
const approved = await new Promise((resolve12) => {
|
|
10136
|
+
this.permissionResolvers.push(resolve12);
|
|
9980
10137
|
setTimeout(() => {
|
|
9981
|
-
const idx = this.permissionResolvers.indexOf(
|
|
10138
|
+
const idx = this.permissionResolvers.indexOf(resolve12);
|
|
9982
10139
|
if (idx >= 0) {
|
|
9983
10140
|
this.permissionResolvers.splice(idx, 1);
|
|
9984
|
-
|
|
10141
|
+
resolve12(false);
|
|
9985
10142
|
}
|
|
9986
10143
|
}, 3e5);
|
|
9987
10144
|
});
|
|
@@ -10688,7 +10845,7 @@ var DaemonCliManager = class {
|
|
|
10688
10845
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
10689
10846
|
const trimmed = (workingDir || "").trim();
|
|
10690
10847
|
if (!trimmed) throw new Error("working directory required");
|
|
10691
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) :
|
|
10848
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
|
|
10692
10849
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
10693
10850
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
10694
10851
|
const key = crypto4.randomUUID();
|
|
@@ -10775,10 +10932,10 @@ ${installInfo}`
|
|
|
10775
10932
|
if (!cliInfo) {
|
|
10776
10933
|
const installHint = provider?.install || "";
|
|
10777
10934
|
const displayName = provider?.displayName || provider?.name || cliType;
|
|
10778
|
-
const spawnCmd = provider?.spawn?.command || cliType;
|
|
10935
|
+
const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
|
|
10779
10936
|
throw new Error(
|
|
10780
10937
|
`${displayName} is not installed.
|
|
10781
|
-
Command '${spawnCmd}' not
|
|
10938
|
+
Command '${spawnCmd}' is not available.
|
|
10782
10939
|
` + (installHint ? `
|
|
10783
10940
|
${installHint}
|
|
10784
10941
|
` : "") + `
|
|
@@ -11138,16 +11295,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
11138
11295
|
var import_child_process6 = require("child_process");
|
|
11139
11296
|
var net = __toESM(require("net"));
|
|
11140
11297
|
var os12 = __toESM(require("os"));
|
|
11141
|
-
var
|
|
11298
|
+
var path13 = __toESM(require("path"));
|
|
11142
11299
|
|
|
11143
11300
|
// src/providers/provider-loader.ts
|
|
11144
11301
|
var fs6 = __toESM(require("fs"));
|
|
11145
|
-
var
|
|
11302
|
+
var path12 = __toESM(require("path"));
|
|
11146
11303
|
var os11 = __toESM(require("os"));
|
|
11147
11304
|
var chokidar = __toESM(require("chokidar"));
|
|
11148
11305
|
init_logger();
|
|
11149
11306
|
var ProviderLoader = class _ProviderLoader {
|
|
11150
11307
|
providers = /* @__PURE__ */ new Map();
|
|
11308
|
+
providerAvailability = /* @__PURE__ */ new Map();
|
|
11151
11309
|
userDir;
|
|
11152
11310
|
upstreamDir;
|
|
11153
11311
|
disableUpstream;
|
|
@@ -11163,12 +11321,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11163
11321
|
static META_FILE = ".meta.json";
|
|
11164
11322
|
constructor(options) {
|
|
11165
11323
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
11166
|
-
const defaultProvidersDir =
|
|
11324
|
+
const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
|
|
11167
11325
|
if (options?.userDir) {
|
|
11168
11326
|
this.userDir = options.userDir;
|
|
11169
11327
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
11170
11328
|
} else {
|
|
11171
|
-
const localRepoPath =
|
|
11329
|
+
const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
|
|
11172
11330
|
if (fs6.existsSync(localRepoPath)) {
|
|
11173
11331
|
this.userDir = localRepoPath;
|
|
11174
11332
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -11177,7 +11335,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11177
11335
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
11178
11336
|
}
|
|
11179
11337
|
}
|
|
11180
|
-
this.upstreamDir =
|
|
11338
|
+
this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
|
|
11181
11339
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
11182
11340
|
}
|
|
11183
11341
|
log(msg) {
|
|
@@ -11207,7 +11365,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11207
11365
|
* Canonical provider directory shape for a given root.
|
|
11208
11366
|
*/
|
|
11209
11367
|
getProviderDir(root, category, type) {
|
|
11210
|
-
return
|
|
11368
|
+
return path12.join(root, category, type);
|
|
11211
11369
|
}
|
|
11212
11370
|
/**
|
|
11213
11371
|
* Canonical user override directory for a provider.
|
|
@@ -11234,7 +11392,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11234
11392
|
resolveProviderFile(type, ...segments) {
|
|
11235
11393
|
const dir = this.findProviderDirInternal(type);
|
|
11236
11394
|
if (!dir) return null;
|
|
11237
|
-
return
|
|
11395
|
+
return path12.join(dir, ...segments);
|
|
11238
11396
|
}
|
|
11239
11397
|
/**
|
|
11240
11398
|
* Load all providers (3-tier priority)
|
|
@@ -11245,6 +11403,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11245
11403
|
*/
|
|
11246
11404
|
loadAll() {
|
|
11247
11405
|
this.providers.clear();
|
|
11406
|
+
this.providerAvailability.clear();
|
|
11248
11407
|
let upstreamCount = 0;
|
|
11249
11408
|
if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
|
|
11250
11409
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
@@ -11272,7 +11431,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11272
11431
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
11273
11432
|
try {
|
|
11274
11433
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
11275
|
-
(d) => fs6.statSync(
|
|
11434
|
+
(d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
|
|
11276
11435
|
);
|
|
11277
11436
|
} catch {
|
|
11278
11437
|
return false;
|
|
@@ -11315,11 +11474,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11315
11474
|
if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
|
|
11316
11475
|
const verCmdConfig = p.versionCommand;
|
|
11317
11476
|
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
|
|
11477
|
+
const command = this.getSpawnCommand(p.type, p.spawn.command);
|
|
11318
11478
|
result.push({
|
|
11319
11479
|
id: p.type,
|
|
11320
11480
|
displayName: p.displayName || p.name,
|
|
11321
11481
|
icon: p.icon || "\u{1F527}",
|
|
11322
|
-
command
|
|
11482
|
+
command,
|
|
11323
11483
|
category: p.category,
|
|
11324
11484
|
...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
|
|
11325
11485
|
});
|
|
@@ -11448,6 +11608,71 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11448
11608
|
getAvailableIdeTypes() {
|
|
11449
11609
|
return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
|
|
11450
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
|
+
}
|
|
11451
11676
|
/**
|
|
11452
11677
|
* Register IDE providers to core/detector registry
|
|
11453
11678
|
* → Enables detectIDEs() to detect provider.js-based IDEs
|
|
@@ -11522,8 +11747,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11522
11747
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
11523
11748
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
11524
11749
|
if (providerDir) {
|
|
11525
|
-
const fullDir =
|
|
11526
|
-
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;
|
|
11527
11752
|
}
|
|
11528
11753
|
matched = true;
|
|
11529
11754
|
}
|
|
@@ -11538,8 +11763,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11538
11763
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11539
11764
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
11540
11765
|
if (providerDir) {
|
|
11541
|
-
const fullDir =
|
|
11542
|
-
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;
|
|
11543
11768
|
}
|
|
11544
11769
|
}
|
|
11545
11770
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -11556,8 +11781,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11556
11781
|
resolved._resolvedScriptDir = dirOverride;
|
|
11557
11782
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
11558
11783
|
if (providerDir) {
|
|
11559
|
-
const fullDir =
|
|
11560
|
-
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;
|
|
11561
11786
|
}
|
|
11562
11787
|
}
|
|
11563
11788
|
} else if (override.scripts) {
|
|
@@ -11573,8 +11798,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11573
11798
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
11574
11799
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
11575
11800
|
if (providerDir) {
|
|
11576
|
-
const fullDir =
|
|
11577
|
-
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;
|
|
11578
11803
|
}
|
|
11579
11804
|
}
|
|
11580
11805
|
}
|
|
@@ -11599,14 +11824,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11599
11824
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
11600
11825
|
return null;
|
|
11601
11826
|
}
|
|
11602
|
-
const dir =
|
|
11827
|
+
const dir = path12.join(providerDir, scriptDir);
|
|
11603
11828
|
if (!fs6.existsSync(dir)) {
|
|
11604
11829
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
11605
11830
|
return null;
|
|
11606
11831
|
}
|
|
11607
11832
|
const cached = this.scriptsCache.get(dir);
|
|
11608
11833
|
if (cached) return cached;
|
|
11609
|
-
const scriptsJs =
|
|
11834
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
11610
11835
|
if (fs6.existsSync(scriptsJs)) {
|
|
11611
11836
|
try {
|
|
11612
11837
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -11648,7 +11873,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11648
11873
|
return;
|
|
11649
11874
|
}
|
|
11650
11875
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
11651
|
-
this.log(`File changed: ${
|
|
11876
|
+
this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
|
|
11652
11877
|
this.reload();
|
|
11653
11878
|
}
|
|
11654
11879
|
};
|
|
@@ -11703,7 +11928,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11703
11928
|
}
|
|
11704
11929
|
const https = require("https");
|
|
11705
11930
|
const { execSync: execSync7 } = require("child_process");
|
|
11706
|
-
const metaPath =
|
|
11931
|
+
const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
11707
11932
|
let prevEtag = "";
|
|
11708
11933
|
let prevTimestamp = 0;
|
|
11709
11934
|
try {
|
|
@@ -11720,7 +11945,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11720
11945
|
return { updated: false };
|
|
11721
11946
|
}
|
|
11722
11947
|
try {
|
|
11723
|
-
const etag = await new Promise((
|
|
11948
|
+
const etag = await new Promise((resolve12, reject) => {
|
|
11724
11949
|
const options = {
|
|
11725
11950
|
method: "HEAD",
|
|
11726
11951
|
hostname: "github.com",
|
|
@@ -11738,7 +11963,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11738
11963
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
11739
11964
|
timeout: 1e4
|
|
11740
11965
|
}, (res2) => {
|
|
11741
|
-
|
|
11966
|
+
resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
11742
11967
|
});
|
|
11743
11968
|
req2.on("error", reject);
|
|
11744
11969
|
req2.on("timeout", () => {
|
|
@@ -11747,7 +11972,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11747
11972
|
});
|
|
11748
11973
|
req2.end();
|
|
11749
11974
|
} else {
|
|
11750
|
-
|
|
11975
|
+
resolve12(res.headers.etag || res.headers["last-modified"] || "");
|
|
11751
11976
|
}
|
|
11752
11977
|
});
|
|
11753
11978
|
req.on("error", reject);
|
|
@@ -11763,17 +11988,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11763
11988
|
return { updated: false };
|
|
11764
11989
|
}
|
|
11765
11990
|
this.log("Downloading latest providers from GitHub...");
|
|
11766
|
-
const tmpTar =
|
|
11767
|
-
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()}`);
|
|
11768
11993
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
11769
11994
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
11770
11995
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
11771
11996
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
11772
11997
|
const rootDir = extracted.find(
|
|
11773
|
-
(d) => fs6.statSync(
|
|
11998
|
+
(d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
11774
11999
|
);
|
|
11775
12000
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
11776
|
-
const sourceDir =
|
|
12001
|
+
const sourceDir = path12.join(tmpExtract, rootDir);
|
|
11777
12002
|
const backupDir = this.upstreamDir + ".bak";
|
|
11778
12003
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
11779
12004
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -11811,7 +12036,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11811
12036
|
downloadFile(url, destPath) {
|
|
11812
12037
|
const https = require("https");
|
|
11813
12038
|
const http3 = require("http");
|
|
11814
|
-
return new Promise((
|
|
12039
|
+
return new Promise((resolve12, reject) => {
|
|
11815
12040
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
11816
12041
|
if (redirectCount > 5) {
|
|
11817
12042
|
reject(new Error("Too many redirects"));
|
|
@@ -11831,7 +12056,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11831
12056
|
res.pipe(ws);
|
|
11832
12057
|
ws.on("finish", () => {
|
|
11833
12058
|
ws.close();
|
|
11834
|
-
|
|
12059
|
+
resolve12();
|
|
11835
12060
|
});
|
|
11836
12061
|
ws.on("error", reject);
|
|
11837
12062
|
});
|
|
@@ -11848,8 +12073,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11848
12073
|
copyDirRecursive(src, dest) {
|
|
11849
12074
|
fs6.mkdirSync(dest, { recursive: true });
|
|
11850
12075
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
11851
|
-
const srcPath =
|
|
11852
|
-
const destPath =
|
|
12076
|
+
const srcPath = path12.join(src, entry.name);
|
|
12077
|
+
const destPath = path12.join(dest, entry.name);
|
|
11853
12078
|
if (entry.isDirectory()) {
|
|
11854
12079
|
this.copyDirRecursive(srcPath, destPath);
|
|
11855
12080
|
} else {
|
|
@@ -11860,7 +12085,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11860
12085
|
/** .meta.json save */
|
|
11861
12086
|
writeMeta(metaPath, etag, timestamp) {
|
|
11862
12087
|
try {
|
|
11863
|
-
fs6.mkdirSync(
|
|
12088
|
+
fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
|
|
11864
12089
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
11865
12090
|
etag,
|
|
11866
12091
|
timestamp,
|
|
@@ -11877,7 +12102,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11877
12102
|
const scan = (d) => {
|
|
11878
12103
|
try {
|
|
11879
12104
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
11880
|
-
if (entry.isDirectory()) scan(
|
|
12105
|
+
if (entry.isDirectory()) scan(path12.join(d, entry.name));
|
|
11881
12106
|
else if (entry.name === "provider.json") count++;
|
|
11882
12107
|
}
|
|
11883
12108
|
} catch {
|
|
@@ -11891,9 +12116,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11891
12116
|
* Get public settings schema for a provider (for dashboard UI rendering)
|
|
11892
12117
|
*/
|
|
11893
12118
|
getPublicSettings(type) {
|
|
11894
|
-
const
|
|
11895
|
-
|
|
11896
|
-
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 }));
|
|
11897
12121
|
}
|
|
11898
12122
|
/**
|
|
11899
12123
|
* Get public settings schema for all providers
|
|
@@ -11910,8 +12134,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11910
12134
|
* Resolved setting value for a provider (default + user override)
|
|
11911
12135
|
*/
|
|
11912
12136
|
getSettingValue(type, key) {
|
|
11913
|
-
const
|
|
11914
|
-
const schemaDef = provider?.settings?.[key];
|
|
12137
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
11915
12138
|
const defaultVal = schemaDef ? schemaDef.default : void 0;
|
|
11916
12139
|
try {
|
|
11917
12140
|
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
@@ -11926,10 +12149,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11926
12149
|
* All resolved settings for a provider (default + user override)
|
|
11927
12150
|
*/
|
|
11928
12151
|
getSettings(type) {
|
|
11929
|
-
const
|
|
11930
|
-
if (!provider?.settings) return {};
|
|
12152
|
+
const settings = this.getSettingsSchema(type);
|
|
11931
12153
|
const result = {};
|
|
11932
|
-
for (const [key
|
|
12154
|
+
for (const [key] of Object.entries(settings)) {
|
|
11933
12155
|
result[key] = this.getSettingValue(type, key);
|
|
11934
12156
|
}
|
|
11935
12157
|
return result;
|
|
@@ -11938,11 +12160,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11938
12160
|
* Save provider setting value (writes to config.json)
|
|
11939
12161
|
*/
|
|
11940
12162
|
setSetting(type, key, value) {
|
|
11941
|
-
const
|
|
11942
|
-
const schemaDef = provider?.settings?.[key];
|
|
12163
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
11943
12164
|
if (!schemaDef) return false;
|
|
11944
12165
|
if (!schemaDef.public) return false;
|
|
11945
12166
|
if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
|
|
12167
|
+
if (schemaDef.type === "string" && typeof value !== "string") return false;
|
|
11946
12168
|
if (schemaDef.type === "number") {
|
|
11947
12169
|
if (typeof value !== "number") return false;
|
|
11948
12170
|
if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
|
|
@@ -11963,6 +12185,53 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11963
12185
|
return false;
|
|
11964
12186
|
}
|
|
11965
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
|
+
}
|
|
11966
12235
|
// ─── Private ───────────────────────────────────
|
|
11967
12236
|
/**
|
|
11968
12237
|
* Find the on-disk directory for a provider by type.
|
|
@@ -11976,17 +12245,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
11976
12245
|
for (const root of searchRoots) {
|
|
11977
12246
|
if (!fs6.existsSync(root)) continue;
|
|
11978
12247
|
const candidate = this.getProviderDir(root, cat, type);
|
|
11979
|
-
if (fs6.existsSync(
|
|
11980
|
-
const catDir =
|
|
12248
|
+
if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
|
|
12249
|
+
const catDir = path12.join(root, cat);
|
|
11981
12250
|
if (fs6.existsSync(catDir)) {
|
|
11982
12251
|
try {
|
|
11983
12252
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
11984
12253
|
if (!entry.isDirectory()) continue;
|
|
11985
|
-
const jsonPath =
|
|
12254
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
11986
12255
|
if (fs6.existsSync(jsonPath)) {
|
|
11987
12256
|
try {
|
|
11988
12257
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
11989
|
-
if (data.type === type) return
|
|
12258
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
11990
12259
|
} catch {
|
|
11991
12260
|
}
|
|
11992
12261
|
}
|
|
@@ -12003,7 +12272,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12003
12272
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
12004
12273
|
*/
|
|
12005
12274
|
buildScriptWrappersFromDir(dir) {
|
|
12006
|
-
const scriptsJs =
|
|
12275
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
12007
12276
|
if (fs6.existsSync(scriptsJs)) {
|
|
12008
12277
|
try {
|
|
12009
12278
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -12017,7 +12286,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12017
12286
|
for (const file of fs6.readdirSync(dir)) {
|
|
12018
12287
|
if (!file.endsWith(".js")) continue;
|
|
12019
12288
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
12020
|
-
const filePath =
|
|
12289
|
+
const filePath = path12.join(dir, file);
|
|
12021
12290
|
result[scriptName] = (...args) => {
|
|
12022
12291
|
try {
|
|
12023
12292
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -12077,7 +12346,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12077
12346
|
}
|
|
12078
12347
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
12079
12348
|
if (hasJson) {
|
|
12080
|
-
const jsonPath =
|
|
12349
|
+
const jsonPath = path12.join(d, "provider.json");
|
|
12081
12350
|
try {
|
|
12082
12351
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
12083
12352
|
const mod = JSON.parse(raw);
|
|
@@ -12090,7 +12359,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12090
12359
|
delete mod.extensionIdPattern_flags;
|
|
12091
12360
|
}
|
|
12092
12361
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
12093
|
-
const scriptsPath =
|
|
12362
|
+
const scriptsPath = path12.join(d, "scripts.js");
|
|
12094
12363
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
12095
12364
|
try {
|
|
12096
12365
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -12116,7 +12385,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
12116
12385
|
if (!entry.isDirectory()) continue;
|
|
12117
12386
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
12118
12387
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
12119
|
-
scan(
|
|
12388
|
+
scan(path12.join(d, entry.name));
|
|
12120
12389
|
}
|
|
12121
12390
|
}
|
|
12122
12391
|
};
|
|
@@ -12212,17 +12481,17 @@ async function findFreePort(ports) {
|
|
|
12212
12481
|
throw new Error("No free port found");
|
|
12213
12482
|
}
|
|
12214
12483
|
function checkPortFree(port) {
|
|
12215
|
-
return new Promise((
|
|
12484
|
+
return new Promise((resolve12) => {
|
|
12216
12485
|
const server = net.createServer();
|
|
12217
12486
|
server.unref();
|
|
12218
|
-
server.on("error", () =>
|
|
12487
|
+
server.on("error", () => resolve12(false));
|
|
12219
12488
|
server.listen(port, "127.0.0.1", () => {
|
|
12220
|
-
server.close(() =>
|
|
12489
|
+
server.close(() => resolve12(true));
|
|
12221
12490
|
});
|
|
12222
12491
|
});
|
|
12223
12492
|
}
|
|
12224
12493
|
async function isCdpActive(port) {
|
|
12225
|
-
return new Promise((
|
|
12494
|
+
return new Promise((resolve12) => {
|
|
12226
12495
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
12227
12496
|
timeout: 2e3
|
|
12228
12497
|
}, (res) => {
|
|
@@ -12231,16 +12500,16 @@ async function isCdpActive(port) {
|
|
|
12231
12500
|
res.on("end", () => {
|
|
12232
12501
|
try {
|
|
12233
12502
|
const info = JSON.parse(data);
|
|
12234
|
-
|
|
12503
|
+
resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
12235
12504
|
} catch {
|
|
12236
|
-
|
|
12505
|
+
resolve12(false);
|
|
12237
12506
|
}
|
|
12238
12507
|
});
|
|
12239
12508
|
});
|
|
12240
|
-
req.on("error", () =>
|
|
12509
|
+
req.on("error", () => resolve12(false));
|
|
12241
12510
|
req.on("timeout", () => {
|
|
12242
12511
|
req.destroy();
|
|
12243
|
-
|
|
12512
|
+
resolve12(false);
|
|
12244
12513
|
});
|
|
12245
12514
|
});
|
|
12246
12515
|
}
|
|
@@ -12374,8 +12643,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12374
12643
|
const appNameMap = getMacAppIdentifiers();
|
|
12375
12644
|
const appName = appNameMap[ideId];
|
|
12376
12645
|
if (appName) {
|
|
12377
|
-
const storagePath =
|
|
12378
|
-
process.env.APPDATA ||
|
|
12646
|
+
const storagePath = path13.join(
|
|
12647
|
+
process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
|
|
12379
12648
|
appName,
|
|
12380
12649
|
"storage.json"
|
|
12381
12650
|
);
|
|
@@ -12399,7 +12668,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
12399
12668
|
async function launchWithCdp(options = {}) {
|
|
12400
12669
|
const platform9 = os12.platform();
|
|
12401
12670
|
let targetIde;
|
|
12402
|
-
const ides = await detectIDEs();
|
|
12671
|
+
const ides = await detectIDEs(getProviderLoader());
|
|
12403
12672
|
if (options.ideId) {
|
|
12404
12673
|
targetIde = ides.find((i) => i.id === options.ideId && i.installed);
|
|
12405
12674
|
if (!targetIde) {
|
|
@@ -12553,9 +12822,9 @@ init_logger();
|
|
|
12553
12822
|
|
|
12554
12823
|
// src/logging/command-log.ts
|
|
12555
12824
|
var fs7 = __toESM(require("fs"));
|
|
12556
|
-
var
|
|
12825
|
+
var path14 = __toESM(require("path"));
|
|
12557
12826
|
var os13 = __toESM(require("os"));
|
|
12558
|
-
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");
|
|
12559
12828
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
12560
12829
|
var MAX_DAYS = 7;
|
|
12561
12830
|
try {
|
|
@@ -12593,13 +12862,13 @@ function getDateStr2() {
|
|
|
12593
12862
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
12594
12863
|
}
|
|
12595
12864
|
var currentDate2 = getDateStr2();
|
|
12596
|
-
var currentFile =
|
|
12865
|
+
var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12597
12866
|
var writeCount2 = 0;
|
|
12598
12867
|
function checkRotation() {
|
|
12599
12868
|
const today = getDateStr2();
|
|
12600
12869
|
if (today !== currentDate2) {
|
|
12601
12870
|
currentDate2 = today;
|
|
12602
|
-
currentFile =
|
|
12871
|
+
currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
12603
12872
|
cleanOldFiles();
|
|
12604
12873
|
}
|
|
12605
12874
|
}
|
|
@@ -12613,7 +12882,7 @@ function cleanOldFiles() {
|
|
|
12613
12882
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
12614
12883
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
12615
12884
|
try {
|
|
12616
|
-
fs7.unlinkSync(
|
|
12885
|
+
fs7.unlinkSync(path14.join(LOG_DIR2, file));
|
|
12617
12886
|
} catch {
|
|
12618
12887
|
}
|
|
12619
12888
|
}
|
|
@@ -12705,12 +12974,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
|
12705
12974
|
}));
|
|
12706
12975
|
}
|
|
12707
12976
|
function buildAvailableProviders(providerLoader) {
|
|
12708
|
-
|
|
12977
|
+
const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
|
|
12978
|
+
return providers.map((provider) => ({
|
|
12709
12979
|
type: provider.type,
|
|
12710
12980
|
name: provider.displayName || provider.type,
|
|
12711
12981
|
displayName: provider.displayName || provider.type,
|
|
12712
12982
|
icon: provider.icon || "\u{1F4BB}",
|
|
12713
|
-
category: provider.category
|
|
12983
|
+
category: provider.category,
|
|
12984
|
+
...provider.installed !== void 0 ? { installed: provider.installed } : {},
|
|
12985
|
+
...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
|
|
12714
12986
|
}));
|
|
12715
12987
|
}
|
|
12716
12988
|
function parseMessageTime(value) {
|
|
@@ -12724,17 +12996,17 @@ function parseMessageTime(value) {
|
|
|
12724
12996
|
function getSessionMessageUpdatedAt(session) {
|
|
12725
12997
|
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
12726
12998
|
if (!lastMessage) return 0;
|
|
12727
|
-
return parseMessageTime(lastMessage.
|
|
12999
|
+
return parseMessageTime(lastMessage.receivedAt) || 0;
|
|
12728
13000
|
}
|
|
12729
13001
|
function getSessionCompletionMarker(session) {
|
|
12730
13002
|
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
12731
13003
|
if (!lastMessage) return "";
|
|
12732
13004
|
const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
|
|
12733
|
-
if (role === "user" || role === "human") return "";
|
|
13005
|
+
if (role === "user" || role === "human" || role === "system") return "";
|
|
12734
13006
|
if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
|
|
12735
13007
|
if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
|
|
12736
13008
|
if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
|
|
12737
|
-
const timestamp = parseMessageTime(lastMessage.
|
|
13009
|
+
const timestamp = parseMessageTime(lastMessage.receivedAt);
|
|
12738
13010
|
return timestamp > 0 ? `ts:${timestamp}` : "";
|
|
12739
13011
|
}
|
|
12740
13012
|
function getSessionLastUsedAt(session) {
|
|
@@ -12751,7 +13023,7 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
|
|
|
12751
13023
|
if (status === "generating" || status === "starting") {
|
|
12752
13024
|
return { unread: false, inboxBucket: "working" };
|
|
12753
13025
|
}
|
|
12754
|
-
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
13026
|
+
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
|
|
12755
13027
|
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
12756
13028
|
}
|
|
12757
13029
|
function buildRecentLaunches(recentActivity) {
|
|
@@ -12838,13 +13110,13 @@ var import_child_process7 = require("child_process");
|
|
|
12838
13110
|
var import_child_process8 = require("child_process");
|
|
12839
13111
|
var fs8 = __toESM(require("fs"));
|
|
12840
13112
|
var os15 = __toESM(require("os"));
|
|
12841
|
-
var
|
|
13113
|
+
var path15 = __toESM(require("path"));
|
|
12842
13114
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
12843
13115
|
function getUpgradeLogPath() {
|
|
12844
13116
|
const home = os15.homedir();
|
|
12845
|
-
const dir =
|
|
13117
|
+
const dir = path15.join(home, ".adhdev");
|
|
12846
13118
|
fs8.mkdirSync(dir, { recursive: true });
|
|
12847
|
-
return
|
|
13119
|
+
return path15.join(dir, "daemon-upgrade.log");
|
|
12848
13120
|
}
|
|
12849
13121
|
function appendUpgradeLog(message) {
|
|
12850
13122
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -12877,14 +13149,14 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
12877
13149
|
while (Date.now() - start < timeoutMs) {
|
|
12878
13150
|
try {
|
|
12879
13151
|
process.kill(pid, 0);
|
|
12880
|
-
await new Promise((
|
|
13152
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
12881
13153
|
} catch {
|
|
12882
13154
|
return;
|
|
12883
13155
|
}
|
|
12884
13156
|
}
|
|
12885
13157
|
}
|
|
12886
13158
|
function stopSessionHostProcesses(appName) {
|
|
12887
|
-
const pidFile =
|
|
13159
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
12888
13160
|
try {
|
|
12889
13161
|
if (fs8.existsSync(pidFile)) {
|
|
12890
13162
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -12913,7 +13185,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
12913
13185
|
}
|
|
12914
13186
|
}
|
|
12915
13187
|
function removeDaemonPidFile() {
|
|
12916
|
-
const pidFile =
|
|
13188
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
|
|
12917
13189
|
try {
|
|
12918
13190
|
fs8.unlinkSync(pidFile);
|
|
12919
13191
|
} catch {
|
|
@@ -12924,7 +13196,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
12924
13196
|
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
12925
13197
|
if (!npmRoot) return;
|
|
12926
13198
|
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
12927
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
13199
|
+
const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
|
|
12928
13200
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
12929
13201
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
12930
13202
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -12932,25 +13204,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
12932
13204
|
}
|
|
12933
13205
|
if (pkgName.startsWith("@")) {
|
|
12934
13206
|
const [scope, name] = pkgName.split("/");
|
|
12935
|
-
const scopeDir =
|
|
13207
|
+
const scopeDir = path15.join(npmRoot, scope);
|
|
12936
13208
|
if (!fs8.existsSync(scopeDir)) return;
|
|
12937
13209
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
12938
13210
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
12939
|
-
fs8.rmSync(
|
|
12940
|
-
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)}`);
|
|
12941
13213
|
}
|
|
12942
13214
|
} else {
|
|
12943
13215
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
12944
13216
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
12945
|
-
fs8.rmSync(
|
|
12946
|
-
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)}`);
|
|
12947
13219
|
}
|
|
12948
13220
|
}
|
|
12949
13221
|
if (fs8.existsSync(binDir)) {
|
|
12950
13222
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
12951
13223
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
12952
|
-
fs8.rmSync(
|
|
12953
|
-
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)}`);
|
|
12954
13226
|
}
|
|
12955
13227
|
}
|
|
12956
13228
|
}
|
|
@@ -12992,7 +13264,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
12992
13264
|
appendUpgradeLog(installOutput.trim());
|
|
12993
13265
|
}
|
|
12994
13266
|
if (process.platform === "win32") {
|
|
12995
|
-
await new Promise((
|
|
13267
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
12996
13268
|
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
12997
13269
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
12998
13270
|
}
|
|
@@ -13036,6 +13308,25 @@ var CHAT_COMMANDS = [
|
|
|
13036
13308
|
"change_model"
|
|
13037
13309
|
];
|
|
13038
13310
|
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
13311
|
+
function toHostedCliRuntimeDescriptor(record) {
|
|
13312
|
+
if (!record || typeof record !== "object") return null;
|
|
13313
|
+
const runtimeId = typeof record.sessionId === "string" ? record.sessionId : "";
|
|
13314
|
+
const cliType = typeof record.providerType === "string" ? record.providerType : "";
|
|
13315
|
+
const workspace = typeof record.workspace === "string" ? record.workspace : "";
|
|
13316
|
+
if (!runtimeId || !cliType || !workspace) return null;
|
|
13317
|
+
return {
|
|
13318
|
+
runtimeId,
|
|
13319
|
+
runtimeKey: typeof record.runtimeKey === "string" ? record.runtimeKey : void 0,
|
|
13320
|
+
displayName: typeof record.displayName === "string" ? record.displayName : void 0,
|
|
13321
|
+
workspaceLabel: typeof record.workspaceLabel === "string" ? record.workspaceLabel : void 0,
|
|
13322
|
+
lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : void 0,
|
|
13323
|
+
recoveryState: typeof record.meta?.runtimeRecoveryState === "string" ? String(record.meta.runtimeRecoveryState) : null,
|
|
13324
|
+
cliType,
|
|
13325
|
+
workspace,
|
|
13326
|
+
cliArgs: Array.isArray(record.meta?.cliArgs) ? record.meta.cliArgs : [],
|
|
13327
|
+
providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
|
|
13328
|
+
};
|
|
13329
|
+
}
|
|
13039
13330
|
var DaemonCommandRouter = class {
|
|
13040
13331
|
deps;
|
|
13041
13332
|
constructor(deps) {
|
|
@@ -13109,6 +13400,90 @@ var DaemonCommandRouter = class {
|
|
|
13109
13400
|
return { success: false, error: e.message };
|
|
13110
13401
|
}
|
|
13111
13402
|
}
|
|
13403
|
+
case "session_host_get_diagnostics": {
|
|
13404
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13405
|
+
const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
|
|
13406
|
+
includeSessions: args?.includeSessions !== false,
|
|
13407
|
+
limit: Number(args?.limit) || void 0
|
|
13408
|
+
});
|
|
13409
|
+
return { success: true, diagnostics };
|
|
13410
|
+
}
|
|
13411
|
+
case "session_host_list_sessions": {
|
|
13412
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13413
|
+
const sessions = await this.deps.sessionHostControl.listSessions();
|
|
13414
|
+
return { success: true, sessions };
|
|
13415
|
+
}
|
|
13416
|
+
case "session_host_stop_session": {
|
|
13417
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13418
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13419
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13420
|
+
const record = await this.deps.sessionHostControl.stopSession(sessionId);
|
|
13421
|
+
return { success: true, record };
|
|
13422
|
+
}
|
|
13423
|
+
case "session_host_resume_session": {
|
|
13424
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13425
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13426
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13427
|
+
const record = await this.deps.sessionHostControl.resumeSession(sessionId);
|
|
13428
|
+
const hosted = toHostedCliRuntimeDescriptor(record);
|
|
13429
|
+
if (hosted) {
|
|
13430
|
+
await this.deps.cliManager.restoreHostedSessions([hosted]);
|
|
13431
|
+
}
|
|
13432
|
+
return { success: true, record };
|
|
13433
|
+
}
|
|
13434
|
+
case "session_host_restart_session": {
|
|
13435
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13436
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13437
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13438
|
+
const record = await this.deps.sessionHostControl.restartSession(sessionId);
|
|
13439
|
+
const hosted = toHostedCliRuntimeDescriptor(record);
|
|
13440
|
+
if (hosted) {
|
|
13441
|
+
await this.deps.cliManager.restoreHostedSessions([hosted]);
|
|
13442
|
+
}
|
|
13443
|
+
return { success: true, record };
|
|
13444
|
+
}
|
|
13445
|
+
case "session_host_send_signal": {
|
|
13446
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13447
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13448
|
+
const signal = typeof args?.signal === "string" ? args.signal : "";
|
|
13449
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13450
|
+
if (!signal) return { success: false, error: "signal required" };
|
|
13451
|
+
const record = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
|
|
13452
|
+
return { success: true, record };
|
|
13453
|
+
}
|
|
13454
|
+
case "session_host_force_detach_client": {
|
|
13455
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13456
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13457
|
+
const clientId = typeof args?.clientId === "string" ? args.clientId : "";
|
|
13458
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13459
|
+
if (!clientId) return { success: false, error: "clientId required" };
|
|
13460
|
+
const record = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
|
|
13461
|
+
return { success: true, record };
|
|
13462
|
+
}
|
|
13463
|
+
case "session_host_acquire_write": {
|
|
13464
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13465
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13466
|
+
const clientId = typeof args?.clientId === "string" ? args.clientId : "";
|
|
13467
|
+
const ownerType = args?.ownerType === "agent" ? "agent" : "user";
|
|
13468
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13469
|
+
if (!clientId) return { success: false, error: "clientId required" };
|
|
13470
|
+
const record = await this.deps.sessionHostControl.acquireWrite({
|
|
13471
|
+
sessionId,
|
|
13472
|
+
clientId,
|
|
13473
|
+
ownerType,
|
|
13474
|
+
force: args?.force !== false
|
|
13475
|
+
});
|
|
13476
|
+
return { success: true, record };
|
|
13477
|
+
}
|
|
13478
|
+
case "session_host_release_write": {
|
|
13479
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
13480
|
+
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
13481
|
+
const clientId = typeof args?.clientId === "string" ? args.clientId : "";
|
|
13482
|
+
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
13483
|
+
if (!clientId) return { success: false, error: "clientId required" };
|
|
13484
|
+
const record = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
|
|
13485
|
+
return { success: true, record };
|
|
13486
|
+
}
|
|
13112
13487
|
case "list_saved_sessions": {
|
|
13113
13488
|
const providerType = typeof args?.providerType === "string" ? args.providerType.trim() : typeof args?.agentType === "string" ? args.agentType.trim() : "";
|
|
13114
13489
|
const kind = args?.kind === "acp" ? "acp" : "cli";
|
|
@@ -13167,6 +13542,12 @@ var DaemonCommandRouter = class {
|
|
|
13167
13542
|
if (!ideType) throw new Error("ideType required");
|
|
13168
13543
|
const killProcess = args?.killProcess !== false;
|
|
13169
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
|
+
}
|
|
13170
13551
|
return { success: true, ideType, stopped: true, processKilled: killProcess };
|
|
13171
13552
|
}
|
|
13172
13553
|
// ─── IDE restart ───
|
|
@@ -13209,6 +13590,12 @@ var DaemonCommandRouter = class {
|
|
|
13209
13590
|
}
|
|
13210
13591
|
}
|
|
13211
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
|
+
}
|
|
13212
13599
|
if (result.success && resolvedWorkspace) {
|
|
13213
13600
|
try {
|
|
13214
13601
|
const next = appendRecentActivity(loadState(), {
|
|
@@ -13236,8 +13623,9 @@ var DaemonCommandRouter = class {
|
|
|
13236
13623
|
}
|
|
13237
13624
|
// ─── Detect IDEs ───
|
|
13238
13625
|
case "detect_ides": {
|
|
13239
|
-
const results = await detectIDEs();
|
|
13626
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
13240
13627
|
this.deps.detectedIdes.value = results;
|
|
13628
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
13241
13629
|
return { success: true, detectedInfo: results };
|
|
13242
13630
|
}
|
|
13243
13631
|
// ─── Set User Name ───
|
|
@@ -13637,6 +14025,14 @@ var ProviderStreamAdapter = class {
|
|
|
13637
14025
|
hasScript(name) {
|
|
13638
14026
|
return typeof this.provider.scripts?.[name] === "function";
|
|
13639
14027
|
}
|
|
14028
|
+
parseMaybeJson(raw) {
|
|
14029
|
+
if (typeof raw !== "string") return raw;
|
|
14030
|
+
try {
|
|
14031
|
+
return JSON.parse(raw);
|
|
14032
|
+
} catch {
|
|
14033
|
+
return raw;
|
|
14034
|
+
}
|
|
14035
|
+
}
|
|
13640
14036
|
summarizeRaw(raw) {
|
|
13641
14037
|
try {
|
|
13642
14038
|
if (typeof raw === "string") return raw.replace(/\s+/g, " ").trim().slice(0, 240);
|
|
@@ -13697,12 +14093,30 @@ var ProviderStreamAdapter = class {
|
|
|
13697
14093
|
}
|
|
13698
14094
|
}
|
|
13699
14095
|
async sendMessage(evaluate, text) {
|
|
13700
|
-
const
|
|
14096
|
+
const params = { message: text };
|
|
14097
|
+
const script = this.callScript("sendMessage", params) || this.callScript("sendMessage", text);
|
|
13701
14098
|
if (!script) throw new Error(`[${this.agentName}] sendMessage script not available`);
|
|
13702
14099
|
const result = await evaluate(script);
|
|
13703
14100
|
if (result && typeof result === "string" && result.startsWith("error:")) {
|
|
13704
14101
|
throw new Error(`[${this.agentName}] sendMessage failed: ${result}`);
|
|
13705
14102
|
}
|
|
14103
|
+
const parsed = this.parseMaybeJson(result);
|
|
14104
|
+
if (parsed === true) return;
|
|
14105
|
+
if (typeof parsed === "string") {
|
|
14106
|
+
const normalized = parsed.trim().toLowerCase();
|
|
14107
|
+
if (normalized === "ok" || normalized === "sent" || normalized === "success" || normalized === "true") {
|
|
14108
|
+
return;
|
|
14109
|
+
}
|
|
14110
|
+
}
|
|
14111
|
+
if (parsed && typeof parsed === "object") {
|
|
14112
|
+
if (parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true) {
|
|
14113
|
+
return;
|
|
14114
|
+
}
|
|
14115
|
+
if (typeof parsed.error === "string" && parsed.error.trim()) {
|
|
14116
|
+
throw new Error(`[${this.agentName}] sendMessage failed: ${parsed.error}`);
|
|
14117
|
+
}
|
|
14118
|
+
}
|
|
14119
|
+
throw new Error(`[${this.agentName}] sendMessage was not confirmed`);
|
|
13706
14120
|
}
|
|
13707
14121
|
async resolveAction(evaluate, action, button) {
|
|
13708
14122
|
const script = this.callScript("resolveAction", { action, button });
|
|
@@ -13725,7 +14139,10 @@ var ProviderStreamAdapter = class {
|
|
|
13725
14139
|
const raw = await evaluate(script, 1e4);
|
|
13726
14140
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
13727
14141
|
if (data?.error) return [];
|
|
13728
|
-
|
|
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 [];
|
|
13729
14146
|
} catch {
|
|
13730
14147
|
return [];
|
|
13731
14148
|
}
|
|
@@ -13733,7 +14150,17 @@ var ProviderStreamAdapter = class {
|
|
|
13733
14150
|
async switchSession(evaluate, sessionId) {
|
|
13734
14151
|
const script = this.callScript("switchSession", sessionId);
|
|
13735
14152
|
if (!script) return false;
|
|
13736
|
-
|
|
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;
|
|
13737
14164
|
}
|
|
13738
14165
|
async focusEditor(evaluate) {
|
|
13739
14166
|
const script = this.callScript("focusEditor");
|
|
@@ -14423,11 +14850,11 @@ var ProviderInstanceManager = class {
|
|
|
14423
14850
|
|
|
14424
14851
|
// src/providers/version-archive.ts
|
|
14425
14852
|
var fs10 = __toESM(require("fs"));
|
|
14426
|
-
var
|
|
14853
|
+
var path16 = __toESM(require("path"));
|
|
14427
14854
|
var os16 = __toESM(require("os"));
|
|
14428
14855
|
var import_child_process9 = require("child_process");
|
|
14429
14856
|
var import_os3 = require("os");
|
|
14430
|
-
var ARCHIVE_PATH =
|
|
14857
|
+
var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
14431
14858
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
14432
14859
|
var VersionArchive = class {
|
|
14433
14860
|
history = {};
|
|
@@ -14474,7 +14901,7 @@ var VersionArchive = class {
|
|
|
14474
14901
|
}
|
|
14475
14902
|
save() {
|
|
14476
14903
|
try {
|
|
14477
|
-
fs10.mkdirSync(
|
|
14904
|
+
fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
|
|
14478
14905
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
14479
14906
|
} catch {
|
|
14480
14907
|
}
|
|
@@ -14515,7 +14942,7 @@ function checkPathExists2(paths) {
|
|
|
14515
14942
|
for (const p of paths) {
|
|
14516
14943
|
if (p.includes("*")) {
|
|
14517
14944
|
const home = os16.homedir();
|
|
14518
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
14945
|
+
const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
|
|
14519
14946
|
if (fs10.existsSync(resolved)) return resolved;
|
|
14520
14947
|
} else {
|
|
14521
14948
|
if (fs10.existsSync(p)) return p;
|
|
@@ -14525,7 +14952,7 @@ function checkPathExists2(paths) {
|
|
|
14525
14952
|
}
|
|
14526
14953
|
function getMacAppVersion(appPath) {
|
|
14527
14954
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
14528
|
-
const plistPath =
|
|
14955
|
+
const plistPath = path16.join(appPath, "Contents", "Info.plist");
|
|
14529
14956
|
if (!fs10.existsSync(plistPath)) return null;
|
|
14530
14957
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
14531
14958
|
return raw || null;
|
|
@@ -14552,7 +14979,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14552
14979
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
14553
14980
|
let resolvedBin = cliBin;
|
|
14554
14981
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
14555
|
-
const bundled =
|
|
14982
|
+
const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
14556
14983
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
14557
14984
|
}
|
|
14558
14985
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -14593,7 +15020,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
14593
15020
|
// src/daemon/dev-server.ts
|
|
14594
15021
|
var http2 = __toESM(require("http"));
|
|
14595
15022
|
var fs14 = __toESM(require("fs"));
|
|
14596
|
-
var
|
|
15023
|
+
var path20 = __toESM(require("path"));
|
|
14597
15024
|
|
|
14598
15025
|
// src/daemon/scaffold-template.ts
|
|
14599
15026
|
function generateFiles(type, name, category, opts = {}) {
|
|
@@ -14929,7 +15356,7 @@ init_logger();
|
|
|
14929
15356
|
|
|
14930
15357
|
// src/daemon/dev-cdp-handlers.ts
|
|
14931
15358
|
var fs11 = __toESM(require("fs"));
|
|
14932
|
-
var
|
|
15359
|
+
var path17 = __toESM(require("path"));
|
|
14933
15360
|
init_logger();
|
|
14934
15361
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
14935
15362
|
const body = await ctx.readBody(req);
|
|
@@ -15108,17 +15535,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
15108
15535
|
return;
|
|
15109
15536
|
}
|
|
15110
15537
|
let scriptsPath = "";
|
|
15111
|
-
const directScripts =
|
|
15538
|
+
const directScripts = path17.join(dir, "scripts.js");
|
|
15112
15539
|
if (fs11.existsSync(directScripts)) {
|
|
15113
15540
|
scriptsPath = directScripts;
|
|
15114
15541
|
} else {
|
|
15115
|
-
const scriptsDir =
|
|
15542
|
+
const scriptsDir = path17.join(dir, "scripts");
|
|
15116
15543
|
if (fs11.existsSync(scriptsDir)) {
|
|
15117
15544
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
15118
|
-
return fs11.statSync(
|
|
15545
|
+
return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
15119
15546
|
}).sort().reverse();
|
|
15120
15547
|
for (const ver of versions) {
|
|
15121
|
-
const p =
|
|
15548
|
+
const p = path17.join(scriptsDir, ver, "scripts.js");
|
|
15122
15549
|
if (fs11.existsSync(p)) {
|
|
15123
15550
|
scriptsPath = p;
|
|
15124
15551
|
break;
|
|
@@ -15937,7 +16364,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
15937
16364
|
|
|
15938
16365
|
// src/daemon/dev-cli-debug.ts
|
|
15939
16366
|
var fs12 = __toESM(require("fs"));
|
|
15940
|
-
var
|
|
16367
|
+
var path18 = __toESM(require("path"));
|
|
15941
16368
|
function slugifyFixtureName(value) {
|
|
15942
16369
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
15943
16370
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -15947,11 +16374,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
15947
16374
|
if (!providerDir) {
|
|
15948
16375
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
15949
16376
|
}
|
|
15950
|
-
return
|
|
16377
|
+
return path18.join(providerDir, "fixtures");
|
|
15951
16378
|
}
|
|
15952
16379
|
function readCliFixture(ctx, type, name) {
|
|
15953
16380
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
15954
|
-
const filePath =
|
|
16381
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
15955
16382
|
if (!fs12.existsSync(filePath)) {
|
|
15956
16383
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
15957
16384
|
}
|
|
@@ -16111,7 +16538,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
16111
16538
|
return { target, instance, adapter };
|
|
16112
16539
|
}
|
|
16113
16540
|
function sleep(ms) {
|
|
16114
|
-
return new Promise((
|
|
16541
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
16115
16542
|
}
|
|
16116
16543
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
16117
16544
|
const startedAt = Date.now();
|
|
@@ -16710,7 +17137,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
16710
17137
|
},
|
|
16711
17138
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
16712
17139
|
};
|
|
16713
|
-
const filePath =
|
|
17140
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
16714
17141
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
16715
17142
|
ctx.json(res, 200, {
|
|
16716
17143
|
saved: true,
|
|
@@ -16734,7 +17161,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
16734
17161
|
return;
|
|
16735
17162
|
}
|
|
16736
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) => {
|
|
16737
|
-
const fullPath =
|
|
17164
|
+
const fullPath = path18.join(fixtureDir, file);
|
|
16738
17165
|
try {
|
|
16739
17166
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
16740
17167
|
return {
|
|
@@ -16870,7 +17297,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
16870
17297
|
|
|
16871
17298
|
// src/daemon/dev-auto-implement.ts
|
|
16872
17299
|
var fs13 = __toESM(require("fs"));
|
|
16873
|
-
var
|
|
17300
|
+
var path19 = __toESM(require("path"));
|
|
16874
17301
|
var os17 = __toESM(require("os"));
|
|
16875
17302
|
function getAutoImplPid(ctx) {
|
|
16876
17303
|
const proc = ctx.autoImplProcess;
|
|
@@ -16910,22 +17337,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
16910
17337
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
16911
17338
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
16912
17339
|
try {
|
|
16913
|
-
return fs13.statSync(
|
|
17340
|
+
return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
|
|
16914
17341
|
} catch {
|
|
16915
17342
|
return false;
|
|
16916
17343
|
}
|
|
16917
17344
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
16918
17345
|
if (versions.length === 0) return null;
|
|
16919
|
-
return
|
|
17346
|
+
return path19.join(scriptsDir, versions[0]);
|
|
16920
17347
|
}
|
|
16921
17348
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
16922
|
-
const canonicalUserDir =
|
|
16923
|
-
const desiredDir = requestedDir ?
|
|
16924
|
-
const upstreamRoot =
|
|
16925
|
-
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}`)) {
|
|
16926
17353
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
16927
17354
|
}
|
|
16928
|
-
if (
|
|
17355
|
+
if (path19.basename(desiredDir) !== type) {
|
|
16929
17356
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
16930
17357
|
}
|
|
16931
17358
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -16933,11 +17360,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
16933
17360
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
16934
17361
|
}
|
|
16935
17362
|
if (!fs13.existsSync(desiredDir)) {
|
|
16936
|
-
fs13.mkdirSync(
|
|
17363
|
+
fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
|
|
16937
17364
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
16938
17365
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
16939
17366
|
}
|
|
16940
|
-
const providerJson =
|
|
17367
|
+
const providerJson = path19.join(desiredDir, "provider.json");
|
|
16941
17368
|
if (!fs13.existsSync(providerJson)) {
|
|
16942
17369
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
16943
17370
|
}
|
|
@@ -16960,13 +17387,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
16960
17387
|
const refDir = ctx.findProviderDir(referenceType);
|
|
16961
17388
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
16962
17389
|
const referenceScripts = {};
|
|
16963
|
-
const scriptsDir =
|
|
17390
|
+
const scriptsDir = path19.join(refDir, "scripts");
|
|
16964
17391
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
16965
17392
|
if (!latestDir) return referenceScripts;
|
|
16966
17393
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
16967
17394
|
if (!file.endsWith(".js")) continue;
|
|
16968
17395
|
try {
|
|
16969
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
17396
|
+
referenceScripts[file] = fs13.readFileSync(path19.join(latestDir, file), "utf-8");
|
|
16970
17397
|
} catch {
|
|
16971
17398
|
}
|
|
16972
17399
|
}
|
|
@@ -17074,9 +17501,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
17074
17501
|
});
|
|
17075
17502
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
17076
17503
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
17077
|
-
const tmpDir =
|
|
17504
|
+
const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
17078
17505
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
17079
|
-
const promptFile =
|
|
17506
|
+
const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
17080
17507
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
17081
17508
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
17082
17509
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -17503,7 +17930,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17503
17930
|
setMode: "set_mode.js"
|
|
17504
17931
|
};
|
|
17505
17932
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
17506
|
-
const scriptsDir =
|
|
17933
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
17507
17934
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
17508
17935
|
if (latestScriptsDir) {
|
|
17509
17936
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -17514,7 +17941,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17514
17941
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
17515
17942
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
17516
17943
|
try {
|
|
17517
|
-
const content = fs13.readFileSync(
|
|
17944
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17518
17945
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
17519
17946
|
lines.push("```javascript");
|
|
17520
17947
|
lines.push(content);
|
|
@@ -17531,7 +17958,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17531
17958
|
lines.push("");
|
|
17532
17959
|
for (const file of refFiles) {
|
|
17533
17960
|
try {
|
|
17534
|
-
const content = fs13.readFileSync(
|
|
17961
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17535
17962
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
17536
17963
|
lines.push("```javascript");
|
|
17537
17964
|
lines.push(content);
|
|
@@ -17572,10 +17999,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
17572
17999
|
lines.push("");
|
|
17573
18000
|
}
|
|
17574
18001
|
}
|
|
17575
|
-
const docsDir =
|
|
18002
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
17576
18003
|
const loadGuide = (name) => {
|
|
17577
18004
|
try {
|
|
17578
|
-
const p =
|
|
18005
|
+
const p = path19.join(docsDir, name);
|
|
17579
18006
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
17580
18007
|
} catch {
|
|
17581
18008
|
}
|
|
@@ -17810,7 +18237,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17810
18237
|
parseApproval: "parse_approval.js"
|
|
17811
18238
|
};
|
|
17812
18239
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
17813
|
-
const scriptsDir =
|
|
18240
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
17814
18241
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
17815
18242
|
if (latestScriptsDir) {
|
|
17816
18243
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -17822,7 +18249,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17822
18249
|
if (!file.endsWith(".js")) continue;
|
|
17823
18250
|
if (!targetFileNames.has(file)) continue;
|
|
17824
18251
|
try {
|
|
17825
|
-
const content = fs13.readFileSync(
|
|
18252
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17826
18253
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
17827
18254
|
lines.push("```javascript");
|
|
17828
18255
|
lines.push(content);
|
|
@@ -17838,7 +18265,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17838
18265
|
lines.push("");
|
|
17839
18266
|
for (const file of refFiles) {
|
|
17840
18267
|
try {
|
|
17841
|
-
const content = fs13.readFileSync(
|
|
18268
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
|
|
17842
18269
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
17843
18270
|
lines.push("```javascript");
|
|
17844
18271
|
lines.push(content);
|
|
@@ -17871,10 +18298,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
17871
18298
|
lines.push("");
|
|
17872
18299
|
}
|
|
17873
18300
|
}
|
|
17874
|
-
const docsDir =
|
|
18301
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
17875
18302
|
const loadGuide = (name) => {
|
|
17876
18303
|
try {
|
|
17877
|
-
const p =
|
|
18304
|
+
const p = path19.join(docsDir, name);
|
|
17878
18305
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
17879
18306
|
} catch {
|
|
17880
18307
|
}
|
|
@@ -18285,8 +18712,8 @@ var DevServer = class _DevServer {
|
|
|
18285
18712
|
}
|
|
18286
18713
|
getEndpointList() {
|
|
18287
18714
|
return this.routes.map((r) => {
|
|
18288
|
-
const
|
|
18289
|
-
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}`;
|
|
18290
18717
|
});
|
|
18291
18718
|
}
|
|
18292
18719
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -18317,15 +18744,15 @@ var DevServer = class _DevServer {
|
|
|
18317
18744
|
this.json(res, 500, { error: e.message });
|
|
18318
18745
|
}
|
|
18319
18746
|
});
|
|
18320
|
-
return new Promise((
|
|
18747
|
+
return new Promise((resolve12, reject) => {
|
|
18321
18748
|
this.server.listen(port, "127.0.0.1", () => {
|
|
18322
18749
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
18323
|
-
|
|
18750
|
+
resolve12();
|
|
18324
18751
|
});
|
|
18325
18752
|
this.server.on("error", (e) => {
|
|
18326
18753
|
if (e.code === "EADDRINUSE") {
|
|
18327
18754
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
18328
|
-
|
|
18755
|
+
resolve12();
|
|
18329
18756
|
} else {
|
|
18330
18757
|
reject(e);
|
|
18331
18758
|
}
|
|
@@ -18408,20 +18835,20 @@ var DevServer = class _DevServer {
|
|
|
18408
18835
|
child.stderr?.on("data", (d) => {
|
|
18409
18836
|
stderr += d.toString().slice(0, 2e3);
|
|
18410
18837
|
});
|
|
18411
|
-
await new Promise((
|
|
18838
|
+
await new Promise((resolve12) => {
|
|
18412
18839
|
const timer = setTimeout(() => {
|
|
18413
18840
|
child.kill();
|
|
18414
|
-
|
|
18841
|
+
resolve12();
|
|
18415
18842
|
}, 3e3);
|
|
18416
18843
|
child.on("exit", () => {
|
|
18417
18844
|
clearTimeout(timer);
|
|
18418
|
-
|
|
18845
|
+
resolve12();
|
|
18419
18846
|
});
|
|
18420
18847
|
child.stdout?.once("data", () => {
|
|
18421
18848
|
setTimeout(() => {
|
|
18422
18849
|
child.kill();
|
|
18423
18850
|
clearTimeout(timer);
|
|
18424
|
-
|
|
18851
|
+
resolve12();
|
|
18425
18852
|
}, 500);
|
|
18426
18853
|
});
|
|
18427
18854
|
});
|
|
@@ -18568,12 +18995,12 @@ var DevServer = class _DevServer {
|
|
|
18568
18995
|
// ─── DevConsole SPA ───
|
|
18569
18996
|
getConsoleDistDir() {
|
|
18570
18997
|
const candidates = [
|
|
18571
|
-
|
|
18572
|
-
|
|
18573
|
-
|
|
18998
|
+
path20.resolve(__dirname, "../../web-devconsole/dist"),
|
|
18999
|
+
path20.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
19000
|
+
path20.join(process.cwd(), "packages/web-devconsole/dist")
|
|
18574
19001
|
];
|
|
18575
19002
|
for (const dir of candidates) {
|
|
18576
|
-
if (fs14.existsSync(
|
|
19003
|
+
if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
|
|
18577
19004
|
}
|
|
18578
19005
|
return null;
|
|
18579
19006
|
}
|
|
@@ -18583,7 +19010,7 @@ var DevServer = class _DevServer {
|
|
|
18583
19010
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
18584
19011
|
return;
|
|
18585
19012
|
}
|
|
18586
|
-
const htmlPath =
|
|
19013
|
+
const htmlPath = path20.join(distDir, "index.html");
|
|
18587
19014
|
try {
|
|
18588
19015
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
18589
19016
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -18608,15 +19035,15 @@ var DevServer = class _DevServer {
|
|
|
18608
19035
|
this.json(res, 404, { error: "Not found" });
|
|
18609
19036
|
return;
|
|
18610
19037
|
}
|
|
18611
|
-
const safePath =
|
|
18612
|
-
const filePath =
|
|
19038
|
+
const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
|
|
19039
|
+
const filePath = path20.join(distDir, safePath);
|
|
18613
19040
|
if (!filePath.startsWith(distDir)) {
|
|
18614
19041
|
this.json(res, 403, { error: "Forbidden" });
|
|
18615
19042
|
return;
|
|
18616
19043
|
}
|
|
18617
19044
|
try {
|
|
18618
19045
|
const content = fs14.readFileSync(filePath);
|
|
18619
|
-
const ext =
|
|
19046
|
+
const ext = path20.extname(filePath);
|
|
18620
19047
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
18621
19048
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
18622
19049
|
res.end(content);
|
|
@@ -18729,9 +19156,9 @@ var DevServer = class _DevServer {
|
|
|
18729
19156
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18730
19157
|
if (entry.isDirectory()) {
|
|
18731
19158
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
18732
|
-
scan(
|
|
19159
|
+
scan(path20.join(d, entry.name), rel);
|
|
18733
19160
|
} else {
|
|
18734
|
-
const stat = fs14.statSync(
|
|
19161
|
+
const stat = fs14.statSync(path20.join(d, entry.name));
|
|
18735
19162
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
18736
19163
|
}
|
|
18737
19164
|
}
|
|
@@ -18754,7 +19181,7 @@ var DevServer = class _DevServer {
|
|
|
18754
19181
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18755
19182
|
return;
|
|
18756
19183
|
}
|
|
18757
|
-
const fullPath =
|
|
19184
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18758
19185
|
if (!fullPath.startsWith(dir)) {
|
|
18759
19186
|
this.json(res, 403, { error: "Forbidden" });
|
|
18760
19187
|
return;
|
|
@@ -18779,14 +19206,14 @@ var DevServer = class _DevServer {
|
|
|
18779
19206
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
18780
19207
|
return;
|
|
18781
19208
|
}
|
|
18782
|
-
const fullPath =
|
|
19209
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
18783
19210
|
if (!fullPath.startsWith(dir)) {
|
|
18784
19211
|
this.json(res, 403, { error: "Forbidden" });
|
|
18785
19212
|
return;
|
|
18786
19213
|
}
|
|
18787
19214
|
try {
|
|
18788
19215
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
18789
|
-
fs14.mkdirSync(
|
|
19216
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
18790
19217
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
18791
19218
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
18792
19219
|
this.providerLoader.reload();
|
|
@@ -18803,7 +19230,7 @@ var DevServer = class _DevServer {
|
|
|
18803
19230
|
return;
|
|
18804
19231
|
}
|
|
18805
19232
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
18806
|
-
const p =
|
|
19233
|
+
const p = path20.join(dir, name);
|
|
18807
19234
|
if (fs14.existsSync(p)) {
|
|
18808
19235
|
const source = fs14.readFileSync(p, "utf-8");
|
|
18809
19236
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -18824,8 +19251,8 @@ var DevServer = class _DevServer {
|
|
|
18824
19251
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
18825
19252
|
return;
|
|
18826
19253
|
}
|
|
18827
|
-
const target = fs14.existsSync(
|
|
18828
|
-
const targetPath =
|
|
19254
|
+
const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
19255
|
+
const targetPath = path20.join(dir, target);
|
|
18829
19256
|
try {
|
|
18830
19257
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
18831
19258
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -18930,14 +19357,14 @@ var DevServer = class _DevServer {
|
|
|
18930
19357
|
child.stderr?.on("data", (d) => {
|
|
18931
19358
|
stderr += d.toString();
|
|
18932
19359
|
});
|
|
18933
|
-
await new Promise((
|
|
19360
|
+
await new Promise((resolve12) => {
|
|
18934
19361
|
const timer = setTimeout(() => {
|
|
18935
19362
|
child.kill();
|
|
18936
|
-
|
|
19363
|
+
resolve12();
|
|
18937
19364
|
}, timeout);
|
|
18938
19365
|
child.on("exit", () => {
|
|
18939
19366
|
clearTimeout(timer);
|
|
18940
|
-
|
|
19367
|
+
resolve12();
|
|
18941
19368
|
});
|
|
18942
19369
|
});
|
|
18943
19370
|
const elapsed = Date.now() - start;
|
|
@@ -18985,7 +19412,7 @@ var DevServer = class _DevServer {
|
|
|
18985
19412
|
}
|
|
18986
19413
|
let targetDir;
|
|
18987
19414
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
18988
|
-
const jsonPath =
|
|
19415
|
+
const jsonPath = path20.join(targetDir, "provider.json");
|
|
18989
19416
|
if (fs14.existsSync(jsonPath)) {
|
|
18990
19417
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
18991
19418
|
return;
|
|
@@ -18997,8 +19424,8 @@ var DevServer = class _DevServer {
|
|
|
18997
19424
|
const createdFiles = ["provider.json"];
|
|
18998
19425
|
if (result.files) {
|
|
18999
19426
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
19000
|
-
const fullPath =
|
|
19001
|
-
fs14.mkdirSync(
|
|
19427
|
+
const fullPath = path20.join(targetDir, relPath);
|
|
19428
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
19002
19429
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
19003
19430
|
createdFiles.push(relPath);
|
|
19004
19431
|
}
|
|
@@ -19051,22 +19478,22 @@ var DevServer = class _DevServer {
|
|
|
19051
19478
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
19052
19479
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
19053
19480
|
try {
|
|
19054
|
-
return fs14.statSync(
|
|
19481
|
+
return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
19055
19482
|
} catch {
|
|
19056
19483
|
return false;
|
|
19057
19484
|
}
|
|
19058
19485
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
19059
19486
|
if (versions.length === 0) return null;
|
|
19060
|
-
return
|
|
19487
|
+
return path20.join(scriptsDir, versions[0]);
|
|
19061
19488
|
}
|
|
19062
19489
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
19063
|
-
const canonicalUserDir =
|
|
19064
|
-
const desiredDir = requestedDir ?
|
|
19065
|
-
const upstreamRoot =
|
|
19066
|
-
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}`)) {
|
|
19067
19494
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
19068
19495
|
}
|
|
19069
|
-
if (
|
|
19496
|
+
if (path20.basename(desiredDir) !== type) {
|
|
19070
19497
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
19071
19498
|
}
|
|
19072
19499
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -19074,11 +19501,11 @@ var DevServer = class _DevServer {
|
|
|
19074
19501
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
19075
19502
|
}
|
|
19076
19503
|
if (!fs14.existsSync(desiredDir)) {
|
|
19077
|
-
fs14.mkdirSync(
|
|
19504
|
+
fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
19078
19505
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
19079
19506
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
19080
19507
|
}
|
|
19081
|
-
const providerJson =
|
|
19508
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
19082
19509
|
if (!fs14.existsSync(providerJson)) {
|
|
19083
19510
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
19084
19511
|
}
|
|
@@ -19126,7 +19553,7 @@ var DevServer = class _DevServer {
|
|
|
19126
19553
|
setMode: "set_mode.js"
|
|
19127
19554
|
};
|
|
19128
19555
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19129
|
-
const scriptsDir =
|
|
19556
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19130
19557
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19131
19558
|
if (latestScriptsDir) {
|
|
19132
19559
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19137,7 +19564,7 @@ var DevServer = class _DevServer {
|
|
|
19137
19564
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
19138
19565
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
19139
19566
|
try {
|
|
19140
|
-
const content = fs14.readFileSync(
|
|
19567
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19141
19568
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19142
19569
|
lines.push("```javascript");
|
|
19143
19570
|
lines.push(content);
|
|
@@ -19154,7 +19581,7 @@ var DevServer = class _DevServer {
|
|
|
19154
19581
|
lines.push("");
|
|
19155
19582
|
for (const file of refFiles) {
|
|
19156
19583
|
try {
|
|
19157
|
-
const content = fs14.readFileSync(
|
|
19584
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19158
19585
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19159
19586
|
lines.push("```javascript");
|
|
19160
19587
|
lines.push(content);
|
|
@@ -19195,10 +19622,10 @@ var DevServer = class _DevServer {
|
|
|
19195
19622
|
lines.push("");
|
|
19196
19623
|
}
|
|
19197
19624
|
}
|
|
19198
|
-
const docsDir =
|
|
19625
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19199
19626
|
const loadGuide = (name) => {
|
|
19200
19627
|
try {
|
|
19201
|
-
const p =
|
|
19628
|
+
const p = path20.join(docsDir, name);
|
|
19202
19629
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19203
19630
|
} catch {
|
|
19204
19631
|
}
|
|
@@ -19372,7 +19799,7 @@ var DevServer = class _DevServer {
|
|
|
19372
19799
|
parseApproval: "parse_approval.js"
|
|
19373
19800
|
};
|
|
19374
19801
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
19375
|
-
const scriptsDir =
|
|
19802
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
19376
19803
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
19377
19804
|
if (latestScriptsDir) {
|
|
19378
19805
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -19384,7 +19811,7 @@ var DevServer = class _DevServer {
|
|
|
19384
19811
|
if (!file.endsWith(".js")) continue;
|
|
19385
19812
|
if (!targetFileNames.has(file)) continue;
|
|
19386
19813
|
try {
|
|
19387
|
-
const content = fs14.readFileSync(
|
|
19814
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19388
19815
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
19389
19816
|
lines.push("```javascript");
|
|
19390
19817
|
lines.push(content);
|
|
@@ -19400,7 +19827,7 @@ var DevServer = class _DevServer {
|
|
|
19400
19827
|
lines.push("");
|
|
19401
19828
|
for (const file of refFiles) {
|
|
19402
19829
|
try {
|
|
19403
|
-
const content = fs14.readFileSync(
|
|
19830
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
19404
19831
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
19405
19832
|
lines.push("```javascript");
|
|
19406
19833
|
lines.push(content);
|
|
@@ -19433,10 +19860,10 @@ var DevServer = class _DevServer {
|
|
|
19433
19860
|
lines.push("");
|
|
19434
19861
|
}
|
|
19435
19862
|
}
|
|
19436
|
-
const docsDir =
|
|
19863
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
19437
19864
|
const loadGuide = (name) => {
|
|
19438
19865
|
try {
|
|
19439
|
-
const p =
|
|
19866
|
+
const p = path20.join(docsDir, name);
|
|
19440
19867
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
19441
19868
|
} catch {
|
|
19442
19869
|
}
|
|
@@ -19612,14 +20039,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
19612
20039
|
res.end(JSON.stringify(data, null, 2));
|
|
19613
20040
|
}
|
|
19614
20041
|
async readBody(req) {
|
|
19615
|
-
return new Promise((
|
|
20042
|
+
return new Promise((resolve12) => {
|
|
19616
20043
|
let body = "";
|
|
19617
20044
|
req.on("data", (chunk) => body += chunk);
|
|
19618
20045
|
req.on("end", () => {
|
|
19619
20046
|
try {
|
|
19620
|
-
|
|
20047
|
+
resolve12(JSON.parse(body));
|
|
19621
20048
|
} catch {
|
|
19622
|
-
|
|
20049
|
+
resolve12({});
|
|
19623
20050
|
}
|
|
19624
20051
|
});
|
|
19625
20052
|
});
|
|
@@ -19953,6 +20380,7 @@ var SessionHostRuntimeTransport = class {
|
|
|
19953
20380
|
}
|
|
19954
20381
|
}
|
|
19955
20382
|
handleEvent(event) {
|
|
20383
|
+
if (!("sessionId" in event)) return;
|
|
19956
20384
|
if (event.sessionId !== this.options.runtimeId) return;
|
|
19957
20385
|
if ((event.type === "session_started" || event.type === "session_resumed") && typeof event.pid === "number") {
|
|
19958
20386
|
this.currentPid = event.pid;
|
|
@@ -20028,7 +20456,10 @@ var SessionHostRuntimeTransport = class {
|
|
|
20028
20456
|
clientId: client.clientId,
|
|
20029
20457
|
type: client.type,
|
|
20030
20458
|
readOnly: client.readOnly
|
|
20031
|
-
}))
|
|
20459
|
+
})),
|
|
20460
|
+
restoredFromStorage: record.meta?.restoredFromStorage === true,
|
|
20461
|
+
recoveryState: typeof record.meta?.runtimeRecoveryState === "string" ? String(record.meta.runtimeRecoveryState) : null,
|
|
20462
|
+
recoveryError: typeof record.meta?.runtimeRecoveryError === "string" ? String(record.meta.runtimeRecoveryError) : null
|
|
20032
20463
|
};
|
|
20033
20464
|
}
|
|
20034
20465
|
enqueue(action) {
|
|
@@ -20083,7 +20514,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
20083
20514
|
const deadline = Date.now() + timeoutMs;
|
|
20084
20515
|
while (Date.now() < deadline) {
|
|
20085
20516
|
if (await canConnect(endpoint)) return;
|
|
20086
|
-
await new Promise((
|
|
20517
|
+
await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
|
|
20087
20518
|
}
|
|
20088
20519
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
20089
20520
|
}
|
|
@@ -20239,10 +20670,10 @@ async function installExtension(ide, extension) {
|
|
|
20239
20670
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
20240
20671
|
const fs15 = await import("fs");
|
|
20241
20672
|
fs15.writeFileSync(vsixPath, buffer);
|
|
20242
|
-
return new Promise((
|
|
20673
|
+
return new Promise((resolve12) => {
|
|
20243
20674
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
20244
20675
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
20245
|
-
|
|
20676
|
+
resolve12({
|
|
20246
20677
|
extensionId: extension.id,
|
|
20247
20678
|
marketplaceId: extension.marketplaceId,
|
|
20248
20679
|
success: !error,
|
|
@@ -20255,11 +20686,11 @@ async function installExtension(ide, extension) {
|
|
|
20255
20686
|
} catch (e) {
|
|
20256
20687
|
}
|
|
20257
20688
|
}
|
|
20258
|
-
return new Promise((
|
|
20689
|
+
return new Promise((resolve12) => {
|
|
20259
20690
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
20260
20691
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
20261
20692
|
if (error) {
|
|
20262
|
-
|
|
20693
|
+
resolve12({
|
|
20263
20694
|
extensionId: extension.id,
|
|
20264
20695
|
marketplaceId: extension.marketplaceId,
|
|
20265
20696
|
success: false,
|
|
@@ -20267,7 +20698,7 @@ async function installExtension(ide, extension) {
|
|
|
20267
20698
|
error: stderr || error.message
|
|
20268
20699
|
});
|
|
20269
20700
|
} else {
|
|
20270
|
-
|
|
20701
|
+
resolve12({
|
|
20271
20702
|
extensionId: extension.id,
|
|
20272
20703
|
marketplaceId: extension.marketplaceId,
|
|
20273
20704
|
success: true,
|
|
@@ -20403,13 +20834,32 @@ async function initDaemonComponents(config) {
|
|
|
20403
20834
|
const detectedIdesRef = { value: [] };
|
|
20404
20835
|
let agentStreamManager = null;
|
|
20405
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
|
+
};
|
|
20406
20856
|
const cliManager = new DaemonCliManager({
|
|
20407
20857
|
...config.cliManagerDeps,
|
|
20408
20858
|
getInstanceManager: () => instanceManager,
|
|
20409
20859
|
getSessionRegistry: () => sessionRegistry
|
|
20410
20860
|
}, providerLoader);
|
|
20411
20861
|
LOG.info("Init", "Detecting IDEs...");
|
|
20412
|
-
|
|
20862
|
+
await refreshProviderAvailability();
|
|
20413
20863
|
const installed = detectedIdesRef.value.filter((i) => i.installed);
|
|
20414
20864
|
LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
|
|
20415
20865
|
const cdpSetupContext = {
|
|
@@ -20449,7 +20899,11 @@ async function initDaemonComponents(config) {
|
|
|
20449
20899
|
adapters: cliManager.adapters,
|
|
20450
20900
|
providerLoader,
|
|
20451
20901
|
instanceManager,
|
|
20452
|
-
sessionRegistry
|
|
20902
|
+
sessionRegistry,
|
|
20903
|
+
onProviderSettingChanged: async (providerType) => {
|
|
20904
|
+
await refreshProviderAvailability(providerType);
|
|
20905
|
+
config.onStatusChange?.();
|
|
20906
|
+
}
|
|
20453
20907
|
});
|
|
20454
20908
|
agentStreamManager = new DaemonAgentStreamManager(
|
|
20455
20909
|
LOG.forComponent("AgentStream").asLogFn(),
|
|
@@ -20472,6 +20926,7 @@ async function initDaemonComponents(config) {
|
|
|
20472
20926
|
onIdeConnected: () => poller?.start(),
|
|
20473
20927
|
onStatusChange: config.onStatusChange,
|
|
20474
20928
|
onPostChatCommand: config.onPostChatCommand,
|
|
20929
|
+
sessionHostControl: config.sessionHostControl,
|
|
20475
20930
|
getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
|
|
20476
20931
|
});
|
|
20477
20932
|
poller = new AgentStreamPoller({
|