@adhdev/daemon-standalone 0.8.27 → 0.8.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +996 -378
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/index-CE_CO9Co.js +59 -0
- package/public/assets/index-DD_wrUJr.css +1 -0
- package/public/index.html +2 -2
- package/vendor/session-host-daemon/index.d.mts +3 -0
- package/vendor/session-host-daemon/index.d.ts +3 -0
- package/vendor/session-host-daemon/index.js +101 -0
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +101 -0
- package/vendor/session-host-daemon/index.mjs.map +1 -1
- package/public/assets/index-BWeT3-TD.css +0 -1
- package/public/assets/index-CeRnyaZl.js +0 -56
package/dist/index.js
CHANGED
|
@@ -9495,6 +9495,9 @@ var require_dist = __commonJS({
|
|
|
9495
9495
|
state.record.lastActivityAt = Date.now();
|
|
9496
9496
|
return this.cloneRecord(state.record);
|
|
9497
9497
|
}
|
|
9498
|
+
deleteSession(sessionId) {
|
|
9499
|
+
return this.sessions.delete(sessionId);
|
|
9500
|
+
}
|
|
9498
9501
|
requireSession(sessionId) {
|
|
9499
9502
|
const state = this.sessions.get(sessionId);
|
|
9500
9503
|
if (!state) throw new Error(`Unknown session: ${sessionId}`);
|
|
@@ -9676,10 +9679,12 @@ var require_dist = __commonJS({
|
|
|
9676
9679
|
env[key] = value;
|
|
9677
9680
|
}
|
|
9678
9681
|
for (const key of Object.keys(env)) {
|
|
9679
|
-
if (key === "INIT_CWD" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
|
|
9682
|
+
if (key === "INIT_CWD" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_") || key.startsWith("VSCODE_") || key.startsWith("ELECTRON_")) {
|
|
9680
9683
|
delete env[key];
|
|
9681
9684
|
}
|
|
9682
9685
|
}
|
|
9686
|
+
delete env.CODEX_THREAD_ID;
|
|
9687
|
+
delete env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE;
|
|
9683
9688
|
applyTerminalColorEnv(env);
|
|
9684
9689
|
return env;
|
|
9685
9690
|
}
|
|
@@ -28029,13 +28034,13 @@ var require_dist2 = __commonJS({
|
|
|
28029
28034
|
return LOG_DIR;
|
|
28030
28035
|
}
|
|
28031
28036
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
28032
|
-
return
|
|
28037
|
+
return path6.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
28033
28038
|
}
|
|
28034
28039
|
function checkDateRotation() {
|
|
28035
28040
|
const today = getDateStr();
|
|
28036
28041
|
if (today !== currentDate) {
|
|
28037
28042
|
currentDate = today;
|
|
28038
|
-
currentLogFile =
|
|
28043
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
28039
28044
|
cleanOldLogs();
|
|
28040
28045
|
}
|
|
28041
28046
|
}
|
|
@@ -28049,7 +28054,7 @@ var require_dist2 = __commonJS({
|
|
|
28049
28054
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
28050
28055
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
28051
28056
|
try {
|
|
28052
|
-
fs22.unlinkSync(
|
|
28057
|
+
fs22.unlinkSync(path6.join(LOG_DIR, file2));
|
|
28053
28058
|
} catch {
|
|
28054
28059
|
}
|
|
28055
28060
|
}
|
|
@@ -28167,7 +28172,7 @@ var require_dist2 = __commonJS({
|
|
|
28167
28172
|
writeToFile(`Log level: ${currentLevel}`);
|
|
28168
28173
|
}
|
|
28169
28174
|
var fs22;
|
|
28170
|
-
var
|
|
28175
|
+
var path6;
|
|
28171
28176
|
var os42;
|
|
28172
28177
|
var LEVEL_NUM;
|
|
28173
28178
|
var LEVEL_LABEL;
|
|
@@ -28190,12 +28195,12 @@ var require_dist2 = __commonJS({
|
|
|
28190
28195
|
"src/logging/logger.ts"() {
|
|
28191
28196
|
"use strict";
|
|
28192
28197
|
fs22 = __toESM2(require("fs"));
|
|
28193
|
-
|
|
28198
|
+
path6 = __toESM2(require("path"));
|
|
28194
28199
|
os42 = __toESM2(require("os"));
|
|
28195
28200
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
28196
28201
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
28197
28202
|
currentLevel = "info";
|
|
28198
|
-
LOG_DIR = process.platform === "win32" ?
|
|
28203
|
+
LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os42.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os42.homedir(), "Library", "Logs", "adhdev") : path6.join(os42.homedir(), ".local", "share", "adhdev", "logs");
|
|
28199
28204
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
28200
28205
|
MAX_LOG_DAYS = 7;
|
|
28201
28206
|
try {
|
|
@@ -28203,16 +28208,16 @@ var require_dist2 = __commonJS({
|
|
|
28203
28208
|
} catch {
|
|
28204
28209
|
}
|
|
28205
28210
|
currentDate = getDateStr();
|
|
28206
|
-
currentLogFile =
|
|
28211
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
28207
28212
|
cleanOldLogs();
|
|
28208
28213
|
try {
|
|
28209
|
-
const oldLog =
|
|
28214
|
+
const oldLog = path6.join(LOG_DIR, "daemon.log");
|
|
28210
28215
|
if (fs22.existsSync(oldLog)) {
|
|
28211
28216
|
const stat4 = fs22.statSync(oldLog);
|
|
28212
28217
|
const oldDate = stat4.mtime.toISOString().slice(0, 10);
|
|
28213
|
-
fs22.renameSync(oldLog,
|
|
28218
|
+
fs22.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
28214
28219
|
}
|
|
28215
|
-
const oldLogBackup =
|
|
28220
|
+
const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
|
|
28216
28221
|
if (fs22.existsSync(oldLogBackup)) {
|
|
28217
28222
|
fs22.unlinkSync(oldLogBackup);
|
|
28218
28223
|
}
|
|
@@ -28244,7 +28249,7 @@ var require_dist2 = __commonJS({
|
|
|
28244
28249
|
}
|
|
28245
28250
|
};
|
|
28246
28251
|
interceptorInstalled = false;
|
|
28247
|
-
LOG_PATH =
|
|
28252
|
+
LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
28248
28253
|
}
|
|
28249
28254
|
});
|
|
28250
28255
|
function isModuleNotFoundError(error48, ref) {
|
|
@@ -28666,16 +28671,22 @@ var require_dist2 = __commonJS({
|
|
|
28666
28671
|
return "";
|
|
28667
28672
|
}
|
|
28668
28673
|
function findBinary(name) {
|
|
28674
|
+
const trimmed = String(name || "").trim();
|
|
28675
|
+
if (!trimmed) return trimmed;
|
|
28676
|
+
const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
|
|
28677
|
+
if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
28678
|
+
return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
28679
|
+
}
|
|
28669
28680
|
const isWin = os8.platform() === "win32";
|
|
28670
28681
|
try {
|
|
28671
|
-
const cmd = isWin ? `where ${
|
|
28682
|
+
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
28672
28683
|
return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
28673
28684
|
} catch {
|
|
28674
|
-
return isWin ? `${
|
|
28685
|
+
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
28675
28686
|
}
|
|
28676
28687
|
}
|
|
28677
28688
|
function isScriptBinary(binaryPath) {
|
|
28678
|
-
if (!
|
|
28689
|
+
if (!path9.isAbsolute(binaryPath)) return false;
|
|
28679
28690
|
try {
|
|
28680
28691
|
const fs15 = require("fs");
|
|
28681
28692
|
const resolved = fs15.realpathSync(binaryPath);
|
|
@@ -28691,7 +28702,7 @@ var require_dist2 = __commonJS({
|
|
|
28691
28702
|
}
|
|
28692
28703
|
}
|
|
28693
28704
|
function looksLikeMachOOrElf(filePath) {
|
|
28694
|
-
if (!
|
|
28705
|
+
if (!path9.isAbsolute(filePath)) return false;
|
|
28695
28706
|
try {
|
|
28696
28707
|
const fs15 = require("fs");
|
|
28697
28708
|
const resolved = fs15.realpathSync(filePath);
|
|
@@ -28816,7 +28827,7 @@ var require_dist2 = __commonJS({
|
|
|
28816
28827
|
};
|
|
28817
28828
|
}
|
|
28818
28829
|
var os8;
|
|
28819
|
-
var
|
|
28830
|
+
var path9;
|
|
28820
28831
|
var import_child_process4;
|
|
28821
28832
|
var buildCliSpawnEnv;
|
|
28822
28833
|
var ProviderCliAdapter;
|
|
@@ -28824,7 +28835,7 @@ var require_dist2 = __commonJS({
|
|
|
28824
28835
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
28825
28836
|
"use strict";
|
|
28826
28837
|
os8 = __toESM2(require("os"));
|
|
28827
|
-
|
|
28838
|
+
path9 = __toESM2(require("path"));
|
|
28828
28839
|
import_child_process4 = require("child_process");
|
|
28829
28840
|
init_logger();
|
|
28830
28841
|
init_terminal_screen();
|
|
@@ -29179,16 +29190,17 @@ var require_dist2 = __commonJS({
|
|
|
29179
29190
|
async spawn() {
|
|
29180
29191
|
if (this.ptyProcess) return;
|
|
29181
29192
|
const { spawn: spawnConfig } = this.provider;
|
|
29182
|
-
const
|
|
29193
|
+
const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
29194
|
+
const binaryPath = findBinary(configuredCommand);
|
|
29183
29195
|
const isWin = os8.platform() === "win32";
|
|
29184
29196
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
29185
29197
|
LOG2.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
29186
29198
|
this.resetTraceSession();
|
|
29187
29199
|
let shellCmd;
|
|
29188
29200
|
let shellArgs;
|
|
29189
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
29201
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
29190
29202
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
29191
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
29203
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
29192
29204
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
29193
29205
|
if (useShell) {
|
|
29194
29206
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -29433,6 +29445,9 @@ var require_dist2 = __commonJS({
|
|
|
29433
29445
|
looksLikeVisibleIdlePrompt(screenText) {
|
|
29434
29446
|
const text = String(screenText || "");
|
|
29435
29447
|
if (!text.trim()) return false;
|
|
29448
|
+
if (this.cliType === "codex-cli" && /(^|\n)\s*[❯›>]\s+(?:Find and fix a bug in @filename|Improve documentation in @filename|Use \/skills|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Run \/review on my current changes)(?:\n|$)/im.test(text)) {
|
|
29449
|
+
return true;
|
|
29450
|
+
}
|
|
29436
29451
|
return /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(text) || /⏎\s+send/i.test(text) || /\?\s*for\s*shortcuts/i.test(text) || /Type your message(?:\s+or\s+@path\/to\/file)?/i.test(text) || /workspace\s*\(\/directory\)/i.test(text) || /for\s*shortcuts/i.test(text);
|
|
29437
29452
|
}
|
|
29438
29453
|
findLastMatchingLineIndex(lines, predicate) {
|
|
@@ -29562,7 +29577,7 @@ var require_dist2 = __commonJS({
|
|
|
29562
29577
|
`[${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)}`
|
|
29563
29578
|
);
|
|
29564
29579
|
}
|
|
29565
|
-
await new Promise((
|
|
29580
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
29566
29581
|
}
|
|
29567
29582
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
29568
29583
|
LOG2.warn(
|
|
@@ -30073,7 +30088,7 @@ ${data.message || ""}`.trim();
|
|
|
30073
30088
|
const deadline = Date.now() + 1e4;
|
|
30074
30089
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
30075
30090
|
this.resolveStartupState("send_wait");
|
|
30076
|
-
await new Promise((
|
|
30091
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
30077
30092
|
}
|
|
30078
30093
|
}
|
|
30079
30094
|
await this.waitForInteractivePrompt();
|
|
@@ -30298,17 +30313,17 @@ ${data.message || ""}`.trim();
|
|
|
30298
30313
|
}
|
|
30299
30314
|
}
|
|
30300
30315
|
waitForStopped(timeoutMs) {
|
|
30301
|
-
return new Promise((
|
|
30316
|
+
return new Promise((resolve12) => {
|
|
30302
30317
|
const startedAt = Date.now();
|
|
30303
30318
|
const timer = setInterval(() => {
|
|
30304
30319
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
30305
30320
|
clearInterval(timer);
|
|
30306
|
-
|
|
30321
|
+
resolve12(true);
|
|
30307
30322
|
return;
|
|
30308
30323
|
}
|
|
30309
30324
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
30310
30325
|
clearInterval(timer);
|
|
30311
|
-
|
|
30326
|
+
resolve12(false);
|
|
30312
30327
|
}
|
|
30313
30328
|
}, 100);
|
|
30314
30329
|
});
|
|
@@ -30995,6 +31010,7 @@ ${data.message || ""}`.trim();
|
|
|
30995
31010
|
var import_child_process2 = require("child_process");
|
|
30996
31011
|
var import_fs3 = require("fs");
|
|
30997
31012
|
var import_os22 = require("os");
|
|
31013
|
+
var path42 = __toESM2(require("path"));
|
|
30998
31014
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
30999
31015
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
31000
31016
|
function registerIDEDefinition(def) {
|
|
@@ -31011,9 +31027,16 @@ ${data.message || ""}`.trim();
|
|
|
31011
31027
|
return [...merged.values()];
|
|
31012
31028
|
}
|
|
31013
31029
|
function findCliCommand(command) {
|
|
31030
|
+
const trimmed = String(command || "").trim();
|
|
31031
|
+
if (!trimmed) return null;
|
|
31032
|
+
if (path42.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
31033
|
+
const candidate = trimmed.startsWith("~") ? path42.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
|
|
31034
|
+
const resolved = path42.isAbsolute(candidate) ? candidate : path42.resolve(candidate);
|
|
31035
|
+
return (0, import_fs3.existsSync)(resolved) ? resolved : null;
|
|
31036
|
+
}
|
|
31014
31037
|
try {
|
|
31015
31038
|
const result = (0, import_child_process2.execSync)(
|
|
31016
|
-
(0, import_os22.platform)() === "win32" ? `where ${
|
|
31039
|
+
(0, import_os22.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
31017
31040
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
31018
31041
|
).trim();
|
|
31019
31042
|
return result.split("\n")[0] || null;
|
|
@@ -31036,23 +31059,23 @@ ${data.message || ""}`.trim();
|
|
|
31036
31059
|
function checkPathExists(paths) {
|
|
31037
31060
|
const home = (0, import_os22.homedir)();
|
|
31038
31061
|
for (const p of paths) {
|
|
31039
|
-
|
|
31062
|
+
const normalized = p.startsWith("~") ? path42.join(home, p.slice(1)) : p;
|
|
31063
|
+
if (normalized.includes("*")) {
|
|
31040
31064
|
const username = home.split(/[\\/]/).pop() || "";
|
|
31041
|
-
const resolved =
|
|
31065
|
+
const resolved = normalized.replace("*", username);
|
|
31042
31066
|
if ((0, import_fs3.existsSync)(resolved)) return resolved;
|
|
31043
31067
|
} else {
|
|
31044
|
-
if ((0, import_fs3.existsSync)(
|
|
31068
|
+
if ((0, import_fs3.existsSync)(normalized)) return normalized;
|
|
31045
31069
|
}
|
|
31046
31070
|
}
|
|
31047
31071
|
return null;
|
|
31048
31072
|
}
|
|
31049
|
-
async function detectIDEs() {
|
|
31073
|
+
async function detectIDEs(providerLoader) {
|
|
31050
31074
|
const os18 = (0, import_os22.platform)();
|
|
31051
31075
|
const results = [];
|
|
31052
31076
|
for (const def of getMergedDefinitions()) {
|
|
31053
|
-
const cliPath = findCliCommand(def.cli);
|
|
31054
|
-
const appPath = checkPathExists(def.paths[os18] || []);
|
|
31055
|
-
const installed = !!(cliPath || appPath);
|
|
31077
|
+
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
31078
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
|
|
31056
31079
|
let resolvedCli = cliPath;
|
|
31057
31080
|
if (!resolvedCli && appPath && os18 === "darwin") {
|
|
31058
31081
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
@@ -31075,6 +31098,7 @@ ${data.message || ""}`.trim();
|
|
|
31075
31098
|
}
|
|
31076
31099
|
}
|
|
31077
31100
|
}
|
|
31101
|
+
const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
31078
31102
|
const version2 = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
31079
31103
|
results.push({
|
|
31080
31104
|
id: def.id,
|
|
@@ -31091,48 +31115,77 @@ ${data.message || ""}`.trim();
|
|
|
31091
31115
|
}
|
|
31092
31116
|
var import_child_process22 = require("child_process");
|
|
31093
31117
|
var os22 = __toESM2(require("os"));
|
|
31118
|
+
var path52 = __toESM2(require("path"));
|
|
31119
|
+
var import_fs4 = require("fs");
|
|
31094
31120
|
function parseVersion(raw) {
|
|
31095
31121
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
31096
31122
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
31097
31123
|
}
|
|
31124
|
+
function shellQuote(value) {
|
|
31125
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
31126
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
31127
|
+
}
|
|
31128
|
+
function expandHome(value) {
|
|
31129
|
+
const trimmed = value.trim();
|
|
31130
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
31131
|
+
return path52.join(os22.homedir(), trimmed.slice(1));
|
|
31132
|
+
}
|
|
31133
|
+
function isExplicitCommandPath(command) {
|
|
31134
|
+
const trimmed = command.trim();
|
|
31135
|
+
return path52.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
31136
|
+
}
|
|
31137
|
+
function resolveCommandPath(command) {
|
|
31138
|
+
const trimmed = command.trim();
|
|
31139
|
+
if (!trimmed) return null;
|
|
31140
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
31141
|
+
const expanded = expandHome(trimmed);
|
|
31142
|
+
const candidate = path52.isAbsolute(expanded) ? expanded : path52.resolve(expanded);
|
|
31143
|
+
return (0, import_fs4.existsSync)(candidate) ? candidate : null;
|
|
31144
|
+
}
|
|
31145
|
+
return null;
|
|
31146
|
+
}
|
|
31098
31147
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
31099
|
-
return new Promise((
|
|
31148
|
+
return new Promise((resolve12) => {
|
|
31100
31149
|
const child = (0, import_child_process22.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
31101
31150
|
if (err || !stdout?.trim()) {
|
|
31102
|
-
|
|
31151
|
+
resolve12(null);
|
|
31103
31152
|
} else {
|
|
31104
|
-
|
|
31153
|
+
resolve12(stdout.trim());
|
|
31105
31154
|
}
|
|
31106
31155
|
});
|
|
31107
|
-
child.on("error", () =>
|
|
31156
|
+
child.on("error", () => resolve12(null));
|
|
31108
31157
|
});
|
|
31109
31158
|
}
|
|
31110
|
-
async function detectCLIs(providerLoader) {
|
|
31159
|
+
async function detectCLIs(providerLoader, options) {
|
|
31111
31160
|
const platform9 = os22.platform();
|
|
31112
31161
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
31162
|
+
const includeVersion = options?.includeVersion !== false;
|
|
31113
31163
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
31114
31164
|
const results = await Promise.all(
|
|
31115
31165
|
cliList.map(async (cli) => {
|
|
31116
31166
|
try {
|
|
31117
|
-
const
|
|
31167
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
31168
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
31118
31169
|
if (!pathResult) return { ...cli, installed: false };
|
|
31119
|
-
const firstPath = pathResult.split("\n")[0];
|
|
31170
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
31120
31171
|
let version2;
|
|
31121
|
-
|
|
31172
|
+
if (includeVersion) {
|
|
31122
31173
|
const versionCommands = [
|
|
31123
|
-
|
|
31124
|
-
|
|
31125
|
-
|
|
31126
|
-
|
|
31174
|
+
`"${firstPath}" --version`,
|
|
31175
|
+
`"${firstPath}" -V`,
|
|
31176
|
+
`"${firstPath}" -v`,
|
|
31177
|
+
cli.versionCommand
|
|
31127
31178
|
].filter((v2) => !!v2);
|
|
31128
|
-
|
|
31129
|
-
const
|
|
31130
|
-
|
|
31131
|
-
|
|
31132
|
-
|
|
31179
|
+
try {
|
|
31180
|
+
for (const versionCommand of versionCommands) {
|
|
31181
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
31182
|
+
if (versionResult) {
|
|
31183
|
+
version2 = parseVersion(versionResult);
|
|
31184
|
+
break;
|
|
31185
|
+
}
|
|
31133
31186
|
}
|
|
31187
|
+
} catch {
|
|
31134
31188
|
}
|
|
31135
|
-
} catch {
|
|
31136
31189
|
}
|
|
31137
31190
|
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
31138
31191
|
} catch {
|
|
@@ -31142,7 +31195,7 @@ ${data.message || ""}`.trim();
|
|
|
31142
31195
|
);
|
|
31143
31196
|
return results;
|
|
31144
31197
|
}
|
|
31145
|
-
async function detectCLI(cliId, providerLoader) {
|
|
31198
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
31146
31199
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
31147
31200
|
if (providerLoader) {
|
|
31148
31201
|
const cliList = providerLoader.getCliDetectionList();
|
|
@@ -31151,25 +31204,28 @@ ${data.message || ""}`.trim();
|
|
|
31151
31204
|
const platform9 = os22.platform();
|
|
31152
31205
|
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
31153
31206
|
try {
|
|
31154
|
-
const
|
|
31207
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
31208
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
31155
31209
|
if (!pathResult) return null;
|
|
31156
|
-
const firstPath = pathResult.split("\n")[0];
|
|
31210
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
31157
31211
|
let version2;
|
|
31158
|
-
|
|
31212
|
+
if (options?.includeVersion !== false) {
|
|
31159
31213
|
const versionCommands = [
|
|
31160
|
-
|
|
31161
|
-
|
|
31162
|
-
|
|
31163
|
-
|
|
31214
|
+
`"${firstPath}" --version`,
|
|
31215
|
+
`"${firstPath}" -V`,
|
|
31216
|
+
`"${firstPath}" -v`,
|
|
31217
|
+
target.versionCommand
|
|
31164
31218
|
].filter((v2) => !!v2);
|
|
31165
|
-
|
|
31166
|
-
const
|
|
31167
|
-
|
|
31168
|
-
|
|
31169
|
-
|
|
31219
|
+
try {
|
|
31220
|
+
for (const versionCommand of versionCommands) {
|
|
31221
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
31222
|
+
if (versionResult) {
|
|
31223
|
+
version2 = parseVersion(versionResult);
|
|
31224
|
+
break;
|
|
31225
|
+
}
|
|
31170
31226
|
}
|
|
31227
|
+
} catch {
|
|
31171
31228
|
}
|
|
31172
|
-
} catch {
|
|
31173
31229
|
}
|
|
31174
31230
|
return { ...target, installed: true, version: version2, path: firstPath };
|
|
31175
31231
|
} catch {
|
|
@@ -31177,7 +31233,7 @@ ${data.message || ""}`.trim();
|
|
|
31177
31233
|
}
|
|
31178
31234
|
}
|
|
31179
31235
|
}
|
|
31180
|
-
const all = await detectCLIs(providerLoader);
|
|
31236
|
+
const all = await detectCLIs(providerLoader, options);
|
|
31181
31237
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
31182
31238
|
}
|
|
31183
31239
|
var os32 = __toESM2(require("os"));
|
|
@@ -31300,7 +31356,7 @@ ${data.message || ""}`.trim();
|
|
|
31300
31356
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
31301
31357
|
*/
|
|
31302
31358
|
static listAllTargets(port) {
|
|
31303
|
-
return new Promise((
|
|
31359
|
+
return new Promise((resolve12) => {
|
|
31304
31360
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
31305
31361
|
let data = "";
|
|
31306
31362
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -31316,16 +31372,16 @@ ${data.message || ""}`.trim();
|
|
|
31316
31372
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
31317
31373
|
);
|
|
31318
31374
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
31319
|
-
|
|
31375
|
+
resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
31320
31376
|
} catch {
|
|
31321
|
-
|
|
31377
|
+
resolve12([]);
|
|
31322
31378
|
}
|
|
31323
31379
|
});
|
|
31324
31380
|
});
|
|
31325
|
-
req.on("error", () =>
|
|
31381
|
+
req.on("error", () => resolve12([]));
|
|
31326
31382
|
req.setTimeout(2e3, () => {
|
|
31327
31383
|
req.destroy();
|
|
31328
|
-
|
|
31384
|
+
resolve12([]);
|
|
31329
31385
|
});
|
|
31330
31386
|
});
|
|
31331
31387
|
}
|
|
@@ -31365,7 +31421,7 @@ ${data.message || ""}`.trim();
|
|
|
31365
31421
|
}
|
|
31366
31422
|
}
|
|
31367
31423
|
findTargetOnPort(port) {
|
|
31368
|
-
return new Promise((
|
|
31424
|
+
return new Promise((resolve12) => {
|
|
31369
31425
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
31370
31426
|
let data = "";
|
|
31371
31427
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -31376,7 +31432,7 @@ ${data.message || ""}`.trim();
|
|
|
31376
31432
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
31377
31433
|
);
|
|
31378
31434
|
if (pages.length === 0) {
|
|
31379
|
-
|
|
31435
|
+
resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
31380
31436
|
return;
|
|
31381
31437
|
}
|
|
31382
31438
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -31386,24 +31442,24 @@ ${data.message || ""}`.trim();
|
|
|
31386
31442
|
const specific = list.find((t) => t.id === this._targetId);
|
|
31387
31443
|
if (specific) {
|
|
31388
31444
|
this._pageTitle = specific.title || "";
|
|
31389
|
-
|
|
31445
|
+
resolve12(specific);
|
|
31390
31446
|
} else {
|
|
31391
31447
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
31392
|
-
|
|
31448
|
+
resolve12(null);
|
|
31393
31449
|
}
|
|
31394
31450
|
return;
|
|
31395
31451
|
}
|
|
31396
31452
|
this._pageTitle = list[0]?.title || "";
|
|
31397
|
-
|
|
31453
|
+
resolve12(list[0]);
|
|
31398
31454
|
} catch {
|
|
31399
|
-
|
|
31455
|
+
resolve12(null);
|
|
31400
31456
|
}
|
|
31401
31457
|
});
|
|
31402
31458
|
});
|
|
31403
|
-
req.on("error", () =>
|
|
31459
|
+
req.on("error", () => resolve12(null));
|
|
31404
31460
|
req.setTimeout(2e3, () => {
|
|
31405
31461
|
req.destroy();
|
|
31406
|
-
|
|
31462
|
+
resolve12(null);
|
|
31407
31463
|
});
|
|
31408
31464
|
});
|
|
31409
31465
|
}
|
|
@@ -31414,7 +31470,7 @@ ${data.message || ""}`.trim();
|
|
|
31414
31470
|
this.extensionProviders = providers;
|
|
31415
31471
|
}
|
|
31416
31472
|
connectToTarget(wsUrl) {
|
|
31417
|
-
return new Promise((
|
|
31473
|
+
return new Promise((resolve12) => {
|
|
31418
31474
|
this.ws = new import_ws2.default(wsUrl);
|
|
31419
31475
|
this.ws.on("open", async () => {
|
|
31420
31476
|
this._connected = true;
|
|
@@ -31424,17 +31480,17 @@ ${data.message || ""}`.trim();
|
|
|
31424
31480
|
}
|
|
31425
31481
|
this.connectBrowserWs().catch(() => {
|
|
31426
31482
|
});
|
|
31427
|
-
|
|
31483
|
+
resolve12(true);
|
|
31428
31484
|
});
|
|
31429
31485
|
this.ws.on("message", (data) => {
|
|
31430
31486
|
try {
|
|
31431
31487
|
const msg = JSON.parse(data.toString());
|
|
31432
31488
|
if (msg.id && this.pending.has(msg.id)) {
|
|
31433
|
-
const { resolve:
|
|
31489
|
+
const { resolve: resolve13, reject } = this.pending.get(msg.id);
|
|
31434
31490
|
this.pending.delete(msg.id);
|
|
31435
31491
|
this.failureCount = 0;
|
|
31436
31492
|
if (msg.error) reject(new Error(msg.error.message));
|
|
31437
|
-
else
|
|
31493
|
+
else resolve13(msg.result);
|
|
31438
31494
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
31439
31495
|
this.contexts.add(msg.params.context.id);
|
|
31440
31496
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -31457,7 +31513,7 @@ ${data.message || ""}`.trim();
|
|
|
31457
31513
|
this.ws.on("error", (err) => {
|
|
31458
31514
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
31459
31515
|
this._connected = false;
|
|
31460
|
-
|
|
31516
|
+
resolve12(false);
|
|
31461
31517
|
});
|
|
31462
31518
|
});
|
|
31463
31519
|
}
|
|
@@ -31471,7 +31527,7 @@ ${data.message || ""}`.trim();
|
|
|
31471
31527
|
return;
|
|
31472
31528
|
}
|
|
31473
31529
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
31474
|
-
await new Promise((
|
|
31530
|
+
await new Promise((resolve12, reject) => {
|
|
31475
31531
|
this.browserWs = new import_ws2.default(browserWsUrl);
|
|
31476
31532
|
this.browserWs.on("open", async () => {
|
|
31477
31533
|
this._browserConnected = true;
|
|
@@ -31481,16 +31537,16 @@ ${data.message || ""}`.trim();
|
|
|
31481
31537
|
} catch (e) {
|
|
31482
31538
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
31483
31539
|
}
|
|
31484
|
-
|
|
31540
|
+
resolve12();
|
|
31485
31541
|
});
|
|
31486
31542
|
this.browserWs.on("message", (data) => {
|
|
31487
31543
|
try {
|
|
31488
31544
|
const msg = JSON.parse(data.toString());
|
|
31489
31545
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
31490
|
-
const { resolve:
|
|
31546
|
+
const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
|
|
31491
31547
|
this.browserPending.delete(msg.id);
|
|
31492
31548
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
31493
|
-
else
|
|
31549
|
+
else resolve13(msg.result);
|
|
31494
31550
|
}
|
|
31495
31551
|
} catch {
|
|
31496
31552
|
}
|
|
@@ -31510,31 +31566,31 @@ ${data.message || ""}`.trim();
|
|
|
31510
31566
|
}
|
|
31511
31567
|
}
|
|
31512
31568
|
getBrowserWsUrl() {
|
|
31513
|
-
return new Promise((
|
|
31569
|
+
return new Promise((resolve12) => {
|
|
31514
31570
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
31515
31571
|
let data = "";
|
|
31516
31572
|
res.on("data", (chunk) => data += chunk.toString());
|
|
31517
31573
|
res.on("end", () => {
|
|
31518
31574
|
try {
|
|
31519
31575
|
const info = JSON.parse(data);
|
|
31520
|
-
|
|
31576
|
+
resolve12(info.webSocketDebuggerUrl || null);
|
|
31521
31577
|
} catch {
|
|
31522
|
-
|
|
31578
|
+
resolve12(null);
|
|
31523
31579
|
}
|
|
31524
31580
|
});
|
|
31525
31581
|
});
|
|
31526
|
-
req.on("error", () =>
|
|
31582
|
+
req.on("error", () => resolve12(null));
|
|
31527
31583
|
req.setTimeout(3e3, () => {
|
|
31528
31584
|
req.destroy();
|
|
31529
|
-
|
|
31585
|
+
resolve12(null);
|
|
31530
31586
|
});
|
|
31531
31587
|
});
|
|
31532
31588
|
}
|
|
31533
31589
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
31534
|
-
return new Promise((
|
|
31590
|
+
return new Promise((resolve12, reject) => {
|
|
31535
31591
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
31536
31592
|
const id = this.browserMsgId++;
|
|
31537
|
-
this.browserPending.set(id, { resolve:
|
|
31593
|
+
this.browserPending.set(id, { resolve: resolve12, reject });
|
|
31538
31594
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
31539
31595
|
setTimeout(() => {
|
|
31540
31596
|
if (this.browserPending.has(id)) {
|
|
@@ -31574,11 +31630,11 @@ ${data.message || ""}`.trim();
|
|
|
31574
31630
|
}
|
|
31575
31631
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
31576
31632
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
31577
|
-
return new Promise((
|
|
31633
|
+
return new Promise((resolve12, reject) => {
|
|
31578
31634
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
31579
31635
|
if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
31580
31636
|
const id = this.msgId++;
|
|
31581
|
-
this.pending.set(id, { resolve:
|
|
31637
|
+
this.pending.set(id, { resolve: resolve12, reject });
|
|
31582
31638
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
31583
31639
|
setTimeout(() => {
|
|
31584
31640
|
if (this.pending.has(id)) {
|
|
@@ -31827,7 +31883,7 @@ ${data.message || ""}`.trim();
|
|
|
31827
31883
|
const browserWs = this.browserWs;
|
|
31828
31884
|
let msgId = this.browserMsgId;
|
|
31829
31885
|
const sendWs = (method, params = {}, sessionId) => {
|
|
31830
|
-
return new Promise((
|
|
31886
|
+
return new Promise((resolve12, reject) => {
|
|
31831
31887
|
const mid = msgId++;
|
|
31832
31888
|
this.browserMsgId = msgId;
|
|
31833
31889
|
const handler = (raw) => {
|
|
@@ -31836,7 +31892,7 @@ ${data.message || ""}`.trim();
|
|
|
31836
31892
|
if (msg.id === mid) {
|
|
31837
31893
|
browserWs.removeListener("message", handler);
|
|
31838
31894
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
31839
|
-
else
|
|
31895
|
+
else resolve12(msg.result);
|
|
31840
31896
|
}
|
|
31841
31897
|
} catch {
|
|
31842
31898
|
}
|
|
@@ -32027,14 +32083,14 @@ ${data.message || ""}`.trim();
|
|
|
32027
32083
|
if (!ws2 || ws2.readyState !== import_ws2.default.OPEN) {
|
|
32028
32084
|
throw new Error("CDP not connected");
|
|
32029
32085
|
}
|
|
32030
|
-
return new Promise((
|
|
32086
|
+
return new Promise((resolve12, reject) => {
|
|
32031
32087
|
const id = getNextId();
|
|
32032
32088
|
pendingMap.set(id, {
|
|
32033
32089
|
resolve: (result) => {
|
|
32034
32090
|
if (result?.result?.subtype === "error") {
|
|
32035
32091
|
reject(new Error(result.result.description));
|
|
32036
32092
|
} else {
|
|
32037
|
-
|
|
32093
|
+
resolve12(result?.result?.value);
|
|
32038
32094
|
}
|
|
32039
32095
|
},
|
|
32040
32096
|
reject
|
|
@@ -32066,10 +32122,10 @@ ${data.message || ""}`.trim();
|
|
|
32066
32122
|
throw new Error("CDP not connected");
|
|
32067
32123
|
}
|
|
32068
32124
|
const sendViaSession = (method, params = {}) => {
|
|
32069
|
-
return new Promise((
|
|
32125
|
+
return new Promise((resolve12, reject) => {
|
|
32070
32126
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
32071
32127
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
32072
|
-
pendingMap.set(id, { resolve:
|
|
32128
|
+
pendingMap.set(id, { resolve: resolve12, reject });
|
|
32073
32129
|
ws2.send(JSON.stringify({ id, sessionId, method, params }));
|
|
32074
32130
|
setTimeout(() => {
|
|
32075
32131
|
if (pendingMap.has(id)) {
|
|
@@ -32687,15 +32743,76 @@ ${data.message || ""}`.trim();
|
|
|
32687
32743
|
return String(value);
|
|
32688
32744
|
}
|
|
32689
32745
|
var fs32 = __toESM2(require("fs"));
|
|
32690
|
-
var
|
|
32746
|
+
var path7 = __toESM2(require("path"));
|
|
32691
32747
|
var os52 = __toESM2(require("os"));
|
|
32692
|
-
var HISTORY_DIR =
|
|
32748
|
+
var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
|
|
32693
32749
|
var RETAIN_DAYS = 30;
|
|
32750
|
+
var CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
|
|
32751
|
+
function normalizeHistoryComparable(text) {
|
|
32752
|
+
return String(text || "").replace(/\s+/g, " ").trim();
|
|
32753
|
+
}
|
|
32754
|
+
function cleanupHistoryContent(agentType, role, content) {
|
|
32755
|
+
let value = String(content || "").replace(/\r\n/g, "\n").trim();
|
|
32756
|
+
if (!value) return "";
|
|
32757
|
+
if (agentType === "codex-cli" && role === "assistant") {
|
|
32758
|
+
const filtered = value.split("\n").filter((line) => !CODEX_STARTER_PROMPT_RE.test(line.trim())).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
32759
|
+
value = filtered;
|
|
32760
|
+
}
|
|
32761
|
+
return value;
|
|
32762
|
+
}
|
|
32763
|
+
function buildHistoryMessageHash(agentType, message) {
|
|
32764
|
+
if (message.historyDedupKey) return message.historyDedupKey;
|
|
32765
|
+
const cleaned = cleanupHistoryContent(agentType, message.role, message.content);
|
|
32766
|
+
return `${message.kind || "standard"}:${message.role}:${message.receivedAt || 0}:${normalizeHistoryComparable(cleaned)}`;
|
|
32767
|
+
}
|
|
32768
|
+
function buildHistoryMessageSignature(agentType, message) {
|
|
32769
|
+
const cleaned = cleanupHistoryContent(agentType, message.role, message.content);
|
|
32770
|
+
return `${message.kind || "standard"}:${message.role}:${normalizeHistoryComparable(cleaned)}`;
|
|
32771
|
+
}
|
|
32772
|
+
function isAdjacentHistoryDuplicate(agentType, previous, next) {
|
|
32773
|
+
if (!previous || !next) return false;
|
|
32774
|
+
return buildHistoryMessageSignature(agentType, previous) === buildHistoryMessageSignature(agentType, next);
|
|
32775
|
+
}
|
|
32776
|
+
function collapseReplayAssistantTurns(agentType, messages) {
|
|
32777
|
+
if (agentType !== "codex-cli") return messages;
|
|
32778
|
+
const collapsed = [];
|
|
32779
|
+
let sawAssistantSinceLastUser = false;
|
|
32780
|
+
for (const message of messages) {
|
|
32781
|
+
if (message.role === "user") {
|
|
32782
|
+
sawAssistantSinceLastUser = false;
|
|
32783
|
+
collapsed.push(message);
|
|
32784
|
+
continue;
|
|
32785
|
+
}
|
|
32786
|
+
if (message.role === "assistant") {
|
|
32787
|
+
if (sawAssistantSinceLastUser) continue;
|
|
32788
|
+
sawAssistantSinceLastUser = true;
|
|
32789
|
+
collapsed.push(message);
|
|
32790
|
+
continue;
|
|
32791
|
+
}
|
|
32792
|
+
collapsed.push(message);
|
|
32793
|
+
}
|
|
32794
|
+
return collapsed;
|
|
32795
|
+
}
|
|
32796
|
+
function sanitizeHistoryMessage(agentType, message) {
|
|
32797
|
+
if (!message || message.role !== "user" && message.role !== "assistant" && message.role !== "system") {
|
|
32798
|
+
return null;
|
|
32799
|
+
}
|
|
32800
|
+
const content = cleanupHistoryContent(agentType, message.role, message.content);
|
|
32801
|
+
if (!content) return null;
|
|
32802
|
+
return {
|
|
32803
|
+
...message,
|
|
32804
|
+
content
|
|
32805
|
+
};
|
|
32806
|
+
}
|
|
32694
32807
|
var ChatHistoryWriter = class {
|
|
32695
32808
|
/** Last seen message count per agent (deduplication) */
|
|
32696
32809
|
lastSeenCounts = /* @__PURE__ */ new Map();
|
|
32697
32810
|
/** Last seen message hash per agent (deduplication) */
|
|
32698
32811
|
lastSeenHashes = /* @__PURE__ */ new Map();
|
|
32812
|
+
/** Last appended normalized message signature per agent/session */
|
|
32813
|
+
lastSeenSignatures = /* @__PURE__ */ new Map();
|
|
32814
|
+
/** Last appended normalized non-system turn signature per agent/session */
|
|
32815
|
+
lastSeenTurnSignatures = /* @__PURE__ */ new Map();
|
|
32699
32816
|
rotated = false;
|
|
32700
32817
|
/**
|
|
32701
32818
|
* Append new messages to history
|
|
@@ -32717,14 +32834,36 @@ ${data.message || ""}`.trim();
|
|
|
32717
32834
|
}
|
|
32718
32835
|
const newMessages = [];
|
|
32719
32836
|
for (const msg of messages) {
|
|
32720
|
-
const
|
|
32837
|
+
const role = msg.role;
|
|
32838
|
+
if (role !== "user" && role !== "assistant" && role !== "system") continue;
|
|
32839
|
+
const content = cleanupHistoryContent(agentType, role, msg.content || "");
|
|
32840
|
+
if (!content) continue;
|
|
32841
|
+
const receivedAt = msg.receivedAt || Date.now();
|
|
32842
|
+
const hash2 = buildHistoryMessageHash(agentType, {
|
|
32843
|
+
role,
|
|
32844
|
+
content,
|
|
32845
|
+
receivedAt,
|
|
32846
|
+
kind: typeof msg.kind === "string" ? msg.kind : void 0,
|
|
32847
|
+
historyDedupKey: msg.historyDedupKey
|
|
32848
|
+
});
|
|
32849
|
+
const signature = buildHistoryMessageSignature(agentType, {
|
|
32850
|
+
role,
|
|
32851
|
+
content,
|
|
32852
|
+
kind: typeof msg.kind === "string" ? msg.kind : void 0
|
|
32853
|
+
});
|
|
32721
32854
|
if (seenHashes.has(hash2)) continue;
|
|
32855
|
+
if (this.lastSeenSignatures.get(dedupKey) === signature) continue;
|
|
32856
|
+
if (role !== "system" && this.lastSeenTurnSignatures.get(dedupKey) === signature) continue;
|
|
32722
32857
|
seenHashes.add(hash2);
|
|
32858
|
+
this.lastSeenSignatures.set(dedupKey, signature);
|
|
32859
|
+
if (role !== "system") {
|
|
32860
|
+
this.lastSeenTurnSignatures.set(dedupKey, signature);
|
|
32861
|
+
}
|
|
32723
32862
|
newMessages.push({
|
|
32724
|
-
ts: new Date(
|
|
32725
|
-
receivedAt
|
|
32726
|
-
role
|
|
32727
|
-
content
|
|
32863
|
+
ts: new Date(receivedAt).toISOString(),
|
|
32864
|
+
receivedAt,
|
|
32865
|
+
role,
|
|
32866
|
+
content,
|
|
32728
32867
|
kind: typeof msg.kind === "string" ? msg.kind : void 0,
|
|
32729
32868
|
senderName: typeof msg.senderName === "string" ? msg.senderName : void 0,
|
|
32730
32869
|
agent: agentType,
|
|
@@ -32734,16 +32873,18 @@ ${data.message || ""}`.trim();
|
|
|
32734
32873
|
});
|
|
32735
32874
|
}
|
|
32736
32875
|
if (newMessages.length === 0) return;
|
|
32737
|
-
const dir =
|
|
32876
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
32738
32877
|
fs32.mkdirSync(dir, { recursive: true });
|
|
32739
32878
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
32740
32879
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
32741
|
-
const filePath =
|
|
32880
|
+
const filePath = path7.join(dir, `${filePrefix}${date5}.jsonl`);
|
|
32742
32881
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
32743
32882
|
fs32.appendFileSync(filePath, lines, "utf-8");
|
|
32744
32883
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
32745
32884
|
if (messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
32746
32885
|
seenHashes.clear();
|
|
32886
|
+
this.lastSeenSignatures.delete(dedupKey);
|
|
32887
|
+
this.lastSeenTurnSignatures.delete(dedupKey);
|
|
32747
32888
|
for (const msg of messages) {
|
|
32748
32889
|
seenHashes.add(msg.historyDedupKey || `${msg.kind || "standard"}:${msg.role}:${(msg.content || "").slice(0, 50)}`);
|
|
32749
32890
|
}
|
|
@@ -32757,6 +32898,54 @@ ${data.message || ""}`.trim();
|
|
|
32757
32898
|
} catch {
|
|
32758
32899
|
}
|
|
32759
32900
|
}
|
|
32901
|
+
seedSessionHistory(agentType, messages = [], historySessionId, instanceId) {
|
|
32902
|
+
const effectiveHistoryKey = historySessionId || instanceId;
|
|
32903
|
+
const dedupKey = effectiveHistoryKey ? `${agentType}:${effectiveHistoryKey}` : agentType;
|
|
32904
|
+
const seenHashes = /* @__PURE__ */ new Set();
|
|
32905
|
+
for (const raw of messages) {
|
|
32906
|
+
const role = raw?.role;
|
|
32907
|
+
if (role !== "user" && role !== "assistant" && role !== "system") continue;
|
|
32908
|
+
const content = cleanupHistoryContent(agentType, role, raw?.content || "");
|
|
32909
|
+
if (!content) continue;
|
|
32910
|
+
seenHashes.add(buildHistoryMessageHash(agentType, {
|
|
32911
|
+
role,
|
|
32912
|
+
content,
|
|
32913
|
+
receivedAt: raw?.receivedAt || 0,
|
|
32914
|
+
kind: typeof raw?.kind === "string" ? raw.kind : void 0,
|
|
32915
|
+
historyDedupKey: raw?.historyDedupKey
|
|
32916
|
+
}));
|
|
32917
|
+
}
|
|
32918
|
+
this.lastSeenHashes.set(dedupKey, seenHashes);
|
|
32919
|
+
this.lastSeenCounts.set(dedupKey, messages.length);
|
|
32920
|
+
const lastMessage = [...messages].reverse().find((raw) => {
|
|
32921
|
+
const role = raw?.role;
|
|
32922
|
+
if (role !== "user" && role !== "assistant" && role !== "system") return false;
|
|
32923
|
+
return !!cleanupHistoryContent(agentType, role, raw?.content || "");
|
|
32924
|
+
});
|
|
32925
|
+
const lastTurnMessage = [...messages].reverse().find((raw) => {
|
|
32926
|
+
const role = raw?.role;
|
|
32927
|
+
if (role !== "user" && role !== "assistant") return false;
|
|
32928
|
+
return !!cleanupHistoryContent(agentType, role, raw?.content || "");
|
|
32929
|
+
});
|
|
32930
|
+
if (lastMessage) {
|
|
32931
|
+
this.lastSeenSignatures.set(dedupKey, buildHistoryMessageSignature(agentType, {
|
|
32932
|
+
role: lastMessage.role,
|
|
32933
|
+
content: lastMessage.content,
|
|
32934
|
+
kind: typeof lastMessage.kind === "string" ? lastMessage.kind : void 0
|
|
32935
|
+
}));
|
|
32936
|
+
} else {
|
|
32937
|
+
this.lastSeenSignatures.delete(dedupKey);
|
|
32938
|
+
}
|
|
32939
|
+
if (lastTurnMessage) {
|
|
32940
|
+
this.lastSeenTurnSignatures.set(dedupKey, buildHistoryMessageSignature(agentType, {
|
|
32941
|
+
role: lastTurnMessage.role,
|
|
32942
|
+
content: lastTurnMessage.content,
|
|
32943
|
+
kind: typeof lastTurnMessage.kind === "string" ? lastTurnMessage.kind : void 0
|
|
32944
|
+
}));
|
|
32945
|
+
} else {
|
|
32946
|
+
this.lastSeenTurnSignatures.delete(dedupKey);
|
|
32947
|
+
}
|
|
32948
|
+
}
|
|
32760
32949
|
appendSystemMarker(agentType, content, options = {}) {
|
|
32761
32950
|
this.appendNewMessages(
|
|
32762
32951
|
agentType,
|
|
@@ -32787,19 +32976,29 @@ ${data.message || ""}`.trim();
|
|
|
32787
32976
|
this.lastSeenHashes.set(toDedupKey, nextHashes);
|
|
32788
32977
|
this.lastSeenHashes.delete(fromDedupKey);
|
|
32789
32978
|
}
|
|
32979
|
+
const fromSignature = this.lastSeenSignatures.get(fromDedupKey);
|
|
32980
|
+
if (fromSignature) {
|
|
32981
|
+
this.lastSeenSignatures.set(toDedupKey, fromSignature);
|
|
32982
|
+
this.lastSeenSignatures.delete(fromDedupKey);
|
|
32983
|
+
}
|
|
32984
|
+
const fromTurnSignature = this.lastSeenTurnSignatures.get(fromDedupKey);
|
|
32985
|
+
if (fromTurnSignature) {
|
|
32986
|
+
this.lastSeenTurnSignatures.set(toDedupKey, fromTurnSignature);
|
|
32987
|
+
this.lastSeenTurnSignatures.delete(fromDedupKey);
|
|
32988
|
+
}
|
|
32790
32989
|
const fromCount = this.lastSeenCounts.get(fromDedupKey);
|
|
32791
32990
|
if (typeof fromCount === "number") {
|
|
32792
32991
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
32793
32992
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
32794
32993
|
}
|
|
32795
|
-
const dir =
|
|
32994
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
32796
32995
|
if (!fs32.existsSync(dir)) return;
|
|
32797
32996
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
32798
32997
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
32799
32998
|
const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(fromPrefix) && file2.endsWith(".jsonl"));
|
|
32800
32999
|
for (const file2 of files) {
|
|
32801
|
-
const sourcePath =
|
|
32802
|
-
const targetPath =
|
|
33000
|
+
const sourcePath = path7.join(dir, file2);
|
|
33001
|
+
const targetPath = path7.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
|
|
32803
33002
|
const sourceLines = fs32.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
32804
33003
|
const rewritten = sourceLines.map((line) => {
|
|
32805
33004
|
try {
|
|
@@ -32828,10 +33027,61 @@ ${data.message || ""}`.trim();
|
|
|
32828
33027
|
} catch {
|
|
32829
33028
|
}
|
|
32830
33029
|
}
|
|
33030
|
+
compactHistorySession(agentType, historySessionId) {
|
|
33031
|
+
const sessionId = String(historySessionId || "").trim();
|
|
33032
|
+
if (!sessionId) return;
|
|
33033
|
+
try {
|
|
33034
|
+
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
33035
|
+
if (!fs32.existsSync(dir)) return;
|
|
33036
|
+
const prefix = `${this.sanitize(sessionId)}_`;
|
|
33037
|
+
const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(prefix) && file2.endsWith(".jsonl")).sort();
|
|
33038
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33039
|
+
for (const file2 of files) {
|
|
33040
|
+
const filePath = path7.join(dir, file2);
|
|
33041
|
+
const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
33042
|
+
const next = [];
|
|
33043
|
+
for (const line of lines) {
|
|
33044
|
+
let parsed = null;
|
|
33045
|
+
try {
|
|
33046
|
+
parsed = JSON.parse(line);
|
|
33047
|
+
} catch {
|
|
33048
|
+
parsed = null;
|
|
33049
|
+
}
|
|
33050
|
+
if (!parsed || parsed.historySessionId !== sessionId) continue;
|
|
33051
|
+
const sanitized = sanitizeHistoryMessage(agentType, parsed);
|
|
33052
|
+
if (!sanitized) continue;
|
|
33053
|
+
const hash2 = buildHistoryMessageHash(agentType, sanitized);
|
|
33054
|
+
if (seen.has(hash2)) continue;
|
|
33055
|
+
seen.add(hash2);
|
|
33056
|
+
next.push(sanitized);
|
|
33057
|
+
}
|
|
33058
|
+
next.sort((a, b2) => a.receivedAt - b2.receivedAt);
|
|
33059
|
+
const dedupedAdjacent = [];
|
|
33060
|
+
let lastTurn = null;
|
|
33061
|
+
for (const entry of next) {
|
|
33062
|
+
const previous = dedupedAdjacent[dedupedAdjacent.length - 1];
|
|
33063
|
+
if (isAdjacentHistoryDuplicate(agentType, previous, entry)) continue;
|
|
33064
|
+
if (entry.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, entry)) continue;
|
|
33065
|
+
dedupedAdjacent.push(entry);
|
|
33066
|
+
if (entry.role !== "system") lastTurn = entry;
|
|
33067
|
+
}
|
|
33068
|
+
const collapsed = collapseReplayAssistantTurns(agentType, dedupedAdjacent);
|
|
33069
|
+
if (collapsed.length === 0) {
|
|
33070
|
+
fs32.unlinkSync(filePath);
|
|
33071
|
+
continue;
|
|
33072
|
+
}
|
|
33073
|
+
fs32.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
33074
|
+
`, "utf-8");
|
|
33075
|
+
}
|
|
33076
|
+
} catch {
|
|
33077
|
+
}
|
|
33078
|
+
}
|
|
32831
33079
|
/** Called when agent session is explicitly changed */
|
|
32832
33080
|
onSessionChange(agentType) {
|
|
32833
33081
|
this.lastSeenHashes.delete(agentType);
|
|
32834
33082
|
this.lastSeenCounts.delete(agentType);
|
|
33083
|
+
this.lastSeenSignatures.delete(agentType);
|
|
33084
|
+
this.lastSeenTurnSignatures.delete(agentType);
|
|
32835
33085
|
}
|
|
32836
33086
|
/** Delete history files older than 30 days */
|
|
32837
33087
|
async rotateOldFiles() {
|
|
@@ -32840,10 +33090,10 @@ ${data.message || ""}`.trim();
|
|
|
32840
33090
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
32841
33091
|
const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
32842
33092
|
for (const dir of agentDirs) {
|
|
32843
|
-
const dirPath =
|
|
33093
|
+
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
32844
33094
|
const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
32845
33095
|
for (const file2 of files) {
|
|
32846
|
-
const filePath =
|
|
33096
|
+
const filePath = path7.join(dirPath, file2);
|
|
32847
33097
|
const stat4 = fs32.statSync(filePath);
|
|
32848
33098
|
if (stat4.mtimeMs < cutoff) {
|
|
32849
33099
|
fs32.unlinkSync(filePath);
|
|
@@ -32861,7 +33111,7 @@ ${data.message || ""}`.trim();
|
|
|
32861
33111
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
32862
33112
|
try {
|
|
32863
33113
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32864
|
-
const dir =
|
|
33114
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
32865
33115
|
if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
|
|
32866
33116
|
const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32867
33117
|
const files = fs32.readdirSync(dir).filter((f) => {
|
|
@@ -32872,23 +33122,37 @@ ${data.message || ""}`.trim();
|
|
|
32872
33122
|
return true;
|
|
32873
33123
|
}).sort().reverse();
|
|
32874
33124
|
const allMessages = [];
|
|
32875
|
-
const
|
|
33125
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32876
33126
|
for (const file2 of files) {
|
|
32877
|
-
|
|
32878
|
-
const filePath = path52.join(dir, file2);
|
|
33127
|
+
const filePath = path7.join(dir, file2);
|
|
32879
33128
|
const content = fs32.readFileSync(filePath, "utf-8");
|
|
32880
33129
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
32881
|
-
for (let i =
|
|
32882
|
-
if (allMessages.length >= needed) break;
|
|
33130
|
+
for (let i = 0; i < lines.length; i++) {
|
|
32883
33131
|
try {
|
|
32884
|
-
|
|
33132
|
+
const parsed = JSON.parse(lines[i]);
|
|
33133
|
+
const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
|
|
33134
|
+
if (!sanitizedMessage) continue;
|
|
33135
|
+
const hash2 = buildHistoryMessageHash(agentType, sanitizedMessage);
|
|
33136
|
+
if (seen.has(hash2)) continue;
|
|
33137
|
+
seen.add(hash2);
|
|
33138
|
+
allMessages.push(sanitizedMessage);
|
|
32885
33139
|
} catch {
|
|
32886
33140
|
}
|
|
32887
33141
|
}
|
|
32888
33142
|
}
|
|
32889
|
-
|
|
32890
|
-
const
|
|
32891
|
-
|
|
33143
|
+
allMessages.sort((a, b2) => a.receivedAt - b2.receivedAt);
|
|
33144
|
+
const chronological = [];
|
|
33145
|
+
let lastTurn = null;
|
|
33146
|
+
for (const message of allMessages) {
|
|
33147
|
+
const previous = chronological[chronological.length - 1];
|
|
33148
|
+
if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
|
|
33149
|
+
if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
|
|
33150
|
+
chronological.push(message);
|
|
33151
|
+
if (message.role !== "system") lastTurn = message;
|
|
33152
|
+
}
|
|
33153
|
+
const collapsed = collapseReplayAssistantTurns(agentType, chronological);
|
|
33154
|
+
const sliced = collapsed.slice(offset, offset + limit);
|
|
33155
|
+
const hasMore = collapsed.length > offset + limit;
|
|
32892
33156
|
return { messages: sliced, hasMore };
|
|
32893
33157
|
} catch {
|
|
32894
33158
|
return { messages: [], hasMore: false };
|
|
@@ -32897,7 +33161,7 @@ ${data.message || ""}`.trim();
|
|
|
32897
33161
|
function listSavedHistorySessions(agentType, options = {}) {
|
|
32898
33162
|
try {
|
|
32899
33163
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32900
|
-
const dir =
|
|
33164
|
+
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
32901
33165
|
if (!fs32.existsSync(dir)) return { sessions: [], hasMore: false };
|
|
32902
33166
|
const groupedFiles = /* @__PURE__ */ new Map();
|
|
32903
33167
|
const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
@@ -32918,7 +33182,7 @@ ${data.message || ""}`.trim();
|
|
|
32918
33182
|
let sessionTitle = "";
|
|
32919
33183
|
let preview = "";
|
|
32920
33184
|
for (const file2 of files.sort()) {
|
|
32921
|
-
const filePath =
|
|
33185
|
+
const filePath = path7.join(dir, file2);
|
|
32922
33186
|
const content = fs32.readFileSync(filePath, "utf-8");
|
|
32923
33187
|
const lines = content.split("\n").filter(Boolean);
|
|
32924
33188
|
for (const line of lines) {
|
|
@@ -34722,6 +34986,46 @@ ${effect.notification.body || ""}`.trim();
|
|
|
34722
34986
|
if (!parsed || typeof parsed !== "object") return false;
|
|
34723
34987
|
return parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true;
|
|
34724
34988
|
}
|
|
34989
|
+
async function readExtensionChatState(h) {
|
|
34990
|
+
try {
|
|
34991
|
+
const evalResult = await h.evaluateProviderScript("readChat", void 0, 5e4);
|
|
34992
|
+
if (!evalResult?.result) return null;
|
|
34993
|
+
const parsed = parseMaybeJson(evalResult.result);
|
|
34994
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
34995
|
+
} catch {
|
|
34996
|
+
return null;
|
|
34997
|
+
}
|
|
34998
|
+
}
|
|
34999
|
+
function getStateMessageCount(state) {
|
|
35000
|
+
return Array.isArray(state?.messages) ? state.messages.length : 0;
|
|
35001
|
+
}
|
|
35002
|
+
function getStateLastSignature(state) {
|
|
35003
|
+
const messages = Array.isArray(state?.messages) ? state.messages : [];
|
|
35004
|
+
const last = messages[messages.length - 1];
|
|
35005
|
+
if (!last) return "";
|
|
35006
|
+
return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
|
|
35007
|
+
}
|
|
35008
|
+
async function getStableExtensionBaseline(h) {
|
|
35009
|
+
const first = await readExtensionChatState(h);
|
|
35010
|
+
if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
|
|
35011
|
+
await new Promise((resolve12) => setTimeout(resolve12, 150));
|
|
35012
|
+
const second = await readExtensionChatState(h);
|
|
35013
|
+
return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
|
|
35014
|
+
}
|
|
35015
|
+
async function verifyExtensionSendObserved(h, before) {
|
|
35016
|
+
const beforeCount = getStateMessageCount(before);
|
|
35017
|
+
const beforeSignature = getStateLastSignature(before);
|
|
35018
|
+
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
35019
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
35020
|
+
const state = await readExtensionChatState(h);
|
|
35021
|
+
if (state?.status === "waiting_approval") return true;
|
|
35022
|
+
const afterCount = getStateMessageCount(state);
|
|
35023
|
+
const afterSignature = getStateLastSignature(state);
|
|
35024
|
+
if (afterCount > beforeCount) return true;
|
|
35025
|
+
if (afterSignature && afterSignature !== beforeSignature) return true;
|
|
35026
|
+
}
|
|
35027
|
+
return false;
|
|
35028
|
+
}
|
|
34725
35029
|
async function handleChatHistory(h, args) {
|
|
34726
35030
|
const { agentType, offset, limit } = args;
|
|
34727
35031
|
const historySessionId = getHistorySessionId(h, args);
|
|
@@ -34902,12 +35206,17 @@ ${effect.notification.body || ""}`.trim();
|
|
|
34902
35206
|
if (isExtensionTransport(transport)) {
|
|
34903
35207
|
_log(`Extension: ${provider?.type || "unknown_extension"}`);
|
|
34904
35208
|
try {
|
|
35209
|
+
const beforeState = await getStableExtensionBaseline(h);
|
|
34905
35210
|
const evalResult = await h.evaluateProviderScript("sendMessage", { message: text }, 3e4);
|
|
34906
35211
|
if (evalResult?.result) {
|
|
34907
35212
|
const parsed = parseMaybeJson(evalResult.result);
|
|
34908
35213
|
if (didProviderConfirmSend(parsed)) {
|
|
34909
|
-
|
|
34910
|
-
|
|
35214
|
+
const observed = await verifyExtensionSendObserved(h, beforeState);
|
|
35215
|
+
if (observed) {
|
|
35216
|
+
_log(`Extension script sent OK`);
|
|
35217
|
+
return _logSendSuccess("extension-script");
|
|
35218
|
+
}
|
|
35219
|
+
_log(`Extension script reported send but no chat-state change was observed`);
|
|
34911
35220
|
}
|
|
34912
35221
|
if (parsed?.needsTypeAndSend) {
|
|
34913
35222
|
_log(`Extension needsTypeAndSend \u2192 AgentStreamManager`);
|
|
@@ -35073,6 +35382,14 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35073
35382
|
} catch {
|
|
35074
35383
|
}
|
|
35075
35384
|
}
|
|
35385
|
+
if (parsed?.sessions && Array.isArray(parsed.sessions)) {
|
|
35386
|
+
LOG2.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
|
|
35387
|
+
return { success: true, chats: parsed.sessions };
|
|
35388
|
+
}
|
|
35389
|
+
if (parsed?.chats && Array.isArray(parsed.chats)) {
|
|
35390
|
+
LOG2.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
|
|
35391
|
+
return { success: true, chats: parsed.chats };
|
|
35392
|
+
}
|
|
35076
35393
|
if (Array.isArray(parsed)) {
|
|
35077
35394
|
LOG2.info("Command", `[list_chats] OK: ${parsed.length} chats`);
|
|
35078
35395
|
return { success: true, chats: parsed };
|
|
@@ -35142,7 +35459,13 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35142
35459
|
} catch (e) {
|
|
35143
35460
|
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
35144
35461
|
}
|
|
35145
|
-
const
|
|
35462
|
+
const switchParams = {
|
|
35463
|
+
sessionId,
|
|
35464
|
+
title: sessionId,
|
|
35465
|
+
id: sessionId,
|
|
35466
|
+
SESSION_ID: JSON.stringify(sessionId)
|
|
35467
|
+
};
|
|
35468
|
+
const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
|
|
35146
35469
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
35147
35470
|
try {
|
|
35148
35471
|
const raw = await cdp.evaluate(script, 15e3);
|
|
@@ -35221,8 +35544,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35221
35544
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
35222
35545
|
if (adapter) {
|
|
35223
35546
|
const acpInstance = adapter._acpInstance;
|
|
35224
|
-
if (acpInstance && typeof acpInstance.
|
|
35225
|
-
acpInstance.
|
|
35547
|
+
if (acpInstance && typeof acpInstance.setMode === "function") {
|
|
35548
|
+
await acpInstance.setMode(mode);
|
|
35226
35549
|
return { success: true, mode };
|
|
35227
35550
|
}
|
|
35228
35551
|
}
|
|
@@ -35279,9 +35602,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35279
35602
|
LOG2.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
35280
35603
|
if (adapter) {
|
|
35281
35604
|
const acpInstance = adapter._acpInstance;
|
|
35282
|
-
if (acpInstance && typeof acpInstance.
|
|
35283
|
-
acpInstance.
|
|
35284
|
-
LOG2.info("Command", `[change_model]
|
|
35605
|
+
if (acpInstance && typeof acpInstance.setConfigOption === "function") {
|
|
35606
|
+
await acpInstance.setConfigOption("model", model);
|
|
35607
|
+
LOG2.info("Command", `[change_model] Updated ACP model to ${model}`);
|
|
35285
35608
|
return { success: true, model };
|
|
35286
35609
|
}
|
|
35287
35610
|
}
|
|
@@ -35398,9 +35721,21 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35398
35721
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
35399
35722
|
}
|
|
35400
35723
|
if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
35401
|
-
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
|
|
35724
|
+
const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action, button);
|
|
35402
35725
|
return { success: ok };
|
|
35403
35726
|
}
|
|
35727
|
+
if (transport === "acp") {
|
|
35728
|
+
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
35729
|
+
const acpInstance = adapter?._acpInstance;
|
|
35730
|
+
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
35731
|
+
try {
|
|
35732
|
+
await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
|
|
35733
|
+
LOG2.info("Command", `[resolveAction] ACP \u2192 ${action}`);
|
|
35734
|
+
return { success: true, action };
|
|
35735
|
+
} catch (e) {
|
|
35736
|
+
return { success: false, error: e?.message || "ACP resolve action failed" };
|
|
35737
|
+
}
|
|
35738
|
+
}
|
|
35404
35739
|
if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
|
|
35405
35740
|
const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
35406
35741
|
if (script) {
|
|
@@ -35477,7 +35812,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35477
35812
|
return { success: false, error: "resolveAction script not available for this provider" };
|
|
35478
35813
|
}
|
|
35479
35814
|
var fs42 = __toESM2(require("fs"));
|
|
35480
|
-
var
|
|
35815
|
+
var path8 = __toESM2(require("path"));
|
|
35481
35816
|
var os62 = __toESM2(require("os"));
|
|
35482
35817
|
var KEY_TO_VK = {
|
|
35483
35818
|
Backspace: 8,
|
|
@@ -35729,25 +36064,25 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35729
36064
|
const inputPath = rawPath || ".";
|
|
35730
36065
|
const home = os62.homedir();
|
|
35731
36066
|
if (inputPath.startsWith("~")) {
|
|
35732
|
-
return
|
|
36067
|
+
return path8.resolve(path8.join(home, inputPath.slice(1)));
|
|
35733
36068
|
}
|
|
35734
36069
|
if (process.platform === "win32") {
|
|
35735
36070
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
35736
|
-
if (
|
|
35737
|
-
return
|
|
36071
|
+
if (path8.win32.isAbsolute(normalized)) {
|
|
36072
|
+
return path8.win32.normalize(normalized);
|
|
35738
36073
|
}
|
|
35739
|
-
return
|
|
36074
|
+
return path8.win32.resolve(normalized);
|
|
35740
36075
|
}
|
|
35741
|
-
if (
|
|
35742
|
-
return
|
|
36076
|
+
if (path8.isAbsolute(inputPath)) {
|
|
36077
|
+
return path8.normalize(inputPath);
|
|
35743
36078
|
}
|
|
35744
|
-
return
|
|
36079
|
+
return path8.resolve(inputPath);
|
|
35745
36080
|
}
|
|
35746
36081
|
function listDirectoryEntriesSafe(dirPath) {
|
|
35747
36082
|
const entries = fs42.readdirSync(dirPath, { withFileTypes: true });
|
|
35748
36083
|
const files = [];
|
|
35749
36084
|
for (const entry of entries) {
|
|
35750
|
-
const entryPath =
|
|
36085
|
+
const entryPath = path8.join(dirPath, entry.name);
|
|
35751
36086
|
try {
|
|
35752
36087
|
if (entry.isDirectory()) {
|
|
35753
36088
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -35786,7 +36121,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35786
36121
|
async function handleFileWrite(h, args) {
|
|
35787
36122
|
try {
|
|
35788
36123
|
const filePath = resolveSafePath(args?.path);
|
|
35789
|
-
fs42.mkdirSync(
|
|
36124
|
+
fs42.mkdirSync(path8.dirname(filePath), { recursive: true });
|
|
35790
36125
|
fs42.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
35791
36126
|
return { success: true, path: filePath };
|
|
35792
36127
|
} catch (e) {
|
|
@@ -35872,7 +36207,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35872
36207
|
}
|
|
35873
36208
|
return { success: true, settings: allSettings, values: allValues };
|
|
35874
36209
|
}
|
|
35875
|
-
function handleSetProviderSetting(h, args) {
|
|
36210
|
+
async function handleSetProviderSetting(h, args) {
|
|
35876
36211
|
const loader = h.ctx.providerLoader;
|
|
35877
36212
|
const { providerType, key, value } = args || {};
|
|
35878
36213
|
if (!providerType || !key || value === void 0) {
|
|
@@ -35885,6 +36220,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35885
36220
|
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
35886
36221
|
LOG2.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
|
|
35887
36222
|
}
|
|
36223
|
+
await h.ctx.onProviderSettingChanged?.(providerType, key, value);
|
|
35888
36224
|
return { success: true, providerType, key, value };
|
|
35889
36225
|
}
|
|
35890
36226
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
@@ -35922,10 +36258,10 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35922
36258
|
}
|
|
35923
36259
|
const command = payload.command;
|
|
35924
36260
|
if (!command || typeof command !== "object") return null;
|
|
35925
|
-
if (command.type !== "send_message") return null;
|
|
36261
|
+
if (command.type !== "send_message" && command.type !== "pty_write") return null;
|
|
35926
36262
|
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
35927
36263
|
if (!text) return null;
|
|
35928
|
-
return { type:
|
|
36264
|
+
return { type: command.type, text };
|
|
35929
36265
|
}
|
|
35930
36266
|
function applyProviderPatch(h, args, payload) {
|
|
35931
36267
|
if (!payload || typeof payload !== "object") return;
|
|
@@ -35966,6 +36302,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
35966
36302
|
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
35967
36303
|
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
35968
36304
|
await adapter.sendMessage(cliCommand.text);
|
|
36305
|
+
} else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
|
|
36306
|
+
adapter.writeRaw(cliCommand.text + "\r");
|
|
35969
36307
|
}
|
|
35970
36308
|
applyProviderPatch(h, args, parsed.payload);
|
|
35971
36309
|
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
@@ -36640,7 +36978,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36640
36978
|
try {
|
|
36641
36979
|
const http3 = await import("http");
|
|
36642
36980
|
const postData = JSON.stringify(body);
|
|
36643
|
-
const result = await new Promise((
|
|
36981
|
+
const result = await new Promise((resolve12, reject) => {
|
|
36644
36982
|
const req = http3.request({
|
|
36645
36983
|
hostname: "127.0.0.1",
|
|
36646
36984
|
port: 19280,
|
|
@@ -36652,9 +36990,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36652
36990
|
res.on("data", (chunk) => data += chunk);
|
|
36653
36991
|
res.on("end", () => {
|
|
36654
36992
|
try {
|
|
36655
|
-
|
|
36993
|
+
resolve12(JSON.parse(data));
|
|
36656
36994
|
} catch {
|
|
36657
|
-
|
|
36995
|
+
resolve12({ raw: data });
|
|
36658
36996
|
}
|
|
36659
36997
|
});
|
|
36660
36998
|
});
|
|
@@ -36672,15 +37010,15 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36672
37010
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
36673
37011
|
try {
|
|
36674
37012
|
const http3 = await import("http");
|
|
36675
|
-
const result = await new Promise((
|
|
37013
|
+
const result = await new Promise((resolve12, reject) => {
|
|
36676
37014
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
36677
37015
|
let data = "";
|
|
36678
37016
|
res.on("data", (chunk) => data += chunk);
|
|
36679
37017
|
res.on("end", () => {
|
|
36680
37018
|
try {
|
|
36681
|
-
|
|
37019
|
+
resolve12(JSON.parse(data));
|
|
36682
37020
|
} catch {
|
|
36683
|
-
|
|
37021
|
+
resolve12({ raw: data });
|
|
36684
37022
|
}
|
|
36685
37023
|
});
|
|
36686
37024
|
}).on("error", reject);
|
|
@@ -36694,7 +37032,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36694
37032
|
try {
|
|
36695
37033
|
const http3 = await import("http");
|
|
36696
37034
|
const postData = JSON.stringify(args || {});
|
|
36697
|
-
const result = await new Promise((
|
|
37035
|
+
const result = await new Promise((resolve12, reject) => {
|
|
36698
37036
|
const req = http3.request({
|
|
36699
37037
|
hostname: "127.0.0.1",
|
|
36700
37038
|
port: 19280,
|
|
@@ -36706,9 +37044,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36706
37044
|
res.on("data", (chunk) => data += chunk);
|
|
36707
37045
|
res.on("end", () => {
|
|
36708
37046
|
try {
|
|
36709
|
-
|
|
37047
|
+
resolve12(JSON.parse(data));
|
|
36710
37048
|
} catch {
|
|
36711
|
-
|
|
37049
|
+
resolve12({ raw: data });
|
|
36712
37050
|
}
|
|
36713
37051
|
});
|
|
36714
37052
|
});
|
|
@@ -36723,13 +37061,13 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36723
37061
|
}
|
|
36724
37062
|
};
|
|
36725
37063
|
var os10 = __toESM2(require("os"));
|
|
36726
|
-
var
|
|
37064
|
+
var path11 = __toESM2(require("path"));
|
|
36727
37065
|
var crypto4 = __toESM2(require("crypto"));
|
|
36728
37066
|
var import_chalk = __toESM2(require("chalk"));
|
|
36729
37067
|
init_provider_cli_adapter();
|
|
36730
37068
|
init_config();
|
|
36731
37069
|
var os9 = __toESM2(require("os"));
|
|
36732
|
-
var
|
|
37070
|
+
var path10 = __toESM2(require("path"));
|
|
36733
37071
|
var crypto3 = __toESM2(require("crypto"));
|
|
36734
37072
|
var fs5 = __toESM2(require("fs"));
|
|
36735
37073
|
var import_node_module = require("module");
|
|
@@ -36738,7 +37076,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36738
37076
|
var CachedDatabaseSync = null;
|
|
36739
37077
|
function getDatabaseSync() {
|
|
36740
37078
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
36741
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
37079
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
36742
37080
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
36743
37081
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
36744
37082
|
if (!CachedDatabaseSync) {
|
|
@@ -36778,6 +37116,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36778
37116
|
historyWriter;
|
|
36779
37117
|
runtimeMessages = [];
|
|
36780
37118
|
instanceId;
|
|
37119
|
+
suppressIdleHistoryReplay = false;
|
|
36781
37120
|
presentationMode;
|
|
36782
37121
|
providerSessionId;
|
|
36783
37122
|
launchMode;
|
|
@@ -36805,7 +37144,15 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36805
37144
|
await this.adapter.spawn();
|
|
36806
37145
|
this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
|
|
36807
37146
|
if (this.providerSessionId) {
|
|
37147
|
+
this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
|
|
36808
37148
|
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
37149
|
+
this.historyWriter.seedSessionHistory(
|
|
37150
|
+
this.type,
|
|
37151
|
+
restoredHistory.messages,
|
|
37152
|
+
this.providerSessionId,
|
|
37153
|
+
this.instanceId
|
|
37154
|
+
);
|
|
37155
|
+
this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
|
|
36809
37156
|
if (restoredHistory.messages.length > 0) {
|
|
36810
37157
|
this.adapter.seedCommittedMessages(
|
|
36811
37158
|
restoredHistory.messages.map((message) => ({
|
|
@@ -36849,7 +37196,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36849
37196
|
} else if (this.type === "codex-cli") {
|
|
36850
37197
|
probedSessionId = this.probeSessionIdFromConfig({
|
|
36851
37198
|
dbPath: "~/.codex/state_5.sqlite",
|
|
36852
|
-
query: "select id from threads where cwd in ({dirs}) and
|
|
37199
|
+
query: "select id from threads where cwd in ({dirs}) and updated_at >= ? and archived = 0 order by updated_at desc limit 1",
|
|
36853
37200
|
timestampFormat: "unix_s"
|
|
36854
37201
|
});
|
|
36855
37202
|
} else if (this.type === "goose-cli") {
|
|
@@ -36909,6 +37256,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36909
37256
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
36910
37257
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
36911
37258
|
if (parsedMessages.length > 0) {
|
|
37259
|
+
const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
|
|
36912
37260
|
let messagesToSave = parsedMessages;
|
|
36913
37261
|
if (parsedStatus?.status === "generating" || parsedStatus?.status === "long_generating") {
|
|
36914
37262
|
const lastIdx = messagesToSave.length - 1;
|
|
@@ -36916,7 +37264,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36916
37264
|
messagesToSave = messagesToSave.slice(0, lastIdx);
|
|
36917
37265
|
}
|
|
36918
37266
|
}
|
|
36919
|
-
if (messagesToSave.length > 0) {
|
|
37267
|
+
if (!shouldSkipReplayPersist && messagesToSave.length > 0) {
|
|
36920
37268
|
this.historyWriter.appendNewMessages(
|
|
36921
37269
|
this.type,
|
|
36922
37270
|
messagesToSave,
|
|
@@ -37011,6 +37359,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37011
37359
|
if (newStatus !== this.lastStatus) {
|
|
37012
37360
|
LOG2.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
37013
37361
|
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
37362
|
+
this.suppressIdleHistoryReplay = false;
|
|
37014
37363
|
if (this.completedDebouncePending) {
|
|
37015
37364
|
LOG2.info("CLI", `[${this.type}] cancelled pending completed (resumed generating)`);
|
|
37016
37365
|
if (this.completedDebounceTimer) {
|
|
@@ -37030,6 +37379,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37030
37379
|
this.generatingDebounceTimer = null;
|
|
37031
37380
|
}, 1e3);
|
|
37032
37381
|
} else if (newStatus === "waiting_approval") {
|
|
37382
|
+
this.suppressIdleHistoryReplay = false;
|
|
37033
37383
|
if (this.generatingDebouncePending) {
|
|
37034
37384
|
if (this.generatingDebounceTimer) {
|
|
37035
37385
|
clearTimeout(this.generatingDebounceTimer);
|
|
@@ -37561,8 +37911,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37561
37911
|
async setConfigOption(category, value) {
|
|
37562
37912
|
const opt = this.configOptions.find((c) => c.category === category);
|
|
37563
37913
|
if (!opt) {
|
|
37564
|
-
|
|
37565
|
-
|
|
37914
|
+
const message = `[${this.type}] No config option for category: ${category}`;
|
|
37915
|
+
this.log.warn(message);
|
|
37916
|
+
throw new Error(message);
|
|
37566
37917
|
}
|
|
37567
37918
|
if (this.useStaticConfig) {
|
|
37568
37919
|
opt.currentValue = value;
|
|
@@ -37574,8 +37925,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37574
37925
|
return;
|
|
37575
37926
|
}
|
|
37576
37927
|
if (!this.connection || !this.sessionId) {
|
|
37577
|
-
|
|
37578
|
-
|
|
37928
|
+
const message = `[${this.type}] Cannot set config: no active connection/session`;
|
|
37929
|
+
this.log.warn(message);
|
|
37930
|
+
throw new Error(message);
|
|
37579
37931
|
}
|
|
37580
37932
|
try {
|
|
37581
37933
|
this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
|
|
@@ -37589,7 +37941,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37589
37941
|
if (result?.configOptions) this.parseConfigOptions(result.configOptions);
|
|
37590
37942
|
this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
|
|
37591
37943
|
} catch (e) {
|
|
37592
|
-
|
|
37944
|
+
const message = e?.message || "Unknown ACP config error";
|
|
37945
|
+
this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
|
|
37946
|
+
throw new Error(message);
|
|
37593
37947
|
}
|
|
37594
37948
|
}
|
|
37595
37949
|
async setMode(modeId) {
|
|
@@ -37605,8 +37959,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37605
37959
|
return;
|
|
37606
37960
|
}
|
|
37607
37961
|
if (!this.connection || !this.sessionId) {
|
|
37608
|
-
|
|
37609
|
-
|
|
37962
|
+
const message = `[${this.type}] Cannot set mode: no active connection/session`;
|
|
37963
|
+
this.log.warn(message);
|
|
37964
|
+
throw new Error(message);
|
|
37610
37965
|
}
|
|
37611
37966
|
try {
|
|
37612
37967
|
await this.connection.setSessionMode({
|
|
@@ -37616,7 +37971,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37616
37971
|
this.currentMode = modeId;
|
|
37617
37972
|
this.log.info(`[${this.type}] Mode set to: ${modeId}`);
|
|
37618
37973
|
} catch (e) {
|
|
37619
|
-
|
|
37974
|
+
const message = e?.message || "Unknown ACP mode error";
|
|
37975
|
+
this.log.warn(`[${this.type}] set_mode failed: ${message}`);
|
|
37976
|
+
throw new Error(message);
|
|
37620
37977
|
}
|
|
37621
37978
|
}
|
|
37622
37979
|
/** Static config: kill process and restart with new args */
|
|
@@ -37664,7 +38021,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37664
38021
|
if (!spawnConfig) {
|
|
37665
38022
|
throw new Error(`[ACP:${this.type}] No spawn config defined`);
|
|
37666
38023
|
}
|
|
37667
|
-
const command = spawnConfig.command;
|
|
38024
|
+
const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
|
|
37668
38025
|
let baseArgs = spawnConfig.args || [];
|
|
37669
38026
|
if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
|
|
37670
38027
|
baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
|
|
@@ -37780,13 +38137,13 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37780
38137
|
}
|
|
37781
38138
|
this.currentStatus = "waiting_approval";
|
|
37782
38139
|
this.detectStatusTransition();
|
|
37783
|
-
const approved = await new Promise((
|
|
37784
|
-
this.permissionResolvers.push(
|
|
38140
|
+
const approved = await new Promise((resolve12) => {
|
|
38141
|
+
this.permissionResolvers.push(resolve12);
|
|
37785
38142
|
setTimeout(() => {
|
|
37786
|
-
const idx = this.permissionResolvers.indexOf(
|
|
38143
|
+
const idx = this.permissionResolvers.indexOf(resolve12);
|
|
37787
38144
|
if (idx >= 0) {
|
|
37788
38145
|
this.permissionResolvers.splice(idx, 1);
|
|
37789
|
-
|
|
38146
|
+
resolve12(false);
|
|
37790
38147
|
}
|
|
37791
38148
|
}, 3e5);
|
|
37792
38149
|
});
|
|
@@ -38491,7 +38848,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
38491
38848
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
38492
38849
|
const trimmed = (workingDir || "").trim();
|
|
38493
38850
|
if (!trimmed) throw new Error("working directory required");
|
|
38494
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) :
|
|
38851
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
|
|
38495
38852
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
38496
38853
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
38497
38854
|
const key = crypto4.randomUUID();
|
|
@@ -38578,10 +38935,10 @@ ${installInfo}`
|
|
|
38578
38935
|
if (!cliInfo) {
|
|
38579
38936
|
const installHint = provider?.install || "";
|
|
38580
38937
|
const displayName = provider?.displayName || provider?.name || cliType;
|
|
38581
|
-
const spawnCmd = provider?.spawn?.command || cliType;
|
|
38938
|
+
const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
|
|
38582
38939
|
throw new Error(
|
|
38583
38940
|
`${displayName} is not installed.
|
|
38584
|
-
Command '${spawnCmd}' not
|
|
38941
|
+
Command '${spawnCmd}' is not available.
|
|
38585
38942
|
` + (installHint ? `
|
|
38586
38943
|
${installHint}
|
|
38587
38944
|
` : "") + `
|
|
@@ -38727,6 +39084,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38727
39084
|
if (!instanceManager) return 0;
|
|
38728
39085
|
const sessions = records || await this.deps.listHostedCliRuntimes?.() || [];
|
|
38729
39086
|
let restored = 0;
|
|
39087
|
+
const restoredBindings = /* @__PURE__ */ new Set();
|
|
38730
39088
|
for (const record2 of sessions) {
|
|
38731
39089
|
if (!record2?.runtimeId || !record2?.cliType || !record2?.workspace) continue;
|
|
38732
39090
|
if (this.adapters.has(record2.runtimeId) || instanceManager.getInstance(record2.runtimeId)) continue;
|
|
@@ -38740,6 +39098,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38740
39098
|
record2.cliArgs,
|
|
38741
39099
|
record2.providerSessionId
|
|
38742
39100
|
);
|
|
39101
|
+
const bindingKey = [
|
|
39102
|
+
normalizedType,
|
|
39103
|
+
record2.workspace,
|
|
39104
|
+
sessionBinding.providerSessionId || record2.runtimeId
|
|
39105
|
+
].join("::");
|
|
39106
|
+
if (restoredBindings.has(bindingKey)) {
|
|
39107
|
+
LOG2.info(
|
|
39108
|
+
"CLI",
|
|
39109
|
+
`\u21B7 Skipping duplicate hosted runtime restore: ${record2.runtimeKey || record2.runtimeId} (${normalizedType} @ ${record2.workspace}) binding=${sessionBinding.providerSessionId || "runtime"}`
|
|
39110
|
+
);
|
|
39111
|
+
continue;
|
|
39112
|
+
}
|
|
38743
39113
|
try {
|
|
38744
39114
|
await this.registerCliInstance(
|
|
38745
39115
|
record2.runtimeId,
|
|
@@ -38755,6 +39125,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38755
39125
|
launchMode: "manual"
|
|
38756
39126
|
}
|
|
38757
39127
|
);
|
|
39128
|
+
restoredBindings.add(bindingKey);
|
|
38758
39129
|
restored += 1;
|
|
38759
39130
|
LOG2.info("CLI", `\u267B Restored hosted runtime: ${record2.runtimeKey || record2.runtimeId} (${record2.displayName || record2.workspace})`);
|
|
38760
39131
|
} catch (error48) {
|
|
@@ -38939,14 +39310,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38939
39310
|
var import_child_process6 = require("child_process");
|
|
38940
39311
|
var net3 = __toESM2(require("net"));
|
|
38941
39312
|
var os12 = __toESM2(require("os"));
|
|
38942
|
-
var
|
|
39313
|
+
var path13 = __toESM2(require("path"));
|
|
38943
39314
|
var fs6 = __toESM2(require("fs"));
|
|
38944
|
-
var
|
|
39315
|
+
var path12 = __toESM2(require("path"));
|
|
38945
39316
|
var os11 = __toESM2(require("os"));
|
|
38946
39317
|
var chokidar = __toESM2((init_chokidar(), __toCommonJS(chokidar_exports)));
|
|
38947
39318
|
init_logger();
|
|
38948
39319
|
var ProviderLoader = class _ProviderLoader {
|
|
38949
39320
|
providers = /* @__PURE__ */ new Map();
|
|
39321
|
+
providerAvailability = /* @__PURE__ */ new Map();
|
|
38950
39322
|
userDir;
|
|
38951
39323
|
upstreamDir;
|
|
38952
39324
|
disableUpstream;
|
|
@@ -38962,12 +39334,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38962
39334
|
static META_FILE = ".meta.json";
|
|
38963
39335
|
constructor(options) {
|
|
38964
39336
|
this.logFn = options?.logFn || LOG2.forComponent("Provider").asLogFn();
|
|
38965
|
-
const defaultProvidersDir =
|
|
39337
|
+
const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
|
|
38966
39338
|
if (options?.userDir) {
|
|
38967
39339
|
this.userDir = options.userDir;
|
|
38968
39340
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
38969
39341
|
} else {
|
|
38970
|
-
const localRepoPath =
|
|
39342
|
+
const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
|
|
38971
39343
|
if (fs6.existsSync(localRepoPath)) {
|
|
38972
39344
|
this.userDir = localRepoPath;
|
|
38973
39345
|
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
@@ -38976,7 +39348,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38976
39348
|
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
38977
39349
|
}
|
|
38978
39350
|
}
|
|
38979
|
-
this.upstreamDir =
|
|
39351
|
+
this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
|
|
38980
39352
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
38981
39353
|
}
|
|
38982
39354
|
log(msg) {
|
|
@@ -39006,7 +39378,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39006
39378
|
* Canonical provider directory shape for a given root.
|
|
39007
39379
|
*/
|
|
39008
39380
|
getProviderDir(root, category, type) {
|
|
39009
|
-
return
|
|
39381
|
+
return path12.join(root, category, type);
|
|
39010
39382
|
}
|
|
39011
39383
|
/**
|
|
39012
39384
|
* Canonical user override directory for a provider.
|
|
@@ -39033,7 +39405,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39033
39405
|
resolveProviderFile(type, ...segments) {
|
|
39034
39406
|
const dir = this.findProviderDirInternal(type);
|
|
39035
39407
|
if (!dir) return null;
|
|
39036
|
-
return
|
|
39408
|
+
return path12.join(dir, ...segments);
|
|
39037
39409
|
}
|
|
39038
39410
|
/**
|
|
39039
39411
|
* Load all providers (3-tier priority)
|
|
@@ -39044,6 +39416,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39044
39416
|
*/
|
|
39045
39417
|
loadAll() {
|
|
39046
39418
|
this.providers.clear();
|
|
39419
|
+
this.providerAvailability.clear();
|
|
39047
39420
|
let upstreamCount = 0;
|
|
39048
39421
|
if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
|
|
39049
39422
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
@@ -39071,7 +39444,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39071
39444
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
39072
39445
|
try {
|
|
39073
39446
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
39074
|
-
(d) => fs6.statSync(
|
|
39447
|
+
(d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
|
|
39075
39448
|
);
|
|
39076
39449
|
} catch {
|
|
39077
39450
|
return false;
|
|
@@ -39114,11 +39487,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39114
39487
|
if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
|
|
39115
39488
|
const verCmdConfig = p.versionCommand;
|
|
39116
39489
|
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
|
|
39490
|
+
const command = this.getSpawnCommand(p.type, p.spawn.command);
|
|
39117
39491
|
result.push({
|
|
39118
39492
|
id: p.type,
|
|
39119
39493
|
displayName: p.displayName || p.name,
|
|
39120
39494
|
icon: p.icon || "\u{1F527}",
|
|
39121
|
-
command
|
|
39495
|
+
command,
|
|
39122
39496
|
category: p.category,
|
|
39123
39497
|
...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
|
|
39124
39498
|
});
|
|
@@ -39247,6 +39621,71 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39247
39621
|
getAvailableIdeTypes() {
|
|
39248
39622
|
return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
|
|
39249
39623
|
}
|
|
39624
|
+
getSpawnCommand(type, fallback) {
|
|
39625
|
+
const override = this.getOptionalStringSetting(type, "executablePath");
|
|
39626
|
+
if (override) return override;
|
|
39627
|
+
return fallback || this.providers.get(type)?.spawn?.command || type;
|
|
39628
|
+
}
|
|
39629
|
+
getIdeCliCommand(type, fallback) {
|
|
39630
|
+
const override = this.getOptionalStringSetting(type, "cliPathOverride");
|
|
39631
|
+
if (override) return override;
|
|
39632
|
+
return fallback || this.providers.get(type)?.cli || null;
|
|
39633
|
+
}
|
|
39634
|
+
getIdePathCandidates(type, fallback) {
|
|
39635
|
+
const override = this.getOptionalStringSetting(type, "appPathOverride");
|
|
39636
|
+
if (override) return [override];
|
|
39637
|
+
if (fallback && fallback.length > 0) return fallback;
|
|
39638
|
+
const osPaths = this.providers.get(type)?.paths?.[process.platform];
|
|
39639
|
+
return Array.isArray(osPaths) ? [...osPaths] : [];
|
|
39640
|
+
}
|
|
39641
|
+
setProviderAvailability(type, state) {
|
|
39642
|
+
this.providerAvailability.set(type, {
|
|
39643
|
+
installed: !!state.installed,
|
|
39644
|
+
detectedPath: state.detectedPath ?? null
|
|
39645
|
+
});
|
|
39646
|
+
}
|
|
39647
|
+
setCliDetectionResults(results, replace = true) {
|
|
39648
|
+
if (replace) {
|
|
39649
|
+
for (const provider of this.providers.values()) {
|
|
39650
|
+
if (provider.category === "cli" || provider.category === "acp") {
|
|
39651
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
39652
|
+
}
|
|
39653
|
+
}
|
|
39654
|
+
}
|
|
39655
|
+
for (const result of results) {
|
|
39656
|
+
this.setProviderAvailability(result.id, {
|
|
39657
|
+
installed: !!result.installed,
|
|
39658
|
+
detectedPath: result.path || null
|
|
39659
|
+
});
|
|
39660
|
+
}
|
|
39661
|
+
}
|
|
39662
|
+
setIdeDetectionResults(results, replace = true) {
|
|
39663
|
+
if (replace) {
|
|
39664
|
+
for (const provider of this.providers.values()) {
|
|
39665
|
+
if (provider.category === "ide") {
|
|
39666
|
+
this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
|
|
39667
|
+
}
|
|
39668
|
+
}
|
|
39669
|
+
}
|
|
39670
|
+
for (const result of results) {
|
|
39671
|
+
this.setProviderAvailability(result.id, {
|
|
39672
|
+
installed: !!result.installed,
|
|
39673
|
+
detectedPath: result.cliCommand || result.path || null
|
|
39674
|
+
});
|
|
39675
|
+
}
|
|
39676
|
+
}
|
|
39677
|
+
getAvailableProviderInfos() {
|
|
39678
|
+
return this.getAll().map((provider) => {
|
|
39679
|
+
const availability = this.providerAvailability.get(provider.type);
|
|
39680
|
+
return {
|
|
39681
|
+
...provider,
|
|
39682
|
+
...availability ? {
|
|
39683
|
+
installed: availability.installed,
|
|
39684
|
+
detectedPath: availability.detectedPath
|
|
39685
|
+
} : {}
|
|
39686
|
+
};
|
|
39687
|
+
});
|
|
39688
|
+
}
|
|
39250
39689
|
/**
|
|
39251
39690
|
* Register IDE providers to core/detector registry
|
|
39252
39691
|
* → Enables detectIDEs() to detect provider.js-based IDEs
|
|
@@ -39321,8 +39760,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39321
39760
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
39322
39761
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
39323
39762
|
if (providerDir) {
|
|
39324
|
-
const fullDir =
|
|
39325
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
39763
|
+
const fullDir = path12.join(providerDir, entry.scriptDir);
|
|
39764
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
39326
39765
|
}
|
|
39327
39766
|
matched = true;
|
|
39328
39767
|
}
|
|
@@ -39337,8 +39776,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39337
39776
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
39338
39777
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
39339
39778
|
if (providerDir) {
|
|
39340
|
-
const fullDir =
|
|
39341
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
39779
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
39780
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
39342
39781
|
}
|
|
39343
39782
|
}
|
|
39344
39783
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -39355,8 +39794,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39355
39794
|
resolved._resolvedScriptDir = dirOverride;
|
|
39356
39795
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
39357
39796
|
if (providerDir) {
|
|
39358
|
-
const fullDir =
|
|
39359
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
39797
|
+
const fullDir = path12.join(providerDir, dirOverride);
|
|
39798
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
39360
39799
|
}
|
|
39361
39800
|
}
|
|
39362
39801
|
} else if (override.scripts) {
|
|
@@ -39372,8 +39811,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39372
39811
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
39373
39812
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
39374
39813
|
if (providerDir) {
|
|
39375
|
-
const fullDir =
|
|
39376
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
39814
|
+
const fullDir = path12.join(providerDir, base.defaultScriptDir);
|
|
39815
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
|
|
39377
39816
|
}
|
|
39378
39817
|
}
|
|
39379
39818
|
}
|
|
@@ -39398,14 +39837,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39398
39837
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
39399
39838
|
return null;
|
|
39400
39839
|
}
|
|
39401
|
-
const dir =
|
|
39840
|
+
const dir = path12.join(providerDir, scriptDir);
|
|
39402
39841
|
if (!fs6.existsSync(dir)) {
|
|
39403
39842
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
39404
39843
|
return null;
|
|
39405
39844
|
}
|
|
39406
39845
|
const cached2 = this.scriptsCache.get(dir);
|
|
39407
39846
|
if (cached2) return cached2;
|
|
39408
|
-
const scriptsJs =
|
|
39847
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
39409
39848
|
if (fs6.existsSync(scriptsJs)) {
|
|
39410
39849
|
try {
|
|
39411
39850
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -39447,7 +39886,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39447
39886
|
return;
|
|
39448
39887
|
}
|
|
39449
39888
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
39450
|
-
this.log(`File changed: ${
|
|
39889
|
+
this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
|
|
39451
39890
|
this.reload();
|
|
39452
39891
|
}
|
|
39453
39892
|
};
|
|
@@ -39502,7 +39941,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39502
39941
|
}
|
|
39503
39942
|
const https = require("https");
|
|
39504
39943
|
const { execSync: execSync7 } = require("child_process");
|
|
39505
|
-
const metaPath =
|
|
39944
|
+
const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
39506
39945
|
let prevEtag = "";
|
|
39507
39946
|
let prevTimestamp = 0;
|
|
39508
39947
|
try {
|
|
@@ -39519,7 +39958,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39519
39958
|
return { updated: false };
|
|
39520
39959
|
}
|
|
39521
39960
|
try {
|
|
39522
|
-
const etag = await new Promise((
|
|
39961
|
+
const etag = await new Promise((resolve12, reject) => {
|
|
39523
39962
|
const options = {
|
|
39524
39963
|
method: "HEAD",
|
|
39525
39964
|
hostname: "github.com",
|
|
@@ -39537,7 +39976,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39537
39976
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
39538
39977
|
timeout: 1e4
|
|
39539
39978
|
}, (res2) => {
|
|
39540
|
-
|
|
39979
|
+
resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
39541
39980
|
});
|
|
39542
39981
|
req2.on("error", reject);
|
|
39543
39982
|
req2.on("timeout", () => {
|
|
@@ -39546,7 +39985,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39546
39985
|
});
|
|
39547
39986
|
req2.end();
|
|
39548
39987
|
} else {
|
|
39549
|
-
|
|
39988
|
+
resolve12(res.headers.etag || res.headers["last-modified"] || "");
|
|
39550
39989
|
}
|
|
39551
39990
|
});
|
|
39552
39991
|
req.on("error", reject);
|
|
@@ -39562,17 +40001,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39562
40001
|
return { updated: false };
|
|
39563
40002
|
}
|
|
39564
40003
|
this.log("Downloading latest providers from GitHub...");
|
|
39565
|
-
const tmpTar =
|
|
39566
|
-
const tmpExtract =
|
|
40004
|
+
const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
40005
|
+
const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
39567
40006
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
39568
40007
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
39569
40008
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
39570
40009
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
39571
40010
|
const rootDir = extracted.find(
|
|
39572
|
-
(d) => fs6.statSync(
|
|
40011
|
+
(d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
39573
40012
|
);
|
|
39574
40013
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
39575
|
-
const sourceDir =
|
|
40014
|
+
const sourceDir = path12.join(tmpExtract, rootDir);
|
|
39576
40015
|
const backupDir = this.upstreamDir + ".bak";
|
|
39577
40016
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
39578
40017
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -39610,7 +40049,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39610
40049
|
downloadFile(url2, destPath) {
|
|
39611
40050
|
const https = require("https");
|
|
39612
40051
|
const http3 = require("http");
|
|
39613
|
-
return new Promise((
|
|
40052
|
+
return new Promise((resolve12, reject) => {
|
|
39614
40053
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
39615
40054
|
if (redirectCount > 5) {
|
|
39616
40055
|
reject(new Error("Too many redirects"));
|
|
@@ -39630,7 +40069,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39630
40069
|
res.pipe(ws2);
|
|
39631
40070
|
ws2.on("finish", () => {
|
|
39632
40071
|
ws2.close();
|
|
39633
|
-
|
|
40072
|
+
resolve12();
|
|
39634
40073
|
});
|
|
39635
40074
|
ws2.on("error", reject);
|
|
39636
40075
|
});
|
|
@@ -39647,8 +40086,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39647
40086
|
copyDirRecursive(src, dest) {
|
|
39648
40087
|
fs6.mkdirSync(dest, { recursive: true });
|
|
39649
40088
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
39650
|
-
const srcPath =
|
|
39651
|
-
const destPath =
|
|
40089
|
+
const srcPath = path12.join(src, entry.name);
|
|
40090
|
+
const destPath = path12.join(dest, entry.name);
|
|
39652
40091
|
if (entry.isDirectory()) {
|
|
39653
40092
|
this.copyDirRecursive(srcPath, destPath);
|
|
39654
40093
|
} else {
|
|
@@ -39659,7 +40098,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39659
40098
|
/** .meta.json save */
|
|
39660
40099
|
writeMeta(metaPath, etag, timestamp) {
|
|
39661
40100
|
try {
|
|
39662
|
-
fs6.mkdirSync(
|
|
40101
|
+
fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
|
|
39663
40102
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
39664
40103
|
etag,
|
|
39665
40104
|
timestamp,
|
|
@@ -39676,7 +40115,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39676
40115
|
const scan = (d) => {
|
|
39677
40116
|
try {
|
|
39678
40117
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
39679
|
-
if (entry.isDirectory()) scan(
|
|
40118
|
+
if (entry.isDirectory()) scan(path12.join(d, entry.name));
|
|
39680
40119
|
else if (entry.name === "provider.json") count++;
|
|
39681
40120
|
}
|
|
39682
40121
|
} catch {
|
|
@@ -39690,9 +40129,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39690
40129
|
* Get public settings schema for a provider (for dashboard UI rendering)
|
|
39691
40130
|
*/
|
|
39692
40131
|
getPublicSettings(type) {
|
|
39693
|
-
const
|
|
39694
|
-
|
|
39695
|
-
return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
40132
|
+
const settings = this.getSettingsSchema(type);
|
|
40133
|
+
return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
|
|
39696
40134
|
}
|
|
39697
40135
|
/**
|
|
39698
40136
|
* Get public settings schema for all providers
|
|
@@ -39709,8 +40147,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39709
40147
|
* Resolved setting value for a provider (default + user override)
|
|
39710
40148
|
*/
|
|
39711
40149
|
getSettingValue(type, key) {
|
|
39712
|
-
const
|
|
39713
|
-
const schemaDef = provider?.settings?.[key];
|
|
40150
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
39714
40151
|
const defaultVal = schemaDef ? schemaDef.default : void 0;
|
|
39715
40152
|
try {
|
|
39716
40153
|
const { loadConfig: loadConfig22 } = (init_config(), __toCommonJS2(config_exports));
|
|
@@ -39725,10 +40162,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39725
40162
|
* All resolved settings for a provider (default + user override)
|
|
39726
40163
|
*/
|
|
39727
40164
|
getSettings(type) {
|
|
39728
|
-
const
|
|
39729
|
-
if (!provider?.settings) return {};
|
|
40165
|
+
const settings = this.getSettingsSchema(type);
|
|
39730
40166
|
const result = {};
|
|
39731
|
-
for (const [key
|
|
40167
|
+
for (const [key] of Object.entries(settings)) {
|
|
39732
40168
|
result[key] = this.getSettingValue(type, key);
|
|
39733
40169
|
}
|
|
39734
40170
|
return result;
|
|
@@ -39737,11 +40173,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39737
40173
|
* Save provider setting value (writes to config.json)
|
|
39738
40174
|
*/
|
|
39739
40175
|
setSetting(type, key, value) {
|
|
39740
|
-
const
|
|
39741
|
-
const schemaDef = provider?.settings?.[key];
|
|
40176
|
+
const schemaDef = this.getSettingsSchema(type)[key];
|
|
39742
40177
|
if (!schemaDef) return false;
|
|
39743
40178
|
if (!schemaDef.public) return false;
|
|
39744
40179
|
if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
|
|
40180
|
+
if (schemaDef.type === "string" && typeof value !== "string") return false;
|
|
39745
40181
|
if (schemaDef.type === "number") {
|
|
39746
40182
|
if (typeof value !== "number") return false;
|
|
39747
40183
|
if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
|
|
@@ -39762,6 +40198,53 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39762
40198
|
return false;
|
|
39763
40199
|
}
|
|
39764
40200
|
}
|
|
40201
|
+
getOptionalStringSetting(type, key) {
|
|
40202
|
+
const value = this.getSettingValue(type, key);
|
|
40203
|
+
if (typeof value !== "string") return null;
|
|
40204
|
+
const trimmed = value.trim();
|
|
40205
|
+
return trimmed ? trimmed : null;
|
|
40206
|
+
}
|
|
40207
|
+
getSettingsSchema(type) {
|
|
40208
|
+
const provider = this.providers.get(type);
|
|
40209
|
+
if (!provider) return {};
|
|
40210
|
+
return {
|
|
40211
|
+
...this.getSyntheticSettings(type, provider),
|
|
40212
|
+
...provider.settings || {}
|
|
40213
|
+
};
|
|
40214
|
+
}
|
|
40215
|
+
getSyntheticSettings(type, provider) {
|
|
40216
|
+
const result = {};
|
|
40217
|
+
if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
|
|
40218
|
+
result.executablePath = {
|
|
40219
|
+
type: "string",
|
|
40220
|
+
default: "",
|
|
40221
|
+
public: true,
|
|
40222
|
+
label: "Executable path",
|
|
40223
|
+
description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
|
|
40224
|
+
};
|
|
40225
|
+
}
|
|
40226
|
+
if (provider.category === "ide") {
|
|
40227
|
+
if (provider.cli && !provider.settings?.cliPathOverride) {
|
|
40228
|
+
result.cliPathOverride = {
|
|
40229
|
+
type: "string",
|
|
40230
|
+
default: "",
|
|
40231
|
+
public: true,
|
|
40232
|
+
label: "CLI path override",
|
|
40233
|
+
description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
|
|
40234
|
+
};
|
|
40235
|
+
}
|
|
40236
|
+
if (provider.paths && !provider.settings?.appPathOverride) {
|
|
40237
|
+
result.appPathOverride = {
|
|
40238
|
+
type: "string",
|
|
40239
|
+
default: "",
|
|
40240
|
+
public: true,
|
|
40241
|
+
label: "App path override",
|
|
40242
|
+
description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
|
|
40243
|
+
};
|
|
40244
|
+
}
|
|
40245
|
+
}
|
|
40246
|
+
return result;
|
|
40247
|
+
}
|
|
39765
40248
|
// ─── Private ───────────────────────────────────
|
|
39766
40249
|
/**
|
|
39767
40250
|
* Find the on-disk directory for a provider by type.
|
|
@@ -39775,17 +40258,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39775
40258
|
for (const root of searchRoots) {
|
|
39776
40259
|
if (!fs6.existsSync(root)) continue;
|
|
39777
40260
|
const candidate = this.getProviderDir(root, cat, type);
|
|
39778
|
-
if (fs6.existsSync(
|
|
39779
|
-
const catDir =
|
|
40261
|
+
if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
|
|
40262
|
+
const catDir = path12.join(root, cat);
|
|
39780
40263
|
if (fs6.existsSync(catDir)) {
|
|
39781
40264
|
try {
|
|
39782
40265
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
39783
40266
|
if (!entry.isDirectory()) continue;
|
|
39784
|
-
const jsonPath =
|
|
40267
|
+
const jsonPath = path12.join(catDir, entry.name, "provider.json");
|
|
39785
40268
|
if (fs6.existsSync(jsonPath)) {
|
|
39786
40269
|
try {
|
|
39787
40270
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
39788
|
-
if (data.type === type) return
|
|
40271
|
+
if (data.type === type) return path12.join(catDir, entry.name);
|
|
39789
40272
|
} catch {
|
|
39790
40273
|
}
|
|
39791
40274
|
}
|
|
@@ -39802,7 +40285,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39802
40285
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
39803
40286
|
*/
|
|
39804
40287
|
buildScriptWrappersFromDir(dir) {
|
|
39805
|
-
const scriptsJs =
|
|
40288
|
+
const scriptsJs = path12.join(dir, "scripts.js");
|
|
39806
40289
|
if (fs6.existsSync(scriptsJs)) {
|
|
39807
40290
|
try {
|
|
39808
40291
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -39816,7 +40299,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39816
40299
|
for (const file2 of fs6.readdirSync(dir)) {
|
|
39817
40300
|
if (!file2.endsWith(".js")) continue;
|
|
39818
40301
|
const scriptName = toCamel(file2.replace(".js", ""));
|
|
39819
|
-
const filePath =
|
|
40302
|
+
const filePath = path12.join(dir, file2);
|
|
39820
40303
|
result[scriptName] = (...args) => {
|
|
39821
40304
|
try {
|
|
39822
40305
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -39876,7 +40359,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39876
40359
|
}
|
|
39877
40360
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
39878
40361
|
if (hasJson) {
|
|
39879
|
-
const jsonPath =
|
|
40362
|
+
const jsonPath = path12.join(d, "provider.json");
|
|
39880
40363
|
try {
|
|
39881
40364
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
39882
40365
|
const mod = JSON.parse(raw);
|
|
@@ -39889,7 +40372,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39889
40372
|
delete mod.extensionIdPattern_flags;
|
|
39890
40373
|
}
|
|
39891
40374
|
const hasCompatibility = Array.isArray(mod.compatibility);
|
|
39892
|
-
const scriptsPath =
|
|
40375
|
+
const scriptsPath = path12.join(d, "scripts.js");
|
|
39893
40376
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
39894
40377
|
try {
|
|
39895
40378
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -39915,7 +40398,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39915
40398
|
if (!entry.isDirectory()) continue;
|
|
39916
40399
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
39917
40400
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
39918
|
-
scan(
|
|
40401
|
+
scan(path12.join(d, entry.name));
|
|
39919
40402
|
}
|
|
39920
40403
|
}
|
|
39921
40404
|
};
|
|
@@ -40009,17 +40492,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40009
40492
|
throw new Error("No free port found");
|
|
40010
40493
|
}
|
|
40011
40494
|
function checkPortFree(port) {
|
|
40012
|
-
return new Promise((
|
|
40495
|
+
return new Promise((resolve12) => {
|
|
40013
40496
|
const server = net3.createServer();
|
|
40014
40497
|
server.unref();
|
|
40015
|
-
server.on("error", () =>
|
|
40498
|
+
server.on("error", () => resolve12(false));
|
|
40016
40499
|
server.listen(port, "127.0.0.1", () => {
|
|
40017
|
-
server.close(() =>
|
|
40500
|
+
server.close(() => resolve12(true));
|
|
40018
40501
|
});
|
|
40019
40502
|
});
|
|
40020
40503
|
}
|
|
40021
40504
|
async function isCdpActive(port) {
|
|
40022
|
-
return new Promise((
|
|
40505
|
+
return new Promise((resolve12) => {
|
|
40023
40506
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
40024
40507
|
timeout: 2e3
|
|
40025
40508
|
}, (res) => {
|
|
@@ -40028,16 +40511,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40028
40511
|
res.on("end", () => {
|
|
40029
40512
|
try {
|
|
40030
40513
|
const info = JSON.parse(data);
|
|
40031
|
-
|
|
40514
|
+
resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
40032
40515
|
} catch {
|
|
40033
|
-
|
|
40516
|
+
resolve12(false);
|
|
40034
40517
|
}
|
|
40035
40518
|
});
|
|
40036
40519
|
});
|
|
40037
|
-
req.on("error", () =>
|
|
40520
|
+
req.on("error", () => resolve12(false));
|
|
40038
40521
|
req.on("timeout", () => {
|
|
40039
40522
|
req.destroy();
|
|
40040
|
-
|
|
40523
|
+
resolve12(false);
|
|
40041
40524
|
});
|
|
40042
40525
|
});
|
|
40043
40526
|
}
|
|
@@ -40171,8 +40654,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40171
40654
|
const appNameMap = getMacAppIdentifiers();
|
|
40172
40655
|
const appName = appNameMap[ideId];
|
|
40173
40656
|
if (appName) {
|
|
40174
|
-
const storagePath =
|
|
40175
|
-
process.env.APPDATA ||
|
|
40657
|
+
const storagePath = path13.join(
|
|
40658
|
+
process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
|
|
40176
40659
|
appName,
|
|
40177
40660
|
"storage.json"
|
|
40178
40661
|
);
|
|
@@ -40196,7 +40679,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40196
40679
|
async function launchWithCdp(options = {}) {
|
|
40197
40680
|
const platform9 = os12.platform();
|
|
40198
40681
|
let targetIde;
|
|
40199
|
-
const ides = await detectIDEs();
|
|
40682
|
+
const ides = await detectIDEs(getProviderLoader());
|
|
40200
40683
|
if (options.ideId) {
|
|
40201
40684
|
targetIde = ides.find((i) => i.id === options.ideId && i.installed);
|
|
40202
40685
|
if (!targetIde) {
|
|
@@ -40346,9 +40829,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40346
40829
|
init_config();
|
|
40347
40830
|
init_logger();
|
|
40348
40831
|
var fs7 = __toESM2(require("fs"));
|
|
40349
|
-
var
|
|
40832
|
+
var path14 = __toESM2(require("path"));
|
|
40350
40833
|
var os13 = __toESM2(require("os"));
|
|
40351
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
40834
|
+
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");
|
|
40352
40835
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
40353
40836
|
var MAX_DAYS = 7;
|
|
40354
40837
|
try {
|
|
@@ -40386,13 +40869,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40386
40869
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
40387
40870
|
}
|
|
40388
40871
|
var currentDate2 = getDateStr2();
|
|
40389
|
-
var currentFile =
|
|
40872
|
+
var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
40390
40873
|
var writeCount2 = 0;
|
|
40391
40874
|
function checkRotation() {
|
|
40392
40875
|
const today = getDateStr2();
|
|
40393
40876
|
if (today !== currentDate2) {
|
|
40394
40877
|
currentDate2 = today;
|
|
40395
|
-
currentFile =
|
|
40878
|
+
currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
40396
40879
|
cleanOldFiles();
|
|
40397
40880
|
}
|
|
40398
40881
|
}
|
|
@@ -40406,7 +40889,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40406
40889
|
const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
40407
40890
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
40408
40891
|
try {
|
|
40409
|
-
fs7.unlinkSync(
|
|
40892
|
+
fs7.unlinkSync(path14.join(LOG_DIR2, file2));
|
|
40410
40893
|
} catch {
|
|
40411
40894
|
}
|
|
40412
40895
|
}
|
|
@@ -40494,12 +40977,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40494
40977
|
}));
|
|
40495
40978
|
}
|
|
40496
40979
|
function buildAvailableProviders(providerLoader) {
|
|
40497
|
-
|
|
40980
|
+
const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
|
|
40981
|
+
return providers.map((provider) => ({
|
|
40498
40982
|
type: provider.type,
|
|
40499
40983
|
name: provider.displayName || provider.type,
|
|
40500
40984
|
displayName: provider.displayName || provider.type,
|
|
40501
40985
|
icon: provider.icon || "\u{1F4BB}",
|
|
40502
|
-
category: provider.category
|
|
40986
|
+
category: provider.category,
|
|
40987
|
+
...provider.installed !== void 0 ? { installed: provider.installed } : {},
|
|
40988
|
+
...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
|
|
40503
40989
|
}));
|
|
40504
40990
|
}
|
|
40505
40991
|
function parseMessageTime(value) {
|
|
@@ -40625,13 +41111,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40625
41111
|
var import_child_process8 = require("child_process");
|
|
40626
41112
|
var fs8 = __toESM2(require("fs"));
|
|
40627
41113
|
var os15 = __toESM2(require("os"));
|
|
40628
|
-
var
|
|
41114
|
+
var path15 = __toESM2(require("path"));
|
|
40629
41115
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
40630
41116
|
function getUpgradeLogPath() {
|
|
40631
41117
|
const home = os15.homedir();
|
|
40632
|
-
const dir =
|
|
41118
|
+
const dir = path15.join(home, ".adhdev");
|
|
40633
41119
|
fs8.mkdirSync(dir, { recursive: true });
|
|
40634
|
-
return
|
|
41120
|
+
return path15.join(dir, "daemon-upgrade.log");
|
|
40635
41121
|
}
|
|
40636
41122
|
function appendUpgradeLog(message) {
|
|
40637
41123
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -40664,14 +41150,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40664
41150
|
while (Date.now() - start < timeoutMs) {
|
|
40665
41151
|
try {
|
|
40666
41152
|
process.kill(pid, 0);
|
|
40667
|
-
await new Promise((
|
|
41153
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
40668
41154
|
} catch {
|
|
40669
41155
|
return;
|
|
40670
41156
|
}
|
|
40671
41157
|
}
|
|
40672
41158
|
}
|
|
40673
41159
|
function stopSessionHostProcesses(appName) {
|
|
40674
|
-
const pidFile =
|
|
41160
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
40675
41161
|
try {
|
|
40676
41162
|
if (fs8.existsSync(pidFile)) {
|
|
40677
41163
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -40700,7 +41186,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40700
41186
|
}
|
|
40701
41187
|
}
|
|
40702
41188
|
function removeDaemonPidFile() {
|
|
40703
|
-
const pidFile =
|
|
41189
|
+
const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
|
|
40704
41190
|
try {
|
|
40705
41191
|
fs8.unlinkSync(pidFile);
|
|
40706
41192
|
} catch {
|
|
@@ -40711,7 +41197,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40711
41197
|
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
40712
41198
|
if (!npmRoot) return;
|
|
40713
41199
|
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
40714
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
41200
|
+
const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
|
|
40715
41201
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
40716
41202
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
40717
41203
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -40719,25 +41205,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40719
41205
|
}
|
|
40720
41206
|
if (pkgName.startsWith("@")) {
|
|
40721
41207
|
const [scope, name] = pkgName.split("/");
|
|
40722
|
-
const scopeDir =
|
|
41208
|
+
const scopeDir = path15.join(npmRoot, scope);
|
|
40723
41209
|
if (!fs8.existsSync(scopeDir)) return;
|
|
40724
41210
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
40725
41211
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
40726
|
-
fs8.rmSync(
|
|
40727
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
41212
|
+
fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
|
|
41213
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
|
|
40728
41214
|
}
|
|
40729
41215
|
} else {
|
|
40730
41216
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
40731
41217
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
40732
|
-
fs8.rmSync(
|
|
40733
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
41218
|
+
fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
|
|
41219
|
+
appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
|
|
40734
41220
|
}
|
|
40735
41221
|
}
|
|
40736
41222
|
if (fs8.existsSync(binDir)) {
|
|
40737
41223
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
40738
41224
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
40739
|
-
fs8.rmSync(
|
|
40740
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
41225
|
+
fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
|
|
41226
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
|
|
40741
41227
|
}
|
|
40742
41228
|
}
|
|
40743
41229
|
}
|
|
@@ -40779,7 +41265,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40779
41265
|
appendUpgradeLog(installOutput.trim());
|
|
40780
41266
|
}
|
|
40781
41267
|
if (process.platform === "win32") {
|
|
40782
|
-
await new Promise((
|
|
41268
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
40783
41269
|
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
40784
41270
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
40785
41271
|
}
|
|
@@ -40973,6 +41459,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40973
41459
|
const record2 = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
|
|
40974
41460
|
return { success: true, record: record2 };
|
|
40975
41461
|
}
|
|
41462
|
+
case "session_host_prune_duplicate_sessions": {
|
|
41463
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
41464
|
+
const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
|
|
41465
|
+
providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
|
|
41466
|
+
workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
|
|
41467
|
+
dryRun: args?.dryRun === true
|
|
41468
|
+
});
|
|
41469
|
+
return { success: true, result };
|
|
41470
|
+
}
|
|
40976
41471
|
case "session_host_acquire_write": {
|
|
40977
41472
|
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
40978
41473
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
@@ -41055,6 +41550,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41055
41550
|
if (!ideType) throw new Error("ideType required");
|
|
41056
41551
|
const killProcess = args?.killProcess !== false;
|
|
41057
41552
|
await this.stopIde(ideType, killProcess);
|
|
41553
|
+
try {
|
|
41554
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
41555
|
+
this.deps.detectedIdes.value = results;
|
|
41556
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
41557
|
+
} catch {
|
|
41558
|
+
}
|
|
41058
41559
|
return { success: true, ideType, stopped: true, processKilled: killProcess };
|
|
41059
41560
|
}
|
|
41060
41561
|
// ─── IDE restart ───
|
|
@@ -41097,6 +41598,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41097
41598
|
}
|
|
41098
41599
|
}
|
|
41099
41600
|
this.deps.onIdeConnected?.();
|
|
41601
|
+
try {
|
|
41602
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
41603
|
+
this.deps.detectedIdes.value = results;
|
|
41604
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
41605
|
+
} catch {
|
|
41606
|
+
}
|
|
41100
41607
|
if (result.success && resolvedWorkspace) {
|
|
41101
41608
|
try {
|
|
41102
41609
|
const next = appendRecentActivity(loadState(), {
|
|
@@ -41124,8 +41631,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41124
41631
|
}
|
|
41125
41632
|
// ─── Detect IDEs ───
|
|
41126
41633
|
case "detect_ides": {
|
|
41127
|
-
const results = await detectIDEs();
|
|
41634
|
+
const results = await detectIDEs(this.deps.providerLoader);
|
|
41128
41635
|
this.deps.detectedIdes.value = results;
|
|
41636
|
+
this.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
41129
41637
|
return { success: true, detectedInfo: results };
|
|
41130
41638
|
}
|
|
41131
41639
|
// ─── Set User Name ───
|
|
@@ -41537,6 +42045,51 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41537
42045
|
isTransportError(reason) {
|
|
41538
42046
|
return /Session with given id not found/i.test(reason) || /CDP not connected/i.test(reason) || /Target closed/i.test(reason) || /WebSocket not open/i.test(reason) || /not connected/i.test(reason) || /execution context/i.test(reason) || /Cannot find context with specified id/i.test(reason);
|
|
41539
42047
|
}
|
|
42048
|
+
titlesMatch(actual, expected) {
|
|
42049
|
+
const lhs = actual.trim().toLowerCase();
|
|
42050
|
+
const rhs = expected.trim().toLowerCase();
|
|
42051
|
+
if (!lhs || !rhs) return false;
|
|
42052
|
+
return lhs === rhs || lhs.includes(rhs) || rhs.includes(lhs);
|
|
42053
|
+
}
|
|
42054
|
+
messageCount(state) {
|
|
42055
|
+
return Array.isArray(state?.messages) ? state.messages.length : 0;
|
|
42056
|
+
}
|
|
42057
|
+
lastMessageSignature(state) {
|
|
42058
|
+
const messages = Array.isArray(state?.messages) ? state.messages : [];
|
|
42059
|
+
const last = messages[messages.length - 1];
|
|
42060
|
+
if (!last) return "";
|
|
42061
|
+
return `${last.role || ""}:${String(last.content || "").replace(/\s+/g, " ").trim()}`;
|
|
42062
|
+
}
|
|
42063
|
+
async verifySendOutcome(evaluate, before) {
|
|
42064
|
+
const beforeCount = this.messageCount(before);
|
|
42065
|
+
const beforeSignature = this.lastMessageSignature(before);
|
|
42066
|
+
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
42067
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
42068
|
+
let state;
|
|
42069
|
+
try {
|
|
42070
|
+
state = await this.readChat(evaluate);
|
|
42071
|
+
} catch {
|
|
42072
|
+
continue;
|
|
42073
|
+
}
|
|
42074
|
+
if (state.status === "waiting_approval") {
|
|
42075
|
+
return true;
|
|
42076
|
+
}
|
|
42077
|
+
const afterCount = this.messageCount(state);
|
|
42078
|
+
const afterSignature = this.lastMessageSignature(state);
|
|
42079
|
+
if (afterCount > beforeCount) return true;
|
|
42080
|
+
if (afterSignature && afterSignature !== beforeSignature) return true;
|
|
42081
|
+
}
|
|
42082
|
+
return false;
|
|
42083
|
+
}
|
|
42084
|
+
async readStableBaselineState(evaluate) {
|
|
42085
|
+
const first = await this.readChat(evaluate);
|
|
42086
|
+
if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
|
|
42087
|
+
return first;
|
|
42088
|
+
}
|
|
42089
|
+
await new Promise((resolve12) => setTimeout(resolve12, 150));
|
|
42090
|
+
const second = await this.readChat(evaluate);
|
|
42091
|
+
return this.messageCount(second) >= this.messageCount(first) ? second : first;
|
|
42092
|
+
}
|
|
41540
42093
|
async readChat(evaluate) {
|
|
41541
42094
|
const script = this.callScript("readChat");
|
|
41542
42095
|
if (!script) return this.errorState("readChat script not available");
|
|
@@ -41562,6 +42115,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41562
42115
|
mode: data.mode,
|
|
41563
42116
|
activeModal: data.activeModal
|
|
41564
42117
|
};
|
|
42118
|
+
if (typeof data.title === "string" && data.title.trim()) {
|
|
42119
|
+
state.title = data.title.trim();
|
|
42120
|
+
}
|
|
41565
42121
|
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
41566
42122
|
if (controlValues) state.controlValues = controlValues;
|
|
41567
42123
|
const effects = normalizeProviderEffects(data);
|
|
@@ -41585,6 +42141,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41585
42141
|
}
|
|
41586
42142
|
}
|
|
41587
42143
|
async sendMessage(evaluate, text) {
|
|
42144
|
+
let beforeState = null;
|
|
42145
|
+
try {
|
|
42146
|
+
beforeState = await this.readStableBaselineState(evaluate);
|
|
42147
|
+
} catch {
|
|
42148
|
+
beforeState = null;
|
|
42149
|
+
}
|
|
41588
42150
|
const params = { message: text };
|
|
41589
42151
|
const script = this.callScript("sendMessage", params) || this.callScript("sendMessage", text);
|
|
41590
42152
|
if (!script) throw new Error(`[${this.agentName}] sendMessage script not available`);
|
|
@@ -41602,7 +42164,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41602
42164
|
}
|
|
41603
42165
|
if (parsed && typeof parsed === "object") {
|
|
41604
42166
|
if (parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true) {
|
|
41605
|
-
|
|
42167
|
+
const verified = await this.verifySendOutcome(evaluate, beforeState);
|
|
42168
|
+
if (verified) return;
|
|
42169
|
+
throw new Error(`[${this.agentName}] sendMessage was not observed in chat state`);
|
|
41606
42170
|
}
|
|
41607
42171
|
if (typeof parsed.error === "string" && parsed.error.trim()) {
|
|
41608
42172
|
throw new Error(`[${this.agentName}] sendMessage failed: ${parsed.error}`);
|
|
@@ -41613,7 +42177,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41613
42177
|
async resolveAction(evaluate, action, button) {
|
|
41614
42178
|
const script = this.callScript("resolveAction", { action, button });
|
|
41615
42179
|
if (!script) return false;
|
|
41616
|
-
|
|
42180
|
+
const result = await evaluate(script);
|
|
42181
|
+
const parsed = this.parseMaybeJson(result);
|
|
42182
|
+
if (parsed === true) return true;
|
|
42183
|
+
if (typeof parsed === "string") {
|
|
42184
|
+
const normalized = parsed.trim().toLowerCase();
|
|
42185
|
+
return normalized === "ok" || normalized === "success" || normalized === "true" || normalized === "resolved" || normalized === "approved" || normalized === "rejected";
|
|
42186
|
+
}
|
|
42187
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
42188
|
+
return parsed.resolved === true || parsed.success === true || parsed.ok === true || parsed.found === true;
|
|
41617
42189
|
}
|
|
41618
42190
|
async newSession(evaluate) {
|
|
41619
42191
|
const script = this.callScript("newSession");
|
|
@@ -41631,7 +42203,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41631
42203
|
const raw = await evaluate(script, 1e4);
|
|
41632
42204
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
41633
42205
|
if (data?.error) return [];
|
|
41634
|
-
|
|
42206
|
+
if (Array.isArray(data)) return data;
|
|
42207
|
+
if (Array.isArray(data?.sessions)) return data.sessions;
|
|
42208
|
+
if (Array.isArray(data?.chats)) return data.chats;
|
|
42209
|
+
return [];
|
|
41635
42210
|
} catch {
|
|
41636
42211
|
return [];
|
|
41637
42212
|
}
|
|
@@ -41639,7 +42214,24 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41639
42214
|
async switchSession(evaluate, sessionId) {
|
|
41640
42215
|
const script = this.callScript("switchSession", sessionId);
|
|
41641
42216
|
if (!script) return false;
|
|
41642
|
-
|
|
42217
|
+
const raw = await evaluate(script, 1e4);
|
|
42218
|
+
const data = this.parseMaybeJson(raw);
|
|
42219
|
+
if (data === true) return true;
|
|
42220
|
+
if (typeof data === "string") {
|
|
42221
|
+
const normalized = data.trim().toLowerCase();
|
|
42222
|
+
return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
|
|
42223
|
+
}
|
|
42224
|
+
if (data && typeof data === "object") {
|
|
42225
|
+
if (data.switched === true || data.success === true || data.ok === true) return true;
|
|
42226
|
+
if (typeof data.error === "string" && data.error.trim()) return false;
|
|
42227
|
+
}
|
|
42228
|
+
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
42229
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
42230
|
+
const state = await this.readChat(evaluate);
|
|
42231
|
+
const title = typeof state.title === "string" ? state.title : "";
|
|
42232
|
+
if (this.titlesMatch(title, sessionId)) return true;
|
|
42233
|
+
}
|
|
42234
|
+
return false;
|
|
41643
42235
|
}
|
|
41644
42236
|
async focusEditor(evaluate) {
|
|
41645
42237
|
const script = this.callScript("focusEditor");
|
|
@@ -41843,7 +42435,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41843
42435
|
return false;
|
|
41844
42436
|
}
|
|
41845
42437
|
}
|
|
41846
|
-
async resolveSessionAction(cdp, sessionId, action) {
|
|
42438
|
+
async resolveSessionAction(cdp, sessionId, action, button) {
|
|
41847
42439
|
await this.ensureSessionPanelOpen(sessionId);
|
|
41848
42440
|
const target = this.getSessionTarget(sessionId);
|
|
41849
42441
|
if (!target?.parentSessionId) return false;
|
|
@@ -41853,7 +42445,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41853
42445
|
if (!agent) return false;
|
|
41854
42446
|
try {
|
|
41855
42447
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
41856
|
-
return await agent.adapter.resolveAction(evaluate, action);
|
|
42448
|
+
return await agent.adapter.resolveAction(evaluate, action, button);
|
|
41857
42449
|
} catch (e) {
|
|
41858
42450
|
this.logFn(`[AgentStream] resolveAction(${sessionId}) error: ${e.message}`);
|
|
41859
42451
|
return false;
|
|
@@ -42319,11 +42911,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42319
42911
|
}
|
|
42320
42912
|
};
|
|
42321
42913
|
var fs10 = __toESM2(require("fs"));
|
|
42322
|
-
var
|
|
42914
|
+
var path16 = __toESM2(require("path"));
|
|
42323
42915
|
var os16 = __toESM2(require("os"));
|
|
42324
42916
|
var import_child_process9 = require("child_process");
|
|
42325
42917
|
var import_os3 = require("os");
|
|
42326
|
-
var ARCHIVE_PATH =
|
|
42918
|
+
var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
42327
42919
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
42328
42920
|
var VersionArchive = class {
|
|
42329
42921
|
history = {};
|
|
@@ -42370,7 +42962,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42370
42962
|
}
|
|
42371
42963
|
save() {
|
|
42372
42964
|
try {
|
|
42373
|
-
fs10.mkdirSync(
|
|
42965
|
+
fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
|
|
42374
42966
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
42375
42967
|
} catch {
|
|
42376
42968
|
}
|
|
@@ -42411,7 +43003,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42411
43003
|
for (const p of paths) {
|
|
42412
43004
|
if (p.includes("*")) {
|
|
42413
43005
|
const home = os16.homedir();
|
|
42414
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
43006
|
+
const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
|
|
42415
43007
|
if (fs10.existsSync(resolved)) return resolved;
|
|
42416
43008
|
} else {
|
|
42417
43009
|
if (fs10.existsSync(p)) return p;
|
|
@@ -42421,7 +43013,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42421
43013
|
}
|
|
42422
43014
|
function getMacAppVersion(appPath) {
|
|
42423
43015
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
42424
|
-
const plistPath =
|
|
43016
|
+
const plistPath = path16.join(appPath, "Contents", "Info.plist");
|
|
42425
43017
|
if (!fs10.existsSync(plistPath)) return null;
|
|
42426
43018
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
42427
43019
|
return raw || null;
|
|
@@ -42448,7 +43040,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42448
43040
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
42449
43041
|
let resolvedBin = cliBin;
|
|
42450
43042
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
42451
|
-
const bundled =
|
|
43043
|
+
const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
42452
43044
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
42453
43045
|
}
|
|
42454
43046
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -42487,7 +43079,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
42487
43079
|
}
|
|
42488
43080
|
var http2 = __toESM2(require("http"));
|
|
42489
43081
|
var fs14 = __toESM2(require("fs"));
|
|
42490
|
-
var
|
|
43082
|
+
var path20 = __toESM2(require("path"));
|
|
42491
43083
|
function generateFiles(type, name, category, opts = {}) {
|
|
42492
43084
|
const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
|
|
42493
43085
|
if (category === "cli" || category === "acp") {
|
|
@@ -42817,7 +43409,7 @@ async (params) => {
|
|
|
42817
43409
|
}
|
|
42818
43410
|
init_logger();
|
|
42819
43411
|
var fs11 = __toESM2(require("fs"));
|
|
42820
|
-
var
|
|
43412
|
+
var path17 = __toESM2(require("path"));
|
|
42821
43413
|
init_logger();
|
|
42822
43414
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
42823
43415
|
const body = await ctx.readBody(req);
|
|
@@ -42996,17 +43588,17 @@ async (params) => {
|
|
|
42996
43588
|
return;
|
|
42997
43589
|
}
|
|
42998
43590
|
let scriptsPath = "";
|
|
42999
|
-
const directScripts =
|
|
43591
|
+
const directScripts = path17.join(dir, "scripts.js");
|
|
43000
43592
|
if (fs11.existsSync(directScripts)) {
|
|
43001
43593
|
scriptsPath = directScripts;
|
|
43002
43594
|
} else {
|
|
43003
|
-
const scriptsDir =
|
|
43595
|
+
const scriptsDir = path17.join(dir, "scripts");
|
|
43004
43596
|
if (fs11.existsSync(scriptsDir)) {
|
|
43005
43597
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
43006
|
-
return fs11.statSync(
|
|
43598
|
+
return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
43007
43599
|
}).sort().reverse();
|
|
43008
43600
|
for (const ver of versions) {
|
|
43009
|
-
const p =
|
|
43601
|
+
const p = path17.join(scriptsDir, ver, "scripts.js");
|
|
43010
43602
|
if (fs11.existsSync(p)) {
|
|
43011
43603
|
scriptsPath = p;
|
|
43012
43604
|
break;
|
|
@@ -43823,7 +44415,7 @@ async (params) => {
|
|
|
43823
44415
|
}
|
|
43824
44416
|
}
|
|
43825
44417
|
var fs12 = __toESM2(require("fs"));
|
|
43826
|
-
var
|
|
44418
|
+
var path18 = __toESM2(require("path"));
|
|
43827
44419
|
function slugifyFixtureName(value) {
|
|
43828
44420
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
43829
44421
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -43833,11 +44425,11 @@ async (params) => {
|
|
|
43833
44425
|
if (!providerDir) {
|
|
43834
44426
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
43835
44427
|
}
|
|
43836
|
-
return
|
|
44428
|
+
return path18.join(providerDir, "fixtures");
|
|
43837
44429
|
}
|
|
43838
44430
|
function readCliFixture(ctx, type, name) {
|
|
43839
44431
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
43840
|
-
const filePath =
|
|
44432
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
43841
44433
|
if (!fs12.existsSync(filePath)) {
|
|
43842
44434
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
43843
44435
|
}
|
|
@@ -43997,7 +44589,7 @@ async (params) => {
|
|
|
43997
44589
|
return { target, instance, adapter };
|
|
43998
44590
|
}
|
|
43999
44591
|
function sleep(ms2) {
|
|
44000
|
-
return new Promise((
|
|
44592
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms2));
|
|
44001
44593
|
}
|
|
44002
44594
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
44003
44595
|
const startedAt = Date.now();
|
|
@@ -44596,7 +45188,7 @@ async (params) => {
|
|
|
44596
45188
|
},
|
|
44597
45189
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
44598
45190
|
};
|
|
44599
|
-
const filePath =
|
|
45191
|
+
const filePath = path18.join(fixtureDir, `${name}.json`);
|
|
44600
45192
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
44601
45193
|
ctx.json(res, 200, {
|
|
44602
45194
|
saved: true,
|
|
@@ -44620,7 +45212,7 @@ async (params) => {
|
|
|
44620
45212
|
return;
|
|
44621
45213
|
}
|
|
44622
45214
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
|
|
44623
|
-
const fullPath =
|
|
45215
|
+
const fullPath = path18.join(fixtureDir, file2);
|
|
44624
45216
|
try {
|
|
44625
45217
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
44626
45218
|
return {
|
|
@@ -44754,7 +45346,7 @@ async (params) => {
|
|
|
44754
45346
|
}
|
|
44755
45347
|
}
|
|
44756
45348
|
var fs13 = __toESM2(require("fs"));
|
|
44757
|
-
var
|
|
45349
|
+
var path19 = __toESM2(require("path"));
|
|
44758
45350
|
var os17 = __toESM2(require("os"));
|
|
44759
45351
|
function getAutoImplPid(ctx) {
|
|
44760
45352
|
const proc = ctx.autoImplProcess;
|
|
@@ -44794,22 +45386,22 @@ async (params) => {
|
|
|
44794
45386
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
44795
45387
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
44796
45388
|
try {
|
|
44797
|
-
return fs13.statSync(
|
|
45389
|
+
return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
|
|
44798
45390
|
} catch {
|
|
44799
45391
|
return false;
|
|
44800
45392
|
}
|
|
44801
45393
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
44802
45394
|
if (versions.length === 0) return null;
|
|
44803
|
-
return
|
|
45395
|
+
return path19.join(scriptsDir, versions[0]);
|
|
44804
45396
|
}
|
|
44805
45397
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
44806
|
-
const canonicalUserDir =
|
|
44807
|
-
const desiredDir = requestedDir ?
|
|
44808
|
-
const upstreamRoot =
|
|
44809
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
45398
|
+
const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
45399
|
+
const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
|
|
45400
|
+
const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
|
|
45401
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
|
|
44810
45402
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
44811
45403
|
}
|
|
44812
|
-
if (
|
|
45404
|
+
if (path19.basename(desiredDir) !== type) {
|
|
44813
45405
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
44814
45406
|
}
|
|
44815
45407
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -44817,11 +45409,11 @@ async (params) => {
|
|
|
44817
45409
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
44818
45410
|
}
|
|
44819
45411
|
if (!fs13.existsSync(desiredDir)) {
|
|
44820
|
-
fs13.mkdirSync(
|
|
45412
|
+
fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
|
|
44821
45413
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
44822
45414
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
44823
45415
|
}
|
|
44824
|
-
const providerJson =
|
|
45416
|
+
const providerJson = path19.join(desiredDir, "provider.json");
|
|
44825
45417
|
if (!fs13.existsSync(providerJson)) {
|
|
44826
45418
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
44827
45419
|
}
|
|
@@ -44844,13 +45436,13 @@ async (params) => {
|
|
|
44844
45436
|
const refDir = ctx.findProviderDir(referenceType);
|
|
44845
45437
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
44846
45438
|
const referenceScripts = {};
|
|
44847
|
-
const scriptsDir =
|
|
45439
|
+
const scriptsDir = path19.join(refDir, "scripts");
|
|
44848
45440
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
44849
45441
|
if (!latestDir) return referenceScripts;
|
|
44850
45442
|
for (const file2 of fs13.readdirSync(latestDir)) {
|
|
44851
45443
|
if (!file2.endsWith(".js")) continue;
|
|
44852
45444
|
try {
|
|
44853
|
-
referenceScripts[file2] = fs13.readFileSync(
|
|
45445
|
+
referenceScripts[file2] = fs13.readFileSync(path19.join(latestDir, file2), "utf-8");
|
|
44854
45446
|
} catch {
|
|
44855
45447
|
}
|
|
44856
45448
|
}
|
|
@@ -44958,9 +45550,9 @@ async (params) => {
|
|
|
44958
45550
|
});
|
|
44959
45551
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
44960
45552
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
44961
|
-
const tmpDir =
|
|
45553
|
+
const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
44962
45554
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
44963
|
-
const promptFile =
|
|
45555
|
+
const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
44964
45556
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
44965
45557
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
44966
45558
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -45387,7 +45979,7 @@ async (params) => {
|
|
|
45387
45979
|
setMode: "set_mode.js"
|
|
45388
45980
|
};
|
|
45389
45981
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
45390
|
-
const scriptsDir =
|
|
45982
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
45391
45983
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
45392
45984
|
if (latestScriptsDir) {
|
|
45393
45985
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -45398,7 +45990,7 @@ async (params) => {
|
|
|
45398
45990
|
for (const file2 of fs13.readdirSync(latestScriptsDir)) {
|
|
45399
45991
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
45400
45992
|
try {
|
|
45401
|
-
const content = fs13.readFileSync(
|
|
45993
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
|
|
45402
45994
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
45403
45995
|
lines.push("```javascript");
|
|
45404
45996
|
lines.push(content);
|
|
@@ -45415,7 +46007,7 @@ async (params) => {
|
|
|
45415
46007
|
lines.push("");
|
|
45416
46008
|
for (const file2 of refFiles) {
|
|
45417
46009
|
try {
|
|
45418
|
-
const content = fs13.readFileSync(
|
|
46010
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
|
|
45419
46011
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
45420
46012
|
lines.push("```javascript");
|
|
45421
46013
|
lines.push(content);
|
|
@@ -45456,10 +46048,10 @@ async (params) => {
|
|
|
45456
46048
|
lines.push("");
|
|
45457
46049
|
}
|
|
45458
46050
|
}
|
|
45459
|
-
const docsDir =
|
|
46051
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
45460
46052
|
const loadGuide = (name) => {
|
|
45461
46053
|
try {
|
|
45462
|
-
const p =
|
|
46054
|
+
const p = path19.join(docsDir, name);
|
|
45463
46055
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
45464
46056
|
} catch {
|
|
45465
46057
|
}
|
|
@@ -45694,7 +46286,7 @@ async (params) => {
|
|
|
45694
46286
|
parseApproval: "parse_approval.js"
|
|
45695
46287
|
};
|
|
45696
46288
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
45697
|
-
const scriptsDir =
|
|
46289
|
+
const scriptsDir = path19.join(providerDir, "scripts");
|
|
45698
46290
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
45699
46291
|
if (latestScriptsDir) {
|
|
45700
46292
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -45706,7 +46298,7 @@ async (params) => {
|
|
|
45706
46298
|
if (!file2.endsWith(".js")) continue;
|
|
45707
46299
|
if (!targetFileNames.has(file2)) continue;
|
|
45708
46300
|
try {
|
|
45709
|
-
const content = fs13.readFileSync(
|
|
46301
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
|
|
45710
46302
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
45711
46303
|
lines.push("```javascript");
|
|
45712
46304
|
lines.push(content);
|
|
@@ -45722,7 +46314,7 @@ async (params) => {
|
|
|
45722
46314
|
lines.push("");
|
|
45723
46315
|
for (const file2 of refFiles) {
|
|
45724
46316
|
try {
|
|
45725
|
-
const content = fs13.readFileSync(
|
|
46317
|
+
const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
|
|
45726
46318
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
45727
46319
|
lines.push("```javascript");
|
|
45728
46320
|
lines.push(content);
|
|
@@ -45755,10 +46347,10 @@ async (params) => {
|
|
|
45755
46347
|
lines.push("");
|
|
45756
46348
|
}
|
|
45757
46349
|
}
|
|
45758
|
-
const docsDir =
|
|
46350
|
+
const docsDir = path19.join(providerDir, "../../docs");
|
|
45759
46351
|
const loadGuide = (name) => {
|
|
45760
46352
|
try {
|
|
45761
|
-
const p =
|
|
46353
|
+
const p = path19.join(docsDir, name);
|
|
45762
46354
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
45763
46355
|
} catch {
|
|
45764
46356
|
}
|
|
@@ -46167,8 +46759,8 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46167
46759
|
}
|
|
46168
46760
|
getEndpointList() {
|
|
46169
46761
|
return this.routes.map((r) => {
|
|
46170
|
-
const
|
|
46171
|
-
return `${r.method.padEnd(5)} ${
|
|
46762
|
+
const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
46763
|
+
return `${r.method.padEnd(5)} ${path21}`;
|
|
46172
46764
|
});
|
|
46173
46765
|
}
|
|
46174
46766
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -46199,15 +46791,15 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46199
46791
|
this.json(res, 500, { error: e.message });
|
|
46200
46792
|
}
|
|
46201
46793
|
});
|
|
46202
|
-
return new Promise((
|
|
46794
|
+
return new Promise((resolve12, reject) => {
|
|
46203
46795
|
this.server.listen(port, "127.0.0.1", () => {
|
|
46204
46796
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
46205
|
-
|
|
46797
|
+
resolve12();
|
|
46206
46798
|
});
|
|
46207
46799
|
this.server.on("error", (e) => {
|
|
46208
46800
|
if (e.code === "EADDRINUSE") {
|
|
46209
46801
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
46210
|
-
|
|
46802
|
+
resolve12();
|
|
46211
46803
|
} else {
|
|
46212
46804
|
reject(e);
|
|
46213
46805
|
}
|
|
@@ -46290,20 +46882,20 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46290
46882
|
child.stderr?.on("data", (d) => {
|
|
46291
46883
|
stderr += d.toString().slice(0, 2e3);
|
|
46292
46884
|
});
|
|
46293
|
-
await new Promise((
|
|
46885
|
+
await new Promise((resolve12) => {
|
|
46294
46886
|
const timer = setTimeout(() => {
|
|
46295
46887
|
child.kill();
|
|
46296
|
-
|
|
46888
|
+
resolve12();
|
|
46297
46889
|
}, 3e3);
|
|
46298
46890
|
child.on("exit", () => {
|
|
46299
46891
|
clearTimeout(timer);
|
|
46300
|
-
|
|
46892
|
+
resolve12();
|
|
46301
46893
|
});
|
|
46302
46894
|
child.stdout?.once("data", () => {
|
|
46303
46895
|
setTimeout(() => {
|
|
46304
46896
|
child.kill();
|
|
46305
46897
|
clearTimeout(timer);
|
|
46306
|
-
|
|
46898
|
+
resolve12();
|
|
46307
46899
|
}, 500);
|
|
46308
46900
|
});
|
|
46309
46901
|
});
|
|
@@ -46450,12 +47042,12 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46450
47042
|
// ─── DevConsole SPA ───
|
|
46451
47043
|
getConsoleDistDir() {
|
|
46452
47044
|
const candidates = [
|
|
46453
|
-
|
|
46454
|
-
|
|
46455
|
-
|
|
47045
|
+
path20.resolve(__dirname, "../../web-devconsole/dist"),
|
|
47046
|
+
path20.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
47047
|
+
path20.join(process.cwd(), "packages/web-devconsole/dist")
|
|
46456
47048
|
];
|
|
46457
47049
|
for (const dir of candidates) {
|
|
46458
|
-
if (fs14.existsSync(
|
|
47050
|
+
if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
|
|
46459
47051
|
}
|
|
46460
47052
|
return null;
|
|
46461
47053
|
}
|
|
@@ -46465,7 +47057,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46465
47057
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
46466
47058
|
return;
|
|
46467
47059
|
}
|
|
46468
|
-
const htmlPath =
|
|
47060
|
+
const htmlPath = path20.join(distDir, "index.html");
|
|
46469
47061
|
try {
|
|
46470
47062
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
46471
47063
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -46490,15 +47082,15 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46490
47082
|
this.json(res, 404, { error: "Not found" });
|
|
46491
47083
|
return;
|
|
46492
47084
|
}
|
|
46493
|
-
const safePath =
|
|
46494
|
-
const filePath =
|
|
47085
|
+
const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
|
|
47086
|
+
const filePath = path20.join(distDir, safePath);
|
|
46495
47087
|
if (!filePath.startsWith(distDir)) {
|
|
46496
47088
|
this.json(res, 403, { error: "Forbidden" });
|
|
46497
47089
|
return;
|
|
46498
47090
|
}
|
|
46499
47091
|
try {
|
|
46500
47092
|
const content = fs14.readFileSync(filePath);
|
|
46501
|
-
const ext =
|
|
47093
|
+
const ext = path20.extname(filePath);
|
|
46502
47094
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
46503
47095
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
46504
47096
|
res.end(content);
|
|
@@ -46611,9 +47203,9 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46611
47203
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
46612
47204
|
if (entry.isDirectory()) {
|
|
46613
47205
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
46614
|
-
scan(
|
|
47206
|
+
scan(path20.join(d, entry.name), rel);
|
|
46615
47207
|
} else {
|
|
46616
|
-
const stat4 = fs14.statSync(
|
|
47208
|
+
const stat4 = fs14.statSync(path20.join(d, entry.name));
|
|
46617
47209
|
files.push({ path: rel, size: stat4.size, type: "file" });
|
|
46618
47210
|
}
|
|
46619
47211
|
}
|
|
@@ -46636,7 +47228,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46636
47228
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
46637
47229
|
return;
|
|
46638
47230
|
}
|
|
46639
|
-
const fullPath =
|
|
47231
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
46640
47232
|
if (!fullPath.startsWith(dir)) {
|
|
46641
47233
|
this.json(res, 403, { error: "Forbidden" });
|
|
46642
47234
|
return;
|
|
@@ -46661,14 +47253,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46661
47253
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
46662
47254
|
return;
|
|
46663
47255
|
}
|
|
46664
|
-
const fullPath =
|
|
47256
|
+
const fullPath = path20.resolve(dir, path20.normalize(filePath));
|
|
46665
47257
|
if (!fullPath.startsWith(dir)) {
|
|
46666
47258
|
this.json(res, 403, { error: "Forbidden" });
|
|
46667
47259
|
return;
|
|
46668
47260
|
}
|
|
46669
47261
|
try {
|
|
46670
47262
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
46671
|
-
fs14.mkdirSync(
|
|
47263
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
46672
47264
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
46673
47265
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
46674
47266
|
this.providerLoader.reload();
|
|
@@ -46685,7 +47277,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46685
47277
|
return;
|
|
46686
47278
|
}
|
|
46687
47279
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
46688
|
-
const p =
|
|
47280
|
+
const p = path20.join(dir, name);
|
|
46689
47281
|
if (fs14.existsSync(p)) {
|
|
46690
47282
|
const source = fs14.readFileSync(p, "utf-8");
|
|
46691
47283
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -46706,8 +47298,8 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46706
47298
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
46707
47299
|
return;
|
|
46708
47300
|
}
|
|
46709
|
-
const target = fs14.existsSync(
|
|
46710
|
-
const targetPath =
|
|
47301
|
+
const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
47302
|
+
const targetPath = path20.join(dir, target);
|
|
46711
47303
|
try {
|
|
46712
47304
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
46713
47305
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -46812,14 +47404,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46812
47404
|
child.stderr?.on("data", (d) => {
|
|
46813
47405
|
stderr += d.toString();
|
|
46814
47406
|
});
|
|
46815
|
-
await new Promise((
|
|
47407
|
+
await new Promise((resolve12) => {
|
|
46816
47408
|
const timer = setTimeout(() => {
|
|
46817
47409
|
child.kill();
|
|
46818
|
-
|
|
47410
|
+
resolve12();
|
|
46819
47411
|
}, timeout);
|
|
46820
47412
|
child.on("exit", () => {
|
|
46821
47413
|
clearTimeout(timer);
|
|
46822
|
-
|
|
47414
|
+
resolve12();
|
|
46823
47415
|
});
|
|
46824
47416
|
});
|
|
46825
47417
|
const elapsed = Date.now() - start;
|
|
@@ -46867,7 +47459,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46867
47459
|
}
|
|
46868
47460
|
let targetDir;
|
|
46869
47461
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
46870
|
-
const jsonPath =
|
|
47462
|
+
const jsonPath = path20.join(targetDir, "provider.json");
|
|
46871
47463
|
if (fs14.existsSync(jsonPath)) {
|
|
46872
47464
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
46873
47465
|
return;
|
|
@@ -46879,8 +47471,8 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46879
47471
|
const createdFiles = ["provider.json"];
|
|
46880
47472
|
if (result.files) {
|
|
46881
47473
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
46882
|
-
const fullPath =
|
|
46883
|
-
fs14.mkdirSync(
|
|
47474
|
+
const fullPath = path20.join(targetDir, relPath);
|
|
47475
|
+
fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
|
|
46884
47476
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
46885
47477
|
createdFiles.push(relPath);
|
|
46886
47478
|
}
|
|
@@ -46933,22 +47525,22 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46933
47525
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
46934
47526
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
46935
47527
|
try {
|
|
46936
|
-
return fs14.statSync(
|
|
47528
|
+
return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
46937
47529
|
} catch {
|
|
46938
47530
|
return false;
|
|
46939
47531
|
}
|
|
46940
47532
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
46941
47533
|
if (versions.length === 0) return null;
|
|
46942
|
-
return
|
|
47534
|
+
return path20.join(scriptsDir, versions[0]);
|
|
46943
47535
|
}
|
|
46944
47536
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
46945
|
-
const canonicalUserDir =
|
|
46946
|
-
const desiredDir = requestedDir ?
|
|
46947
|
-
const upstreamRoot =
|
|
46948
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
47537
|
+
const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
47538
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
47539
|
+
const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
|
|
47540
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
46949
47541
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
46950
47542
|
}
|
|
46951
|
-
if (
|
|
47543
|
+
if (path20.basename(desiredDir) !== type) {
|
|
46952
47544
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
46953
47545
|
}
|
|
46954
47546
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -46956,11 +47548,11 @@ data: ${JSON.stringify(msg.data)}
|
|
|
46956
47548
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
46957
47549
|
}
|
|
46958
47550
|
if (!fs14.existsSync(desiredDir)) {
|
|
46959
|
-
fs14.mkdirSync(
|
|
47551
|
+
fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
46960
47552
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
46961
47553
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
46962
47554
|
}
|
|
46963
|
-
const providerJson =
|
|
47555
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
46964
47556
|
if (!fs14.existsSync(providerJson)) {
|
|
46965
47557
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
46966
47558
|
}
|
|
@@ -47008,7 +47600,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47008
47600
|
setMode: "set_mode.js"
|
|
47009
47601
|
};
|
|
47010
47602
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
47011
|
-
const scriptsDir =
|
|
47603
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
47012
47604
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
47013
47605
|
if (latestScriptsDir) {
|
|
47014
47606
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -47019,7 +47611,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47019
47611
|
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
47020
47612
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
47021
47613
|
try {
|
|
47022
|
-
const content = fs14.readFileSync(
|
|
47614
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
|
|
47023
47615
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
47024
47616
|
lines.push("```javascript");
|
|
47025
47617
|
lines.push(content);
|
|
@@ -47036,7 +47628,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47036
47628
|
lines.push("");
|
|
47037
47629
|
for (const file2 of refFiles) {
|
|
47038
47630
|
try {
|
|
47039
|
-
const content = fs14.readFileSync(
|
|
47631
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
|
|
47040
47632
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
47041
47633
|
lines.push("```javascript");
|
|
47042
47634
|
lines.push(content);
|
|
@@ -47077,10 +47669,10 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47077
47669
|
lines.push("");
|
|
47078
47670
|
}
|
|
47079
47671
|
}
|
|
47080
|
-
const docsDir =
|
|
47672
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
47081
47673
|
const loadGuide = (name) => {
|
|
47082
47674
|
try {
|
|
47083
|
-
const p =
|
|
47675
|
+
const p = path20.join(docsDir, name);
|
|
47084
47676
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
47085
47677
|
} catch {
|
|
47086
47678
|
}
|
|
@@ -47254,7 +47846,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47254
47846
|
parseApproval: "parse_approval.js"
|
|
47255
47847
|
};
|
|
47256
47848
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
47257
|
-
const scriptsDir =
|
|
47849
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
47258
47850
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
47259
47851
|
if (latestScriptsDir) {
|
|
47260
47852
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -47266,7 +47858,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47266
47858
|
if (!file2.endsWith(".js")) continue;
|
|
47267
47859
|
if (!targetFileNames.has(file2)) continue;
|
|
47268
47860
|
try {
|
|
47269
|
-
const content = fs14.readFileSync(
|
|
47861
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
|
|
47270
47862
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
47271
47863
|
lines.push("```javascript");
|
|
47272
47864
|
lines.push(content);
|
|
@@ -47282,7 +47874,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47282
47874
|
lines.push("");
|
|
47283
47875
|
for (const file2 of refFiles) {
|
|
47284
47876
|
try {
|
|
47285
|
-
const content = fs14.readFileSync(
|
|
47877
|
+
const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
|
|
47286
47878
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
47287
47879
|
lines.push("```javascript");
|
|
47288
47880
|
lines.push(content);
|
|
@@ -47315,10 +47907,10 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47315
47907
|
lines.push("");
|
|
47316
47908
|
}
|
|
47317
47909
|
}
|
|
47318
|
-
const docsDir =
|
|
47910
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
47319
47911
|
const loadGuide = (name) => {
|
|
47320
47912
|
try {
|
|
47321
|
-
const p =
|
|
47913
|
+
const p = path20.join(docsDir, name);
|
|
47322
47914
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
47323
47915
|
} catch {
|
|
47324
47916
|
}
|
|
@@ -47494,14 +48086,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47494
48086
|
res.end(JSON.stringify(data, null, 2));
|
|
47495
48087
|
}
|
|
47496
48088
|
async readBody(req) {
|
|
47497
|
-
return new Promise((
|
|
48089
|
+
return new Promise((resolve12) => {
|
|
47498
48090
|
let body = "";
|
|
47499
48091
|
req.on("data", (chunk) => body += chunk);
|
|
47500
48092
|
req.on("end", () => {
|
|
47501
48093
|
try {
|
|
47502
|
-
|
|
48094
|
+
resolve12(JSON.parse(body));
|
|
47503
48095
|
} catch {
|
|
47504
|
-
|
|
48096
|
+
resolve12({});
|
|
47505
48097
|
}
|
|
47506
48098
|
});
|
|
47507
48099
|
});
|
|
@@ -47963,7 +48555,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
47963
48555
|
const deadline = Date.now() + timeoutMs;
|
|
47964
48556
|
while (Date.now() < deadline) {
|
|
47965
48557
|
if (await canConnect(endpoint)) return;
|
|
47966
|
-
await new Promise((
|
|
48558
|
+
await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
|
|
47967
48559
|
}
|
|
47968
48560
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
47969
48561
|
}
|
|
@@ -48117,10 +48709,10 @@ data: ${JSON.stringify(msg.data)}
|
|
|
48117
48709
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
48118
48710
|
const fs15 = await import("fs");
|
|
48119
48711
|
fs15.writeFileSync(vsixPath, buffer);
|
|
48120
|
-
return new Promise((
|
|
48712
|
+
return new Promise((resolve12) => {
|
|
48121
48713
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
48122
48714
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
|
|
48123
|
-
|
|
48715
|
+
resolve12({
|
|
48124
48716
|
extensionId: extension.id,
|
|
48125
48717
|
marketplaceId: extension.marketplaceId,
|
|
48126
48718
|
success: !error48,
|
|
@@ -48133,11 +48725,11 @@ data: ${JSON.stringify(msg.data)}
|
|
|
48133
48725
|
} catch (e) {
|
|
48134
48726
|
}
|
|
48135
48727
|
}
|
|
48136
|
-
return new Promise((
|
|
48728
|
+
return new Promise((resolve12) => {
|
|
48137
48729
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
48138
48730
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
|
|
48139
48731
|
if (error48) {
|
|
48140
|
-
|
|
48732
|
+
resolve12({
|
|
48141
48733
|
extensionId: extension.id,
|
|
48142
48734
|
marketplaceId: extension.marketplaceId,
|
|
48143
48735
|
success: false,
|
|
@@ -48145,7 +48737,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
48145
48737
|
error: stderr || error48.message
|
|
48146
48738
|
});
|
|
48147
48739
|
} else {
|
|
48148
|
-
|
|
48740
|
+
resolve12({
|
|
48149
48741
|
extensionId: extension.id,
|
|
48150
48742
|
marketplaceId: extension.marketplaceId,
|
|
48151
48743
|
success: true,
|
|
@@ -48277,13 +48869,32 @@ data: ${JSON.stringify(msg.data)}
|
|
|
48277
48869
|
const detectedIdesRef = { value: [] };
|
|
48278
48870
|
let agentStreamManager = null;
|
|
48279
48871
|
let poller = null;
|
|
48872
|
+
const refreshProviderAvailability = async (providerType) => {
|
|
48873
|
+
const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
|
|
48874
|
+
const targetCategory = targetProvider?.category;
|
|
48875
|
+
if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
|
|
48876
|
+
if (providerType && targetProvider) {
|
|
48877
|
+
const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
|
|
48878
|
+
providerLoader.setProviderAvailability(targetProvider.type, {
|
|
48879
|
+
installed: !!detected,
|
|
48880
|
+
detectedPath: detected?.path || null
|
|
48881
|
+
});
|
|
48882
|
+
} else {
|
|
48883
|
+
providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
|
|
48884
|
+
}
|
|
48885
|
+
}
|
|
48886
|
+
if (!providerType || targetCategory === "ide") {
|
|
48887
|
+
detectedIdesRef.value = await detectIDEs(providerLoader);
|
|
48888
|
+
providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
|
|
48889
|
+
}
|
|
48890
|
+
};
|
|
48280
48891
|
const cliManager = new DaemonCliManager({
|
|
48281
48892
|
...config2.cliManagerDeps,
|
|
48282
48893
|
getInstanceManager: () => instanceManager,
|
|
48283
48894
|
getSessionRegistry: () => sessionRegistry
|
|
48284
48895
|
}, providerLoader);
|
|
48285
48896
|
LOG2.info("Init", "Detecting IDEs...");
|
|
48286
|
-
|
|
48897
|
+
await refreshProviderAvailability();
|
|
48287
48898
|
const installed = detectedIdesRef.value.filter((i) => i.installed);
|
|
48288
48899
|
LOG2.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
|
|
48289
48900
|
const cdpSetupContext = {
|
|
@@ -48323,7 +48934,11 @@ data: ${JSON.stringify(msg.data)}
|
|
|
48323
48934
|
adapters: cliManager.adapters,
|
|
48324
48935
|
providerLoader,
|
|
48325
48936
|
instanceManager,
|
|
48326
|
-
sessionRegistry
|
|
48937
|
+
sessionRegistry,
|
|
48938
|
+
onProviderSettingChanged: async (providerType) => {
|
|
48939
|
+
await refreshProviderAvailability(providerType);
|
|
48940
|
+
config2.onStatusChange?.();
|
|
48941
|
+
}
|
|
48327
48942
|
});
|
|
48328
48943
|
agentStreamManager = new DaemonAgentStreamManager(
|
|
48329
48944
|
LOG2.forComponent("AgentStream").asLogFn(),
|
|
@@ -48747,6 +49362,9 @@ var StandaloneSessionHostControlPlane = class {
|
|
|
48747
49362
|
async forceDetachClient(sessionId, clientId) {
|
|
48748
49363
|
return this.request("force_detach_client", { sessionId, clientId });
|
|
48749
49364
|
}
|
|
49365
|
+
async pruneDuplicateSessions(payload = {}) {
|
|
49366
|
+
return this.request("prune_duplicate_sessions", payload);
|
|
49367
|
+
}
|
|
48750
49368
|
async acquireWrite(payload) {
|
|
48751
49369
|
return this.request("acquire_write", payload);
|
|
48752
49370
|
}
|