@adhdev/daemon-core 0.8.12 → 0.8.14
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/cli-adapters/spawn-env.d.ts +8 -0
- package/dist/cli-adapters/terminal-screen.d.ts +5 -3
- package/dist/detection/cli-detector.d.ts +1 -1
- package/dist/index.js +347 -236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +343 -229
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +5 -3
- package/dist/providers/contracts.d.ts +38 -0
- package/node_modules/@adhdev/session-host-core/dist/index.d.mts +30 -1
- package/node_modules/@adhdev/session-host-core/dist/index.d.ts +30 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js +73 -6
- package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.mjs +77 -6
- package/node_modules/@adhdev/session-host-core/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -3
- package/src/cli-adapters/provider-cli-adapter.ts +36 -62
- package/src/cli-adapters/pty-transport.ts +13 -1
- package/src/cli-adapters/spawn-env.ts +12 -0
- package/src/cli-adapters/terminal-screen.ts +12 -3
- package/src/commands/cli-manager.ts +13 -2
- package/src/commands/workspace-commands.ts +37 -9
- package/src/detection/cli-detector.ts +36 -2
- package/src/providers/cli-provider-instance.ts +62 -36
- package/src/providers/contracts.ts +39 -0
package/dist/index.mjs
CHANGED
|
@@ -632,6 +632,13 @@ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind)
|
|
|
632
632
|
const key = `${preference}:${ghosttyAvailable}:${backendKind}`;
|
|
633
633
|
if (loggedTerminalBackends.has(key)) return;
|
|
634
634
|
loggedTerminalBackends.add(key);
|
|
635
|
+
if (backendKind === "xterm" && preference !== "xterm" && !ghosttyAvailable) {
|
|
636
|
+
LOG.warn(
|
|
637
|
+
"Terminal",
|
|
638
|
+
`[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`
|
|
639
|
+
);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
635
642
|
LOG.info(
|
|
636
643
|
"Terminal",
|
|
637
644
|
`[terminal-screen] backend=${backendKind} preference=${preference} ghosttyAvailable=${ghosttyAvailable}`
|
|
@@ -694,6 +701,7 @@ var init_terminal_screen = __esm({
|
|
|
694
701
|
});
|
|
695
702
|
|
|
696
703
|
// src/cli-adapters/pty-transport.ts
|
|
704
|
+
import * as os7 from "os";
|
|
697
705
|
var pty, NodePtyRuntimeTransport, NodePtyTransportFactory;
|
|
698
706
|
var init_pty_transport = __esm({
|
|
699
707
|
"src/cli-adapters/pty-transport.ts"() {
|
|
@@ -734,11 +742,21 @@ var init_pty_transport = __esm({
|
|
|
734
742
|
NodePtyTransportFactory = class {
|
|
735
743
|
spawn(command, args, options) {
|
|
736
744
|
if (!pty) throw new Error("node-pty is not installed");
|
|
745
|
+
let cwd = options.cwd;
|
|
746
|
+
if (cwd) {
|
|
747
|
+
try {
|
|
748
|
+
const fs15 = __require("fs");
|
|
749
|
+
const stat = fs15.statSync(cwd);
|
|
750
|
+
if (!stat.isDirectory()) cwd = os7.homedir();
|
|
751
|
+
} catch {
|
|
752
|
+
cwd = os7.homedir();
|
|
753
|
+
}
|
|
754
|
+
}
|
|
737
755
|
const handle = pty.spawn(command, args, {
|
|
738
756
|
name: "xterm-256color",
|
|
739
757
|
cols: options.cols,
|
|
740
758
|
rows: options.rows,
|
|
741
|
-
cwd
|
|
759
|
+
cwd,
|
|
742
760
|
env: options.env
|
|
743
761
|
});
|
|
744
762
|
return new NodePtyRuntimeTransport(handle);
|
|
@@ -747,13 +765,25 @@ var init_pty_transport = __esm({
|
|
|
747
765
|
}
|
|
748
766
|
});
|
|
749
767
|
|
|
768
|
+
// src/cli-adapters/spawn-env.ts
|
|
769
|
+
import {
|
|
770
|
+
sanitizeSpawnEnv,
|
|
771
|
+
applyTerminalColorEnv,
|
|
772
|
+
ensureNodePtySpawnHelperPermissions
|
|
773
|
+
} from "@adhdev/session-host-core";
|
|
774
|
+
var init_spawn_env = __esm({
|
|
775
|
+
"src/cli-adapters/spawn-env.ts"() {
|
|
776
|
+
"use strict";
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
|
|
750
780
|
// src/cli-adapters/provider-cli-adapter.ts
|
|
751
781
|
var provider_cli_adapter_exports = {};
|
|
752
782
|
__export(provider_cli_adapter_exports, {
|
|
753
783
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
754
784
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
755
785
|
});
|
|
756
|
-
import * as
|
|
786
|
+
import * as os8 from "os";
|
|
757
787
|
import * as path7 from "path";
|
|
758
788
|
import { execSync as execSync3 } from "child_process";
|
|
759
789
|
function stripAnsi(str) {
|
|
@@ -765,32 +795,6 @@ function stripTerminalNoise(str) {
|
|
|
765
795
|
function sanitizeTerminalText(str) {
|
|
766
796
|
return stripTerminalNoise(stripAnsi(str));
|
|
767
797
|
}
|
|
768
|
-
function applyPreferredTerminalColorEnv(env) {
|
|
769
|
-
if (env.NO_COLOR) return;
|
|
770
|
-
if (!env.TERM || env.TERM === "xterm-color") {
|
|
771
|
-
env.TERM = "xterm-256color";
|
|
772
|
-
}
|
|
773
|
-
if (!env.COLORTERM) env.COLORTERM = "truecolor";
|
|
774
|
-
if (process.platform === "win32") {
|
|
775
|
-
if (!env.FORCE_COLOR) env.FORCE_COLOR = "1";
|
|
776
|
-
if (!env.CLICOLOR) env.CLICOLOR = "1";
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
function buildCliSpawnEnv(baseEnv, overrides) {
|
|
780
|
-
const env = {};
|
|
781
|
-
const source = { ...baseEnv, ...overrides || {} };
|
|
782
|
-
for (const [key, value] of Object.entries(source)) {
|
|
783
|
-
if (typeof value !== "string") continue;
|
|
784
|
-
env[key] = value;
|
|
785
|
-
}
|
|
786
|
-
for (const key of Object.keys(env)) {
|
|
787
|
-
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_")) {
|
|
788
|
-
delete env[key];
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
applyPreferredTerminalColorEnv(env);
|
|
792
|
-
return env;
|
|
793
|
-
}
|
|
794
798
|
function computeTerminalQueryTail(buffer) {
|
|
795
799
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
796
800
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -804,7 +808,7 @@ function computeTerminalQueryTail(buffer) {
|
|
|
804
808
|
return "";
|
|
805
809
|
}
|
|
806
810
|
function findBinary(name) {
|
|
807
|
-
const isWin =
|
|
811
|
+
const isWin = os8.platform() === "win32";
|
|
808
812
|
try {
|
|
809
813
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
810
814
|
return execSync3(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
@@ -852,7 +856,7 @@ function looksLikeMachOOrElf(filePath) {
|
|
|
852
856
|
}
|
|
853
857
|
function shSingleQuote(arg) {
|
|
854
858
|
if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
|
|
855
|
-
if (
|
|
859
|
+
if (os8.platform() === "win32") {
|
|
856
860
|
return `"${arg.replace(/"/g, '""')}"`;
|
|
857
861
|
}
|
|
858
862
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
@@ -919,34 +923,21 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
919
923
|
}
|
|
920
924
|
};
|
|
921
925
|
}
|
|
922
|
-
var pty2, ProviderCliAdapter;
|
|
926
|
+
var pty2, buildCliSpawnEnv, ProviderCliAdapter;
|
|
923
927
|
var init_provider_cli_adapter = __esm({
|
|
924
928
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
925
929
|
"use strict";
|
|
926
930
|
init_logger();
|
|
927
931
|
init_terminal_screen();
|
|
928
932
|
init_pty_transport();
|
|
933
|
+
init_spawn_env();
|
|
929
934
|
try {
|
|
930
935
|
pty2 = __require("node-pty");
|
|
931
|
-
|
|
932
|
-
try {
|
|
933
|
-
const fs15 = __require("fs");
|
|
934
|
-
const ptyDir = path7.resolve(path7.dirname(__require.resolve("node-pty")), "..");
|
|
935
|
-
const platformArch = `${os7.platform()}-${os7.arch()}`;
|
|
936
|
-
const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
937
|
-
if (fs15.existsSync(helper)) {
|
|
938
|
-
const stat = fs15.statSync(helper);
|
|
939
|
-
if (!(stat.mode & 73)) {
|
|
940
|
-
fs15.chmodSync(helper, stat.mode | 493);
|
|
941
|
-
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
} catch {
|
|
945
|
-
}
|
|
946
|
-
}
|
|
936
|
+
ensureNodePtySpawnHelperPermissions((msg) => LOG.info("CLI", msg));
|
|
947
937
|
} catch {
|
|
948
938
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
|
|
949
939
|
}
|
|
940
|
+
buildCliSpawnEnv = sanitizeSpawnEnv;
|
|
950
941
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
951
942
|
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
952
943
|
this.extraArgs = extraArgs;
|
|
@@ -954,7 +945,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
954
945
|
this.transportFactory = transportFactory;
|
|
955
946
|
this.cliType = provider.type;
|
|
956
947
|
this.cliName = provider.name;
|
|
957
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
948
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os8.homedir()) : workingDir;
|
|
958
949
|
const t = provider.timeouts || {};
|
|
959
950
|
this.timeouts = {
|
|
960
951
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -1261,7 +1252,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1261
1252
|
if (this.ptyProcess) return;
|
|
1262
1253
|
const { spawn: spawnConfig } = this.provider;
|
|
1263
1254
|
const binaryPath = findBinary(spawnConfig.command);
|
|
1264
|
-
const isWin =
|
|
1255
|
+
const isWin = os8.platform() === "win32";
|
|
1265
1256
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
1266
1257
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1267
1258
|
this.resetTraceSession();
|
|
@@ -1269,13 +1260,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
1269
1260
|
let shellArgs;
|
|
1270
1261
|
const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1271
1262
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1272
|
-
const
|
|
1263
|
+
const useShellWin = isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1264
|
+
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1273
1265
|
if (useShell) {
|
|
1274
1266
|
if (!spawnConfig.shell && !isWin) {
|
|
1275
1267
|
LOG.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
|
|
1276
1268
|
}
|
|
1277
1269
|
if (isCmdShim) {
|
|
1278
1270
|
LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell for .cmd/.bat shim: ${binaryPath}`);
|
|
1271
|
+
} else if (isWin) {
|
|
1272
|
+
LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell on Windows: ${binaryPath}`);
|
|
1279
1273
|
}
|
|
1280
1274
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
1281
1275
|
if (isWin) {
|
|
@@ -1285,6 +1279,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1285
1279
|
shellArgs = ["-l", "-c", fullCmd];
|
|
1286
1280
|
}
|
|
1287
1281
|
} else {
|
|
1282
|
+
if (isWin && spawnConfig.shell) {
|
|
1283
|
+
LOG.info("CLI", `[${this.cliType}] Spawning Windows binary directly without cmd.exe: ${binaryPath}`);
|
|
1284
|
+
}
|
|
1288
1285
|
shellCmd = binaryPath;
|
|
1289
1286
|
shellArgs = allArgs;
|
|
1290
1287
|
}
|
|
@@ -1313,6 +1310,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1313
1310
|
shellArgs = ["-l", "-c", fullCmd];
|
|
1314
1311
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
1315
1312
|
} else {
|
|
1313
|
+
if (isWin) {
|
|
1314
|
+
const hint = /error code 267|ERROR_DIRECTORY/i.test(msg) ? " (working directory does not exist or is not a directory)" : /error code 740|elevation/i.test(msg) ? " (requires administrator privileges)" : /error code 2|ENOENT|not found/i.test(msg) ? ` (executable not found: ${shellCmd})` : "";
|
|
1315
|
+
if (hint) {
|
|
1316
|
+
throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1316
1319
|
throw err;
|
|
1317
1320
|
}
|
|
1318
1321
|
}
|
|
@@ -1487,7 +1490,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1487
1490
|
`[${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)}`
|
|
1488
1491
|
);
|
|
1489
1492
|
}
|
|
1490
|
-
await new Promise((
|
|
1493
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1491
1494
|
}
|
|
1492
1495
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1493
1496
|
LOG.warn(
|
|
@@ -1874,7 +1877,7 @@ ${data.message || ""}`.trim();
|
|
|
1874
1877
|
if (this.startupParseGate) {
|
|
1875
1878
|
const deadline = Date.now() + 1e4;
|
|
1876
1879
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
1877
|
-
await new Promise((
|
|
1880
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1878
1881
|
}
|
|
1879
1882
|
}
|
|
1880
1883
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
@@ -2065,7 +2068,8 @@ ${data.message || ""}`.trim();
|
|
|
2065
2068
|
const payload = stopCommand.endsWith("\r") || stopCommand.endsWith("\n") ? stopCommand : `${stopCommand}${this.sendKey}`;
|
|
2066
2069
|
this.ptyProcess.write(payload);
|
|
2067
2070
|
};
|
|
2068
|
-
|
|
2071
|
+
const interruptGraceMs = typeof resume.interruptGraceMs === "number" ? Math.max(100, resume.interruptGraceMs) : 500;
|
|
2072
|
+
if (wasProcessing) setTimeout(writeCommand, interruptGraceMs);
|
|
2069
2073
|
else writeCommand();
|
|
2070
2074
|
} else {
|
|
2071
2075
|
this.ptyProcess.write("");
|
|
@@ -2081,17 +2085,17 @@ ${data.message || ""}`.trim();
|
|
|
2081
2085
|
}
|
|
2082
2086
|
}
|
|
2083
2087
|
waitForStopped(timeoutMs) {
|
|
2084
|
-
return new Promise((
|
|
2088
|
+
return new Promise((resolve9) => {
|
|
2085
2089
|
const startedAt = Date.now();
|
|
2086
2090
|
const timer = setInterval(() => {
|
|
2087
2091
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
2088
2092
|
clearInterval(timer);
|
|
2089
|
-
|
|
2093
|
+
resolve9(true);
|
|
2090
2094
|
return;
|
|
2091
2095
|
}
|
|
2092
2096
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
2093
2097
|
clearInterval(timer);
|
|
2094
|
-
|
|
2098
|
+
resolve9(false);
|
|
2095
2099
|
}
|
|
2096
2100
|
}, 100);
|
|
2097
2101
|
});
|
|
@@ -2110,6 +2114,18 @@ ${data.message || ""}`.trim();
|
|
|
2110
2114
|
clearTimeout(this.submitRetryTimer);
|
|
2111
2115
|
this.submitRetryTimer = null;
|
|
2112
2116
|
}
|
|
2117
|
+
if (this.responseTimeout) {
|
|
2118
|
+
clearTimeout(this.responseTimeout);
|
|
2119
|
+
this.responseTimeout = null;
|
|
2120
|
+
}
|
|
2121
|
+
if (this.idleTimeout) {
|
|
2122
|
+
clearTimeout(this.idleTimeout);
|
|
2123
|
+
this.idleTimeout = null;
|
|
2124
|
+
}
|
|
2125
|
+
if (this.pendingScriptStatusTimer) {
|
|
2126
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2127
|
+
this.pendingScriptStatusTimer = null;
|
|
2128
|
+
}
|
|
2113
2129
|
if (this.pendingOutputParseTimer) {
|
|
2114
2130
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2115
2131
|
this.pendingOutputParseTimer = null;
|
|
@@ -2151,6 +2167,18 @@ ${data.message || ""}`.trim();
|
|
|
2151
2167
|
clearTimeout(this.submitRetryTimer);
|
|
2152
2168
|
this.submitRetryTimer = null;
|
|
2153
2169
|
}
|
|
2170
|
+
if (this.responseTimeout) {
|
|
2171
|
+
clearTimeout(this.responseTimeout);
|
|
2172
|
+
this.responseTimeout = null;
|
|
2173
|
+
}
|
|
2174
|
+
if (this.idleTimeout) {
|
|
2175
|
+
clearTimeout(this.idleTimeout);
|
|
2176
|
+
this.idleTimeout = null;
|
|
2177
|
+
}
|
|
2178
|
+
if (this.pendingScriptStatusTimer) {
|
|
2179
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2180
|
+
this.pendingScriptStatusTimer = null;
|
|
2181
|
+
}
|
|
2154
2182
|
if (this.pendingOutputParseTimer) {
|
|
2155
2183
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2156
2184
|
this.pendingOutputParseTimer = null;
|
|
@@ -2665,20 +2693,20 @@ function checkPathExists(paths) {
|
|
|
2665
2693
|
return null;
|
|
2666
2694
|
}
|
|
2667
2695
|
async function detectIDEs() {
|
|
2668
|
-
const
|
|
2696
|
+
const os18 = platform();
|
|
2669
2697
|
const results = [];
|
|
2670
2698
|
for (const def of getMergedDefinitions()) {
|
|
2671
2699
|
const cliPath = findCliCommand(def.cli);
|
|
2672
|
-
const appPath = checkPathExists(def.paths[
|
|
2700
|
+
const appPath = checkPathExists(def.paths[os18] || []);
|
|
2673
2701
|
const installed = !!(cliPath || appPath);
|
|
2674
2702
|
let resolvedCli = cliPath;
|
|
2675
|
-
if (!resolvedCli && appPath &&
|
|
2703
|
+
if (!resolvedCli && appPath && os18 === "darwin") {
|
|
2676
2704
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
2677
2705
|
if (existsSync3(bundledCli)) resolvedCli = bundledCli;
|
|
2678
2706
|
}
|
|
2679
|
-
if (!resolvedCli && appPath &&
|
|
2680
|
-
const { dirname:
|
|
2681
|
-
const appDir =
|
|
2707
|
+
if (!resolvedCli && appPath && os18 === "win32") {
|
|
2708
|
+
const { dirname: dirname6 } = await import("path");
|
|
2709
|
+
const appDir = dirname6(appPath);
|
|
2682
2710
|
const candidates = [
|
|
2683
2711
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
2684
2712
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -2716,15 +2744,15 @@ function parseVersion(raw) {
|
|
|
2716
2744
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
2717
2745
|
}
|
|
2718
2746
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
2719
|
-
return new Promise((
|
|
2747
|
+
return new Promise((resolve9) => {
|
|
2720
2748
|
const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
2721
2749
|
if (err || !stdout?.trim()) {
|
|
2722
|
-
|
|
2750
|
+
resolve9(null);
|
|
2723
2751
|
} else {
|
|
2724
|
-
|
|
2752
|
+
resolve9(stdout.trim());
|
|
2725
2753
|
}
|
|
2726
2754
|
});
|
|
2727
|
-
child.on("error", () =>
|
|
2755
|
+
child.on("error", () => resolve9(null));
|
|
2728
2756
|
});
|
|
2729
2757
|
}
|
|
2730
2758
|
async function detectCLIs(providerLoader) {
|
|
@@ -2764,6 +2792,39 @@ async function detectCLIs(providerLoader) {
|
|
|
2764
2792
|
}
|
|
2765
2793
|
async function detectCLI(cliId, providerLoader) {
|
|
2766
2794
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
2795
|
+
if (providerLoader) {
|
|
2796
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
2797
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
2798
|
+
if (target) {
|
|
2799
|
+
const platform9 = os2.platform();
|
|
2800
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
2801
|
+
try {
|
|
2802
|
+
const pathResult = await execAsync(`${whichCmd} ${target.command}`);
|
|
2803
|
+
if (!pathResult) return null;
|
|
2804
|
+
const firstPath = pathResult.split("\n")[0];
|
|
2805
|
+
let version;
|
|
2806
|
+
try {
|
|
2807
|
+
const versionCommands = [
|
|
2808
|
+
target.versionCommand,
|
|
2809
|
+
`${target.command} --version`,
|
|
2810
|
+
`${target.command} -V`,
|
|
2811
|
+
`${target.command} -v`
|
|
2812
|
+
].filter((v) => !!v);
|
|
2813
|
+
for (const versionCommand of versionCommands) {
|
|
2814
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
2815
|
+
if (versionResult) {
|
|
2816
|
+
version = parseVersion(versionResult);
|
|
2817
|
+
break;
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
} catch {
|
|
2821
|
+
}
|
|
2822
|
+
return { ...target, installed: true, version, path: firstPath };
|
|
2823
|
+
} catch {
|
|
2824
|
+
return null;
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2767
2828
|
const all = await detectCLIs(providerLoader);
|
|
2768
2829
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
2769
2830
|
}
|
|
@@ -2891,7 +2952,7 @@ var DaemonCdpManager = class {
|
|
|
2891
2952
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
2892
2953
|
*/
|
|
2893
2954
|
static listAllTargets(port) {
|
|
2894
|
-
return new Promise((
|
|
2955
|
+
return new Promise((resolve9) => {
|
|
2895
2956
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2896
2957
|
let data = "";
|
|
2897
2958
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2907,16 +2968,16 @@ var DaemonCdpManager = class {
|
|
|
2907
2968
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
2908
2969
|
);
|
|
2909
2970
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
2910
|
-
|
|
2971
|
+
resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
2911
2972
|
} catch {
|
|
2912
|
-
|
|
2973
|
+
resolve9([]);
|
|
2913
2974
|
}
|
|
2914
2975
|
});
|
|
2915
2976
|
});
|
|
2916
|
-
req.on("error", () =>
|
|
2977
|
+
req.on("error", () => resolve9([]));
|
|
2917
2978
|
req.setTimeout(2e3, () => {
|
|
2918
2979
|
req.destroy();
|
|
2919
|
-
|
|
2980
|
+
resolve9([]);
|
|
2920
2981
|
});
|
|
2921
2982
|
});
|
|
2922
2983
|
}
|
|
@@ -2956,7 +3017,7 @@ var DaemonCdpManager = class {
|
|
|
2956
3017
|
}
|
|
2957
3018
|
}
|
|
2958
3019
|
findTargetOnPort(port) {
|
|
2959
|
-
return new Promise((
|
|
3020
|
+
return new Promise((resolve9) => {
|
|
2960
3021
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2961
3022
|
let data = "";
|
|
2962
3023
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2967,7 +3028,7 @@ var DaemonCdpManager = class {
|
|
|
2967
3028
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
2968
3029
|
);
|
|
2969
3030
|
if (pages.length === 0) {
|
|
2970
|
-
|
|
3031
|
+
resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
2971
3032
|
return;
|
|
2972
3033
|
}
|
|
2973
3034
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -2977,24 +3038,24 @@ var DaemonCdpManager = class {
|
|
|
2977
3038
|
const specific = list.find((t) => t.id === this._targetId);
|
|
2978
3039
|
if (specific) {
|
|
2979
3040
|
this._pageTitle = specific.title || "";
|
|
2980
|
-
|
|
3041
|
+
resolve9(specific);
|
|
2981
3042
|
} else {
|
|
2982
3043
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
2983
|
-
|
|
3044
|
+
resolve9(null);
|
|
2984
3045
|
}
|
|
2985
3046
|
return;
|
|
2986
3047
|
}
|
|
2987
3048
|
this._pageTitle = list[0]?.title || "";
|
|
2988
|
-
|
|
3049
|
+
resolve9(list[0]);
|
|
2989
3050
|
} catch {
|
|
2990
|
-
|
|
3051
|
+
resolve9(null);
|
|
2991
3052
|
}
|
|
2992
3053
|
});
|
|
2993
3054
|
});
|
|
2994
|
-
req.on("error", () =>
|
|
3055
|
+
req.on("error", () => resolve9(null));
|
|
2995
3056
|
req.setTimeout(2e3, () => {
|
|
2996
3057
|
req.destroy();
|
|
2997
|
-
|
|
3058
|
+
resolve9(null);
|
|
2998
3059
|
});
|
|
2999
3060
|
});
|
|
3000
3061
|
}
|
|
@@ -3005,7 +3066,7 @@ var DaemonCdpManager = class {
|
|
|
3005
3066
|
this.extensionProviders = providers;
|
|
3006
3067
|
}
|
|
3007
3068
|
connectToTarget(wsUrl) {
|
|
3008
|
-
return new Promise((
|
|
3069
|
+
return new Promise((resolve9) => {
|
|
3009
3070
|
this.ws = new WebSocket(wsUrl);
|
|
3010
3071
|
this.ws.on("open", async () => {
|
|
3011
3072
|
this._connected = true;
|
|
@@ -3015,17 +3076,17 @@ var DaemonCdpManager = class {
|
|
|
3015
3076
|
}
|
|
3016
3077
|
this.connectBrowserWs().catch(() => {
|
|
3017
3078
|
});
|
|
3018
|
-
|
|
3079
|
+
resolve9(true);
|
|
3019
3080
|
});
|
|
3020
3081
|
this.ws.on("message", (data) => {
|
|
3021
3082
|
try {
|
|
3022
3083
|
const msg = JSON.parse(data.toString());
|
|
3023
3084
|
if (msg.id && this.pending.has(msg.id)) {
|
|
3024
|
-
const { resolve:
|
|
3085
|
+
const { resolve: resolve10, reject } = this.pending.get(msg.id);
|
|
3025
3086
|
this.pending.delete(msg.id);
|
|
3026
3087
|
this.failureCount = 0;
|
|
3027
3088
|
if (msg.error) reject(new Error(msg.error.message));
|
|
3028
|
-
else
|
|
3089
|
+
else resolve10(msg.result);
|
|
3029
3090
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
3030
3091
|
this.contexts.add(msg.params.context.id);
|
|
3031
3092
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -3048,7 +3109,7 @@ var DaemonCdpManager = class {
|
|
|
3048
3109
|
this.ws.on("error", (err) => {
|
|
3049
3110
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
3050
3111
|
this._connected = false;
|
|
3051
|
-
|
|
3112
|
+
resolve9(false);
|
|
3052
3113
|
});
|
|
3053
3114
|
});
|
|
3054
3115
|
}
|
|
@@ -3062,7 +3123,7 @@ var DaemonCdpManager = class {
|
|
|
3062
3123
|
return;
|
|
3063
3124
|
}
|
|
3064
3125
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
3065
|
-
await new Promise((
|
|
3126
|
+
await new Promise((resolve9, reject) => {
|
|
3066
3127
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
3067
3128
|
this.browserWs.on("open", async () => {
|
|
3068
3129
|
this._browserConnected = true;
|
|
@@ -3072,16 +3133,16 @@ var DaemonCdpManager = class {
|
|
|
3072
3133
|
} catch (e) {
|
|
3073
3134
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
3074
3135
|
}
|
|
3075
|
-
|
|
3136
|
+
resolve9();
|
|
3076
3137
|
});
|
|
3077
3138
|
this.browserWs.on("message", (data) => {
|
|
3078
3139
|
try {
|
|
3079
3140
|
const msg = JSON.parse(data.toString());
|
|
3080
3141
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
3081
|
-
const { resolve:
|
|
3142
|
+
const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
|
|
3082
3143
|
this.browserPending.delete(msg.id);
|
|
3083
3144
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
3084
|
-
else
|
|
3145
|
+
else resolve10(msg.result);
|
|
3085
3146
|
}
|
|
3086
3147
|
} catch {
|
|
3087
3148
|
}
|
|
@@ -3101,31 +3162,31 @@ var DaemonCdpManager = class {
|
|
|
3101
3162
|
}
|
|
3102
3163
|
}
|
|
3103
3164
|
getBrowserWsUrl() {
|
|
3104
|
-
return new Promise((
|
|
3165
|
+
return new Promise((resolve9) => {
|
|
3105
3166
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
3106
3167
|
let data = "";
|
|
3107
3168
|
res.on("data", (chunk) => data += chunk.toString());
|
|
3108
3169
|
res.on("end", () => {
|
|
3109
3170
|
try {
|
|
3110
3171
|
const info = JSON.parse(data);
|
|
3111
|
-
|
|
3172
|
+
resolve9(info.webSocketDebuggerUrl || null);
|
|
3112
3173
|
} catch {
|
|
3113
|
-
|
|
3174
|
+
resolve9(null);
|
|
3114
3175
|
}
|
|
3115
3176
|
});
|
|
3116
3177
|
});
|
|
3117
|
-
req.on("error", () =>
|
|
3178
|
+
req.on("error", () => resolve9(null));
|
|
3118
3179
|
req.setTimeout(3e3, () => {
|
|
3119
3180
|
req.destroy();
|
|
3120
|
-
|
|
3181
|
+
resolve9(null);
|
|
3121
3182
|
});
|
|
3122
3183
|
});
|
|
3123
3184
|
}
|
|
3124
3185
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
3125
|
-
return new Promise((
|
|
3186
|
+
return new Promise((resolve9, reject) => {
|
|
3126
3187
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
3127
3188
|
const id = this.browserMsgId++;
|
|
3128
|
-
this.browserPending.set(id, { resolve:
|
|
3189
|
+
this.browserPending.set(id, { resolve: resolve9, reject });
|
|
3129
3190
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
3130
3191
|
setTimeout(() => {
|
|
3131
3192
|
if (this.browserPending.has(id)) {
|
|
@@ -3165,11 +3226,11 @@ var DaemonCdpManager = class {
|
|
|
3165
3226
|
}
|
|
3166
3227
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
3167
3228
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
3168
|
-
return new Promise((
|
|
3229
|
+
return new Promise((resolve9, reject) => {
|
|
3169
3230
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
3170
3231
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
3171
3232
|
const id = this.msgId++;
|
|
3172
|
-
this.pending.set(id, { resolve:
|
|
3233
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
3173
3234
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
3174
3235
|
setTimeout(() => {
|
|
3175
3236
|
if (this.pending.has(id)) {
|
|
@@ -3418,7 +3479,7 @@ var DaemonCdpManager = class {
|
|
|
3418
3479
|
const browserWs = this.browserWs;
|
|
3419
3480
|
let msgId = this.browserMsgId;
|
|
3420
3481
|
const sendWs = (method, params = {}, sessionId) => {
|
|
3421
|
-
return new Promise((
|
|
3482
|
+
return new Promise((resolve9, reject) => {
|
|
3422
3483
|
const mid = msgId++;
|
|
3423
3484
|
this.browserMsgId = msgId;
|
|
3424
3485
|
const handler = (raw) => {
|
|
@@ -3427,7 +3488,7 @@ var DaemonCdpManager = class {
|
|
|
3427
3488
|
if (msg.id === mid) {
|
|
3428
3489
|
browserWs.removeListener("message", handler);
|
|
3429
3490
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
3430
|
-
else
|
|
3491
|
+
else resolve9(msg.result);
|
|
3431
3492
|
}
|
|
3432
3493
|
} catch {
|
|
3433
3494
|
}
|
|
@@ -3618,14 +3679,14 @@ var DaemonCdpManager = class {
|
|
|
3618
3679
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
3619
3680
|
throw new Error("CDP not connected");
|
|
3620
3681
|
}
|
|
3621
|
-
return new Promise((
|
|
3682
|
+
return new Promise((resolve9, reject) => {
|
|
3622
3683
|
const id = getNextId();
|
|
3623
3684
|
pendingMap.set(id, {
|
|
3624
3685
|
resolve: (result) => {
|
|
3625
3686
|
if (result?.result?.subtype === "error") {
|
|
3626
3687
|
reject(new Error(result.result.description));
|
|
3627
3688
|
} else {
|
|
3628
|
-
|
|
3689
|
+
resolve9(result?.result?.value);
|
|
3629
3690
|
}
|
|
3630
3691
|
},
|
|
3631
3692
|
reject
|
|
@@ -3657,10 +3718,10 @@ var DaemonCdpManager = class {
|
|
|
3657
3718
|
throw new Error("CDP not connected");
|
|
3658
3719
|
}
|
|
3659
3720
|
const sendViaSession = (method, params = {}) => {
|
|
3660
|
-
return new Promise((
|
|
3721
|
+
return new Promise((resolve9, reject) => {
|
|
3661
3722
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
3662
3723
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
3663
|
-
pendingMap.set(id, { resolve:
|
|
3724
|
+
pendingMap.set(id, { resolve: resolve9, reject });
|
|
3664
3725
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
3665
3726
|
setTimeout(() => {
|
|
3666
3727
|
if (pendingMap.has(id)) {
|
|
@@ -7192,8 +7253,24 @@ function handleSetIdeExtension(h, args) {
|
|
|
7192
7253
|
|
|
7193
7254
|
// src/commands/workspace-commands.ts
|
|
7194
7255
|
init_config();
|
|
7256
|
+
function loadWorkspaceConfig() {
|
|
7257
|
+
try {
|
|
7258
|
+
return loadConfig();
|
|
7259
|
+
} catch (e) {
|
|
7260
|
+
return { error: `Could not load config: ${e?.message || "unknown error"}` };
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
function persistWorkspaceConfig(config) {
|
|
7264
|
+
try {
|
|
7265
|
+
saveConfig(config);
|
|
7266
|
+
return { ok: true };
|
|
7267
|
+
} catch (e) {
|
|
7268
|
+
return { error: `Could not save config: ${e?.message || "unknown error"}` };
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7195
7271
|
function handleWorkspaceList() {
|
|
7196
|
-
const config =
|
|
7272
|
+
const config = loadWorkspaceConfig();
|
|
7273
|
+
if ("error" in config) return { success: false, error: config.error };
|
|
7197
7274
|
const state = getWorkspaceState(config);
|
|
7198
7275
|
return {
|
|
7199
7276
|
success: true,
|
|
@@ -7207,31 +7284,37 @@ function handleWorkspaceAdd(args) {
|
|
|
7207
7284
|
const label = (args?.label || "").trim() || void 0;
|
|
7208
7285
|
const createIfMissing = args?.createIfMissing === true;
|
|
7209
7286
|
if (!rawPath) return { success: false, error: "path required" };
|
|
7210
|
-
const config =
|
|
7287
|
+
const config = loadWorkspaceConfig();
|
|
7288
|
+
if ("error" in config) return { success: false, error: config.error };
|
|
7211
7289
|
const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
|
|
7212
7290
|
if ("error" in result) return { success: false, error: result.error };
|
|
7213
|
-
|
|
7291
|
+
const saveResult = persistWorkspaceConfig(result.config);
|
|
7292
|
+
if ("error" in saveResult) return { success: false, error: saveResult.error };
|
|
7214
7293
|
const state = getWorkspaceState(result.config);
|
|
7215
7294
|
return { success: true, entry: result.entry, ...state };
|
|
7216
7295
|
}
|
|
7217
7296
|
function handleWorkspaceRemove(args) {
|
|
7218
7297
|
const id = (args?.id || "").trim();
|
|
7219
7298
|
if (!id) return { success: false, error: "id required" };
|
|
7220
|
-
const config =
|
|
7299
|
+
const config = loadWorkspaceConfig();
|
|
7300
|
+
if ("error" in config) return { success: false, error: config.error };
|
|
7221
7301
|
const removed = (config.workspaces || []).find((w) => w.id === id);
|
|
7222
7302
|
const result = removeWorkspaceEntry(config, id);
|
|
7223
7303
|
if ("error" in result) return { success: false, error: result.error };
|
|
7224
|
-
|
|
7304
|
+
const saveResult = persistWorkspaceConfig(result.config);
|
|
7305
|
+
if ("error" in saveResult) return { success: false, error: saveResult.error };
|
|
7225
7306
|
const state = getWorkspaceState(result.config);
|
|
7226
7307
|
return { success: true, removedId: id, ...state };
|
|
7227
7308
|
}
|
|
7228
7309
|
function handleWorkspaceSetDefault(args) {
|
|
7229
7310
|
const clear = args?.clear === true || args?.id === null || args?.id === "";
|
|
7230
7311
|
if (clear) {
|
|
7231
|
-
const config2 =
|
|
7312
|
+
const config2 = loadWorkspaceConfig();
|
|
7313
|
+
if ("error" in config2) return { success: false, error: config2.error };
|
|
7232
7314
|
const result2 = setDefaultWorkspaceId(config2, null);
|
|
7233
7315
|
if ("error" in result2) return { success: false, error: result2.error };
|
|
7234
|
-
|
|
7316
|
+
const saveResult2 = persistWorkspaceConfig(result2.config);
|
|
7317
|
+
if ("error" in saveResult2) return { success: false, error: saveResult2.error };
|
|
7235
7318
|
const state2 = getWorkspaceState(result2.config);
|
|
7236
7319
|
return {
|
|
7237
7320
|
success: true,
|
|
@@ -7243,7 +7326,9 @@ function handleWorkspaceSetDefault(args) {
|
|
|
7243
7326
|
if (!pathArg && !idArg) {
|
|
7244
7327
|
return { success: false, error: "id or path required (or clear: true)" };
|
|
7245
7328
|
}
|
|
7246
|
-
|
|
7329
|
+
const configResult = loadWorkspaceConfig();
|
|
7330
|
+
if ("error" in configResult) return { success: false, error: configResult.error };
|
|
7331
|
+
let config = configResult;
|
|
7247
7332
|
let nextId;
|
|
7248
7333
|
if (pathArg) {
|
|
7249
7334
|
let w = findWorkspaceByPath(config, pathArg);
|
|
@@ -7259,7 +7344,8 @@ function handleWorkspaceSetDefault(args) {
|
|
|
7259
7344
|
}
|
|
7260
7345
|
const result = setDefaultWorkspaceId(config, nextId);
|
|
7261
7346
|
if ("error" in result) return { success: false, error: result.error };
|
|
7262
|
-
|
|
7347
|
+
const saveResult = persistWorkspaceConfig(result.config);
|
|
7348
|
+
if ("error" in saveResult) return { success: false, error: saveResult.error };
|
|
7263
7349
|
const state = getWorkspaceState(result.config);
|
|
7264
7350
|
return { success: true, ...state };
|
|
7265
7351
|
}
|
|
@@ -7661,7 +7747,7 @@ var DaemonCommandHandler = class {
|
|
|
7661
7747
|
try {
|
|
7662
7748
|
const http3 = await import("http");
|
|
7663
7749
|
const postData = JSON.stringify(body);
|
|
7664
|
-
const result = await new Promise((
|
|
7750
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7665
7751
|
const req = http3.request({
|
|
7666
7752
|
hostname: "127.0.0.1",
|
|
7667
7753
|
port: 19280,
|
|
@@ -7673,9 +7759,9 @@ var DaemonCommandHandler = class {
|
|
|
7673
7759
|
res.on("data", (chunk) => data += chunk);
|
|
7674
7760
|
res.on("end", () => {
|
|
7675
7761
|
try {
|
|
7676
|
-
|
|
7762
|
+
resolve9(JSON.parse(data));
|
|
7677
7763
|
} catch {
|
|
7678
|
-
|
|
7764
|
+
resolve9({ raw: data });
|
|
7679
7765
|
}
|
|
7680
7766
|
});
|
|
7681
7767
|
});
|
|
@@ -7693,15 +7779,15 @@ var DaemonCommandHandler = class {
|
|
|
7693
7779
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
7694
7780
|
try {
|
|
7695
7781
|
const http3 = await import("http");
|
|
7696
|
-
const result = await new Promise((
|
|
7782
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7697
7783
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
7698
7784
|
let data = "";
|
|
7699
7785
|
res.on("data", (chunk) => data += chunk);
|
|
7700
7786
|
res.on("end", () => {
|
|
7701
7787
|
try {
|
|
7702
|
-
|
|
7788
|
+
resolve9(JSON.parse(data));
|
|
7703
7789
|
} catch {
|
|
7704
|
-
|
|
7790
|
+
resolve9({ raw: data });
|
|
7705
7791
|
}
|
|
7706
7792
|
});
|
|
7707
7793
|
}).on("error", reject);
|
|
@@ -7715,7 +7801,7 @@ var DaemonCommandHandler = class {
|
|
|
7715
7801
|
try {
|
|
7716
7802
|
const http3 = await import("http");
|
|
7717
7803
|
const postData = JSON.stringify(args || {});
|
|
7718
|
-
const result = await new Promise((
|
|
7804
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7719
7805
|
const req = http3.request({
|
|
7720
7806
|
hostname: "127.0.0.1",
|
|
7721
7807
|
port: 19280,
|
|
@@ -7727,9 +7813,9 @@ var DaemonCommandHandler = class {
|
|
|
7727
7813
|
res.on("data", (chunk) => data += chunk);
|
|
7728
7814
|
res.on("end", () => {
|
|
7729
7815
|
try {
|
|
7730
|
-
|
|
7816
|
+
resolve9(JSON.parse(data));
|
|
7731
7817
|
} catch {
|
|
7732
|
-
|
|
7818
|
+
resolve9({ raw: data });
|
|
7733
7819
|
}
|
|
7734
7820
|
});
|
|
7735
7821
|
});
|
|
@@ -7746,7 +7832,7 @@ var DaemonCommandHandler = class {
|
|
|
7746
7832
|
|
|
7747
7833
|
// src/commands/cli-manager.ts
|
|
7748
7834
|
init_provider_cli_adapter();
|
|
7749
|
-
import * as
|
|
7835
|
+
import * as os10 from "os";
|
|
7750
7836
|
import * as path9 from "path";
|
|
7751
7837
|
import * as crypto4 from "crypto";
|
|
7752
7838
|
import chalk from "chalk";
|
|
@@ -7754,7 +7840,7 @@ init_config();
|
|
|
7754
7840
|
|
|
7755
7841
|
// src/providers/cli-provider-instance.ts
|
|
7756
7842
|
init_provider_cli_adapter();
|
|
7757
|
-
import * as
|
|
7843
|
+
import * as os9 from "os";
|
|
7758
7844
|
import * as path8 from "path";
|
|
7759
7845
|
import * as crypto3 from "crypto";
|
|
7760
7846
|
import * as fs5 from "fs";
|
|
@@ -7842,17 +7928,60 @@ var CliProviderInstance = class {
|
|
|
7842
7928
|
async onTick() {
|
|
7843
7929
|
if (this.providerSessionId) return;
|
|
7844
7930
|
let probedSessionId = null;
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7931
|
+
const probeConfig = this.provider.sessionProbe;
|
|
7932
|
+
if (probeConfig) {
|
|
7933
|
+
probedSessionId = this.probeSessionIdFromConfig(probeConfig);
|
|
7934
|
+
} else {
|
|
7935
|
+
if (this.type === "opencode-cli") {
|
|
7936
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7937
|
+
dbPath: "~/.local/share/opencode/opencode.db",
|
|
7938
|
+
query: "select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1",
|
|
7939
|
+
timestampFormat: "unix_ms"
|
|
7940
|
+
});
|
|
7941
|
+
} else if (this.type === "codex-cli") {
|
|
7942
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7943
|
+
dbPath: "~/.codex/state_5.sqlite",
|
|
7944
|
+
query: "select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1",
|
|
7945
|
+
timestampFormat: "unix_s"
|
|
7946
|
+
});
|
|
7947
|
+
} else if (this.type === "goose-cli") {
|
|
7948
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7949
|
+
dbPath: "~/.local/share/goose/sessions/sessions.db",
|
|
7950
|
+
query: "select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1",
|
|
7951
|
+
timestampFormat: "iso"
|
|
7952
|
+
});
|
|
7953
|
+
}
|
|
7851
7954
|
}
|
|
7852
7955
|
if (probedSessionId) {
|
|
7853
7956
|
this.promoteProviderSessionId(probedSessionId);
|
|
7854
7957
|
}
|
|
7855
7958
|
}
|
|
7959
|
+
/**
|
|
7960
|
+
* Generic session ID probe using declarative ProviderSessionProbe config.
|
|
7961
|
+
* Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
|
|
7962
|
+
*/
|
|
7963
|
+
probeSessionIdFromConfig(probe) {
|
|
7964
|
+
const resolvedDbPath = probe.dbPath.replace(/^~/, os9.homedir());
|
|
7965
|
+
if (!fs5.existsSync(resolvedDbPath)) return null;
|
|
7966
|
+
const directories = this.getProbeDirectories();
|
|
7967
|
+
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
7968
|
+
const tsFormat = probe.timestampFormat || "unix_ms";
|
|
7969
|
+
let timestampParam;
|
|
7970
|
+
if (tsFormat === "unix_s") {
|
|
7971
|
+
timestampParam = Math.floor(minCreatedAt / 1e3);
|
|
7972
|
+
} else if (tsFormat === "iso") {
|
|
7973
|
+
timestampParam = new Date(minCreatedAt).toISOString().slice(0, 19).replace("T", " ");
|
|
7974
|
+
} else {
|
|
7975
|
+
timestampParam = minCreatedAt;
|
|
7976
|
+
}
|
|
7977
|
+
const placeholders = this.buildSqlPlaceholderList(directories.length);
|
|
7978
|
+
const query = probe.query.replace("{dirs}", placeholders);
|
|
7979
|
+
try {
|
|
7980
|
+
return this.querySqliteText(resolvedDbPath, query, [...directories, timestampParam]);
|
|
7981
|
+
} catch {
|
|
7982
|
+
return null;
|
|
7983
|
+
}
|
|
7984
|
+
}
|
|
7856
7985
|
getState() {
|
|
7857
7986
|
const adapterStatus = this.adapter.getStatus();
|
|
7858
7987
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
@@ -8150,34 +8279,6 @@ var CliProviderInstance = class {
|
|
|
8150
8279
|
});
|
|
8151
8280
|
LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
8152
8281
|
}
|
|
8153
|
-
probeOpenCodeSessionId() {
|
|
8154
|
-
const dbPath = path8.join(os8.homedir(), ".local", "share", "opencode", "opencode.db");
|
|
8155
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8156
|
-
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
8157
|
-
const directories = this.getProbeDirectories();
|
|
8158
|
-
const query = `select id from session where directory in (${this.buildSqlPlaceholderList(directories.length)}) and time_created >= ? and time_archived is null order by time_updated desc limit 1;`;
|
|
8159
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8160
|
-
}
|
|
8161
|
-
probeCodexSessionId() {
|
|
8162
|
-
const dbPath = path8.join(os8.homedir(), ".codex", "state_5.sqlite");
|
|
8163
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8164
|
-
const minCreatedAt = Math.max(0, Math.floor((this.startedAt - 6e4) / 1e3));
|
|
8165
|
-
const directories = this.getProbeDirectories();
|
|
8166
|
-
const query = `select id from threads where cwd in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? and archived = 0 order by created_at desc limit 1;`;
|
|
8167
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8168
|
-
}
|
|
8169
|
-
probeGooseSessionId() {
|
|
8170
|
-
const dbPath = path8.join(os8.homedir(), ".local", "share", "goose", "sessions", "sessions.db");
|
|
8171
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8172
|
-
const minCreatedAtIso = new Date(Math.max(0, this.startedAt - 6e4)).toISOString().slice(0, 19).replace("T", " ");
|
|
8173
|
-
const directories = this.getProbeDirectories();
|
|
8174
|
-
const query = `select id from sessions where working_dir in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? order by updated_at desc limit 1;`;
|
|
8175
|
-
try {
|
|
8176
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAtIso]);
|
|
8177
|
-
} catch {
|
|
8178
|
-
return null;
|
|
8179
|
-
}
|
|
8180
|
-
}
|
|
8181
8282
|
getProbeDirectories() {
|
|
8182
8283
|
const dirs = /* @__PURE__ */ new Set();
|
|
8183
8284
|
const addDir = (value) => {
|
|
@@ -8654,13 +8755,13 @@ var AcpProviderInstance = class {
|
|
|
8654
8755
|
}
|
|
8655
8756
|
this.currentStatus = "waiting_approval";
|
|
8656
8757
|
this.detectStatusTransition();
|
|
8657
|
-
const approved = await new Promise((
|
|
8658
|
-
this.permissionResolvers.push(
|
|
8758
|
+
const approved = await new Promise((resolve9) => {
|
|
8759
|
+
this.permissionResolvers.push(resolve9);
|
|
8659
8760
|
setTimeout(() => {
|
|
8660
|
-
const idx = this.permissionResolvers.indexOf(
|
|
8761
|
+
const idx = this.permissionResolvers.indexOf(resolve9);
|
|
8661
8762
|
if (idx >= 0) {
|
|
8662
8763
|
this.permissionResolvers.splice(idx, 1);
|
|
8663
|
-
|
|
8764
|
+
resolve9(false);
|
|
8664
8765
|
}
|
|
8665
8766
|
}, 3e5);
|
|
8666
8767
|
});
|
|
@@ -9367,7 +9468,7 @@ var DaemonCliManager = class {
|
|
|
9367
9468
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
9368
9469
|
const trimmed = (workingDir || "").trim();
|
|
9369
9470
|
if (!trimmed) throw new Error("working directory required");
|
|
9370
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
9471
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
|
|
9371
9472
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
9372
9473
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
9373
9474
|
const key = crypto4.randomUUID();
|
|
@@ -9451,7 +9552,19 @@ ${installInfo}`
|
|
|
9451
9552
|
return { runtimeSessionId: sessionId };
|
|
9452
9553
|
}
|
|
9453
9554
|
const cliInfo = await detectCLI(cliType, this.providerLoader);
|
|
9454
|
-
if (!cliInfo)
|
|
9555
|
+
if (!cliInfo) {
|
|
9556
|
+
const installHint = provider?.install || "";
|
|
9557
|
+
const displayName = provider?.displayName || provider?.name || cliType;
|
|
9558
|
+
const spawnCmd = provider?.spawn?.command || cliType;
|
|
9559
|
+
throw new Error(
|
|
9560
|
+
`${displayName} is not installed.
|
|
9561
|
+
Command '${spawnCmd}' not found on PATH.
|
|
9562
|
+
` + (installHint ? `
|
|
9563
|
+
${installHint}
|
|
9564
|
+
` : "") + `
|
|
9565
|
+
Run 'adhdev doctor' for detailed diagnostics.`
|
|
9566
|
+
);
|
|
9567
|
+
}
|
|
9455
9568
|
console.log(colorize("yellow", ` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
9456
9569
|
if (provider) {
|
|
9457
9570
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
@@ -9767,8 +9880,9 @@ ${installInfo}`
|
|
|
9767
9880
|
const dir = rdir.path;
|
|
9768
9881
|
if (!cliType) throw new Error("cliType required");
|
|
9769
9882
|
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9883
|
+
const prevCliArgs = found ? found.adapter.extraArgs : void 0;
|
|
9770
9884
|
if (found) await this.stopSession(found.key);
|
|
9771
|
-
await this.startSession(cliType, dir);
|
|
9885
|
+
await this.startSession(cliType, dir, args?.cliArgs || prevCliArgs, args?.initialModel);
|
|
9772
9886
|
return { success: true, restarted: true };
|
|
9773
9887
|
}
|
|
9774
9888
|
case "agent_command": {
|
|
@@ -9803,13 +9917,13 @@ ${installInfo}`
|
|
|
9803
9917
|
// src/launch.ts
|
|
9804
9918
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
9805
9919
|
import * as net from "net";
|
|
9806
|
-
import * as
|
|
9920
|
+
import * as os12 from "os";
|
|
9807
9921
|
import * as path11 from "path";
|
|
9808
9922
|
|
|
9809
9923
|
// src/providers/provider-loader.ts
|
|
9810
9924
|
import * as fs6 from "fs";
|
|
9811
9925
|
import * as path10 from "path";
|
|
9812
|
-
import * as
|
|
9926
|
+
import * as os11 from "os";
|
|
9813
9927
|
import * as chokidar from "chokidar";
|
|
9814
9928
|
init_logger();
|
|
9815
9929
|
var ProviderLoader = class _ProviderLoader {
|
|
@@ -9829,7 +9943,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
9829
9943
|
static META_FILE = ".meta.json";
|
|
9830
9944
|
constructor(options) {
|
|
9831
9945
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
9832
|
-
const defaultProvidersDir = path10.join(
|
|
9946
|
+
const defaultProvidersDir = path10.join(os11.homedir(), ".adhdev", "providers");
|
|
9833
9947
|
if (options?.userDir) {
|
|
9834
9948
|
this.userDir = options.userDir;
|
|
9835
9949
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -10386,7 +10500,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10386
10500
|
return { updated: false };
|
|
10387
10501
|
}
|
|
10388
10502
|
try {
|
|
10389
|
-
const etag = await new Promise((
|
|
10503
|
+
const etag = await new Promise((resolve9, reject) => {
|
|
10390
10504
|
const options = {
|
|
10391
10505
|
method: "HEAD",
|
|
10392
10506
|
hostname: "github.com",
|
|
@@ -10404,7 +10518,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10404
10518
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
10405
10519
|
timeout: 1e4
|
|
10406
10520
|
}, (res2) => {
|
|
10407
|
-
|
|
10521
|
+
resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
10408
10522
|
});
|
|
10409
10523
|
req2.on("error", reject);
|
|
10410
10524
|
req2.on("timeout", () => {
|
|
@@ -10413,7 +10527,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10413
10527
|
});
|
|
10414
10528
|
req2.end();
|
|
10415
10529
|
} else {
|
|
10416
|
-
|
|
10530
|
+
resolve9(res.headers.etag || res.headers["last-modified"] || "");
|
|
10417
10531
|
}
|
|
10418
10532
|
});
|
|
10419
10533
|
req.on("error", reject);
|
|
@@ -10429,8 +10543,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10429
10543
|
return { updated: false };
|
|
10430
10544
|
}
|
|
10431
10545
|
this.log("Downloading latest providers from GitHub...");
|
|
10432
|
-
const tmpTar = path10.join(
|
|
10433
|
-
const tmpExtract = path10.join(
|
|
10546
|
+
const tmpTar = path10.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
10547
|
+
const tmpExtract = path10.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
10434
10548
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
10435
10549
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
10436
10550
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
@@ -10477,7 +10591,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10477
10591
|
downloadFile(url, destPath) {
|
|
10478
10592
|
const https = __require("https");
|
|
10479
10593
|
const http3 = __require("http");
|
|
10480
|
-
return new Promise((
|
|
10594
|
+
return new Promise((resolve9, reject) => {
|
|
10481
10595
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
10482
10596
|
if (redirectCount > 5) {
|
|
10483
10597
|
reject(new Error("Too many redirects"));
|
|
@@ -10497,7 +10611,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10497
10611
|
res.pipe(ws);
|
|
10498
10612
|
ws.on("finish", () => {
|
|
10499
10613
|
ws.close();
|
|
10500
|
-
|
|
10614
|
+
resolve9();
|
|
10501
10615
|
});
|
|
10502
10616
|
ws.on("error", reject);
|
|
10503
10617
|
});
|
|
@@ -10862,17 +10976,17 @@ async function findFreePort(ports) {
|
|
|
10862
10976
|
throw new Error("No free port found");
|
|
10863
10977
|
}
|
|
10864
10978
|
function checkPortFree(port) {
|
|
10865
|
-
return new Promise((
|
|
10979
|
+
return new Promise((resolve9) => {
|
|
10866
10980
|
const server = net.createServer();
|
|
10867
10981
|
server.unref();
|
|
10868
|
-
server.on("error", () =>
|
|
10982
|
+
server.on("error", () => resolve9(false));
|
|
10869
10983
|
server.listen(port, "127.0.0.1", () => {
|
|
10870
|
-
server.close(() =>
|
|
10984
|
+
server.close(() => resolve9(true));
|
|
10871
10985
|
});
|
|
10872
10986
|
});
|
|
10873
10987
|
}
|
|
10874
10988
|
async function isCdpActive(port) {
|
|
10875
|
-
return new Promise((
|
|
10989
|
+
return new Promise((resolve9) => {
|
|
10876
10990
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
10877
10991
|
timeout: 2e3
|
|
10878
10992
|
}, (res) => {
|
|
@@ -10881,21 +10995,21 @@ async function isCdpActive(port) {
|
|
|
10881
10995
|
res.on("end", () => {
|
|
10882
10996
|
try {
|
|
10883
10997
|
const info = JSON.parse(data);
|
|
10884
|
-
|
|
10998
|
+
resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
10885
10999
|
} catch {
|
|
10886
|
-
|
|
11000
|
+
resolve9(false);
|
|
10887
11001
|
}
|
|
10888
11002
|
});
|
|
10889
11003
|
});
|
|
10890
|
-
req.on("error", () =>
|
|
11004
|
+
req.on("error", () => resolve9(false));
|
|
10891
11005
|
req.on("timeout", () => {
|
|
10892
11006
|
req.destroy();
|
|
10893
|
-
|
|
11007
|
+
resolve9(false);
|
|
10894
11008
|
});
|
|
10895
11009
|
});
|
|
10896
11010
|
}
|
|
10897
11011
|
async function killIdeProcess(ideId) {
|
|
10898
|
-
const plat =
|
|
11012
|
+
const plat = os12.platform();
|
|
10899
11013
|
const appName = getMacAppIdentifiers()[ideId];
|
|
10900
11014
|
const winProcesses = getWinProcessNames()[ideId];
|
|
10901
11015
|
try {
|
|
@@ -10954,7 +11068,7 @@ async function killIdeProcess(ideId) {
|
|
|
10954
11068
|
}
|
|
10955
11069
|
}
|
|
10956
11070
|
function isIdeRunning(ideId) {
|
|
10957
|
-
const plat =
|
|
11071
|
+
const plat = os12.platform();
|
|
10958
11072
|
try {
|
|
10959
11073
|
if (plat === "darwin") {
|
|
10960
11074
|
const appName = getMacAppIdentifiers()[ideId];
|
|
@@ -10990,7 +11104,7 @@ function isIdeRunning(ideId) {
|
|
|
10990
11104
|
}
|
|
10991
11105
|
}
|
|
10992
11106
|
function detectCurrentWorkspace(ideId) {
|
|
10993
|
-
const plat =
|
|
11107
|
+
const plat = os12.platform();
|
|
10994
11108
|
if (plat === "darwin") {
|
|
10995
11109
|
try {
|
|
10996
11110
|
const appName = getMacAppIdentifiers()[ideId];
|
|
@@ -11010,7 +11124,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
11010
11124
|
const appName = appNameMap[ideId];
|
|
11011
11125
|
if (appName) {
|
|
11012
11126
|
const storagePath = path11.join(
|
|
11013
|
-
process.env.APPDATA || path11.join(
|
|
11127
|
+
process.env.APPDATA || path11.join(os12.homedir(), "AppData", "Roaming"),
|
|
11014
11128
|
appName,
|
|
11015
11129
|
"storage.json"
|
|
11016
11130
|
);
|
|
@@ -11032,7 +11146,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
11032
11146
|
return void 0;
|
|
11033
11147
|
}
|
|
11034
11148
|
async function launchWithCdp(options = {}) {
|
|
11035
|
-
const platform9 =
|
|
11149
|
+
const platform9 = os12.platform();
|
|
11036
11150
|
let targetIde;
|
|
11037
11151
|
const ides = await detectIDEs();
|
|
11038
11152
|
if (options.ideId) {
|
|
@@ -11184,8 +11298,8 @@ init_logger();
|
|
|
11184
11298
|
// src/logging/command-log.ts
|
|
11185
11299
|
import * as fs7 from "fs";
|
|
11186
11300
|
import * as path12 from "path";
|
|
11187
|
-
import * as
|
|
11188
|
-
var LOG_DIR2 = process.platform === "win32" ? path12.join(process.env.LOCALAPPDATA || process.env.APPDATA || path12.join(
|
|
11301
|
+
import * as os13 from "os";
|
|
11302
|
+
var LOG_DIR2 = process.platform === "win32" ? path12.join(process.env.LOCALAPPDATA || process.env.APPDATA || path12.join(os13.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path12.join(os13.homedir(), "Library", "Logs", "adhdev") : path12.join(os13.homedir(), ".local", "share", "adhdev", "logs");
|
|
11189
11303
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
11190
11304
|
var MAX_DAYS = 7;
|
|
11191
11305
|
try {
|
|
@@ -11321,7 +11435,7 @@ init_logger();
|
|
|
11321
11435
|
|
|
11322
11436
|
// src/status/snapshot.ts
|
|
11323
11437
|
init_config();
|
|
11324
|
-
import * as
|
|
11438
|
+
import * as os14 from "os";
|
|
11325
11439
|
init_terminal_screen();
|
|
11326
11440
|
init_logger();
|
|
11327
11441
|
var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
@@ -11436,16 +11550,16 @@ function buildStatusSnapshot(options) {
|
|
|
11436
11550
|
version: options.version,
|
|
11437
11551
|
daemonMode: options.daemonMode,
|
|
11438
11552
|
machine: {
|
|
11439
|
-
hostname:
|
|
11440
|
-
platform:
|
|
11441
|
-
arch:
|
|
11442
|
-
cpus:
|
|
11553
|
+
hostname: os14.hostname(),
|
|
11554
|
+
platform: os14.platform(),
|
|
11555
|
+
arch: os14.arch(),
|
|
11556
|
+
cpus: os14.cpus().length,
|
|
11443
11557
|
totalMem: memSnap.totalMem,
|
|
11444
11558
|
freeMem: memSnap.freeMem,
|
|
11445
11559
|
availableMem: memSnap.availableMem,
|
|
11446
|
-
loadavg:
|
|
11447
|
-
uptime:
|
|
11448
|
-
release:
|
|
11560
|
+
loadavg: os14.loadavg(),
|
|
11561
|
+
uptime: os14.uptime(),
|
|
11562
|
+
release: os14.release()
|
|
11449
11563
|
},
|
|
11450
11564
|
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
11451
11565
|
timestamp: options.timestamp ?? Date.now(),
|
|
@@ -11465,11 +11579,11 @@ function buildStatusSnapshot(options) {
|
|
|
11465
11579
|
import { execFileSync } from "child_process";
|
|
11466
11580
|
import { spawn as spawn3 } from "child_process";
|
|
11467
11581
|
import * as fs8 from "fs";
|
|
11468
|
-
import * as
|
|
11582
|
+
import * as os15 from "os";
|
|
11469
11583
|
import * as path13 from "path";
|
|
11470
11584
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
11471
11585
|
function getUpgradeLogPath() {
|
|
11472
|
-
const home =
|
|
11586
|
+
const home = os15.homedir();
|
|
11473
11587
|
const dir = path13.join(home, ".adhdev");
|
|
11474
11588
|
fs8.mkdirSync(dir, { recursive: true });
|
|
11475
11589
|
return path13.join(dir, "daemon-upgrade.log");
|
|
@@ -11502,14 +11616,14 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
11502
11616
|
while (Date.now() - start < timeoutMs) {
|
|
11503
11617
|
try {
|
|
11504
11618
|
process.kill(pid, 0);
|
|
11505
|
-
await new Promise((
|
|
11619
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
11506
11620
|
} catch {
|
|
11507
11621
|
return;
|
|
11508
11622
|
}
|
|
11509
11623
|
}
|
|
11510
11624
|
}
|
|
11511
11625
|
function stopSessionHostProcesses(appName) {
|
|
11512
|
-
const pidFile = path13.join(
|
|
11626
|
+
const pidFile = path13.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
11513
11627
|
try {
|
|
11514
11628
|
if (fs8.existsSync(pidFile)) {
|
|
11515
11629
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -11538,7 +11652,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
11538
11652
|
}
|
|
11539
11653
|
}
|
|
11540
11654
|
function removeDaemonPidFile() {
|
|
11541
|
-
const pidFile = path13.join(
|
|
11655
|
+
const pidFile = path13.join(os15.homedir(), ".adhdev", "daemon.pid");
|
|
11542
11656
|
try {
|
|
11543
11657
|
fs8.unlinkSync(pidFile);
|
|
11544
11658
|
} catch {
|
|
@@ -13048,10 +13162,10 @@ var ProviderInstanceManager = class {
|
|
|
13048
13162
|
// src/providers/version-archive.ts
|
|
13049
13163
|
import * as fs10 from "fs";
|
|
13050
13164
|
import * as path14 from "path";
|
|
13051
|
-
import * as
|
|
13165
|
+
import * as os16 from "os";
|
|
13052
13166
|
import { execSync as execSync5 } from "child_process";
|
|
13053
13167
|
import { platform as platform7 } from "os";
|
|
13054
|
-
var ARCHIVE_PATH = path14.join(
|
|
13168
|
+
var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
13055
13169
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
13056
13170
|
var VersionArchive = class {
|
|
13057
13171
|
history = {};
|
|
@@ -13138,7 +13252,7 @@ function getVersion(binary, versionCommand) {
|
|
|
13138
13252
|
function checkPathExists2(paths) {
|
|
13139
13253
|
for (const p of paths) {
|
|
13140
13254
|
if (p.includes("*")) {
|
|
13141
|
-
const home =
|
|
13255
|
+
const home = os16.homedir();
|
|
13142
13256
|
const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
|
|
13143
13257
|
if (fs10.existsSync(resolved)) return resolved;
|
|
13144
13258
|
} else {
|
|
@@ -14735,7 +14849,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
14735
14849
|
return { target, instance, adapter };
|
|
14736
14850
|
}
|
|
14737
14851
|
function sleep(ms) {
|
|
14738
|
-
return new Promise((
|
|
14852
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
14739
14853
|
}
|
|
14740
14854
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
14741
14855
|
const startedAt = Date.now();
|
|
@@ -15466,7 +15580,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
15466
15580
|
// src/daemon/dev-auto-implement.ts
|
|
15467
15581
|
import * as fs13 from "fs";
|
|
15468
15582
|
import * as path17 from "path";
|
|
15469
|
-
import * as
|
|
15583
|
+
import * as os17 from "os";
|
|
15470
15584
|
function getAutoImplPid(ctx) {
|
|
15471
15585
|
const proc = ctx.autoImplProcess;
|
|
15472
15586
|
return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
|
|
@@ -15669,7 +15783,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
15669
15783
|
});
|
|
15670
15784
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
15671
15785
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
15672
|
-
const tmpDir = path17.join(
|
|
15786
|
+
const tmpDir = path17.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
15673
15787
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
15674
15788
|
const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
15675
15789
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
@@ -15823,7 +15937,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
15823
15937
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
15824
15938
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
15825
15939
|
let shellCmd;
|
|
15826
|
-
const isWin =
|
|
15940
|
+
const isWin = os17.platform() === "win32";
|
|
15827
15941
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
15828
15942
|
if (command === "claude") {
|
|
15829
15943
|
const args = [...baseArgs, "--dangerously-skip-permissions"];
|
|
@@ -15867,7 +15981,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
15867
15981
|
try {
|
|
15868
15982
|
const pty3 = __require("node-pty");
|
|
15869
15983
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
15870
|
-
const isWin2 =
|
|
15984
|
+
const isWin2 = os17.platform() === "win32";
|
|
15871
15985
|
child = pty3.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
15872
15986
|
name: "xterm-256color",
|
|
15873
15987
|
cols: 120,
|
|
@@ -16905,15 +17019,15 @@ var DevServer = class _DevServer {
|
|
|
16905
17019
|
this.json(res, 500, { error: e.message });
|
|
16906
17020
|
}
|
|
16907
17021
|
});
|
|
16908
|
-
return new Promise((
|
|
17022
|
+
return new Promise((resolve9, reject) => {
|
|
16909
17023
|
this.server.listen(port, "127.0.0.1", () => {
|
|
16910
17024
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
16911
|
-
|
|
17025
|
+
resolve9();
|
|
16912
17026
|
});
|
|
16913
17027
|
this.server.on("error", (e) => {
|
|
16914
17028
|
if (e.code === "EADDRINUSE") {
|
|
16915
17029
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
16916
|
-
|
|
17030
|
+
resolve9();
|
|
16917
17031
|
} else {
|
|
16918
17032
|
reject(e);
|
|
16919
17033
|
}
|
|
@@ -16996,20 +17110,20 @@ var DevServer = class _DevServer {
|
|
|
16996
17110
|
child.stderr?.on("data", (d) => {
|
|
16997
17111
|
stderr += d.toString().slice(0, 2e3);
|
|
16998
17112
|
});
|
|
16999
|
-
await new Promise((
|
|
17113
|
+
await new Promise((resolve9) => {
|
|
17000
17114
|
const timer = setTimeout(() => {
|
|
17001
17115
|
child.kill();
|
|
17002
|
-
|
|
17116
|
+
resolve9();
|
|
17003
17117
|
}, 3e3);
|
|
17004
17118
|
child.on("exit", () => {
|
|
17005
17119
|
clearTimeout(timer);
|
|
17006
|
-
|
|
17120
|
+
resolve9();
|
|
17007
17121
|
});
|
|
17008
17122
|
child.stdout?.once("data", () => {
|
|
17009
17123
|
setTimeout(() => {
|
|
17010
17124
|
child.kill();
|
|
17011
17125
|
clearTimeout(timer);
|
|
17012
|
-
|
|
17126
|
+
resolve9();
|
|
17013
17127
|
}, 500);
|
|
17014
17128
|
});
|
|
17015
17129
|
});
|
|
@@ -17518,14 +17632,14 @@ var DevServer = class _DevServer {
|
|
|
17518
17632
|
child.stderr?.on("data", (d) => {
|
|
17519
17633
|
stderr += d.toString();
|
|
17520
17634
|
});
|
|
17521
|
-
await new Promise((
|
|
17635
|
+
await new Promise((resolve9) => {
|
|
17522
17636
|
const timer = setTimeout(() => {
|
|
17523
17637
|
child.kill();
|
|
17524
|
-
|
|
17638
|
+
resolve9();
|
|
17525
17639
|
}, timeout);
|
|
17526
17640
|
child.on("exit", () => {
|
|
17527
17641
|
clearTimeout(timer);
|
|
17528
|
-
|
|
17642
|
+
resolve9();
|
|
17529
17643
|
});
|
|
17530
17644
|
});
|
|
17531
17645
|
const elapsed = Date.now() - start;
|
|
@@ -18200,14 +18314,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
18200
18314
|
res.end(JSON.stringify(data, null, 2));
|
|
18201
18315
|
}
|
|
18202
18316
|
async readBody(req) {
|
|
18203
|
-
return new Promise((
|
|
18317
|
+
return new Promise((resolve9) => {
|
|
18204
18318
|
let body = "";
|
|
18205
18319
|
req.on("data", (chunk) => body += chunk);
|
|
18206
18320
|
req.on("end", () => {
|
|
18207
18321
|
try {
|
|
18208
|
-
|
|
18322
|
+
resolve9(JSON.parse(body));
|
|
18209
18323
|
} catch {
|
|
18210
|
-
|
|
18324
|
+
resolve9({});
|
|
18211
18325
|
}
|
|
18212
18326
|
});
|
|
18213
18327
|
});
|
|
@@ -18676,7 +18790,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
18676
18790
|
const deadline = Date.now() + timeoutMs;
|
|
18677
18791
|
while (Date.now() < deadline) {
|
|
18678
18792
|
if (await canConnect(endpoint)) return;
|
|
18679
|
-
await new Promise((
|
|
18793
|
+
await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
|
|
18680
18794
|
}
|
|
18681
18795
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
18682
18796
|
}
|
|
@@ -18832,10 +18946,10 @@ async function installExtension(ide, extension) {
|
|
|
18832
18946
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
18833
18947
|
const fs15 = await import("fs");
|
|
18834
18948
|
fs15.writeFileSync(vsixPath, buffer);
|
|
18835
|
-
return new Promise((
|
|
18949
|
+
return new Promise((resolve9) => {
|
|
18836
18950
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
18837
18951
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
18838
|
-
|
|
18952
|
+
resolve9({
|
|
18839
18953
|
extensionId: extension.id,
|
|
18840
18954
|
marketplaceId: extension.marketplaceId,
|
|
18841
18955
|
success: !error,
|
|
@@ -18848,11 +18962,11 @@ async function installExtension(ide, extension) {
|
|
|
18848
18962
|
} catch (e) {
|
|
18849
18963
|
}
|
|
18850
18964
|
}
|
|
18851
|
-
return new Promise((
|
|
18965
|
+
return new Promise((resolve9) => {
|
|
18852
18966
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
18853
18967
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
18854
18968
|
if (error) {
|
|
18855
|
-
|
|
18969
|
+
resolve9({
|
|
18856
18970
|
extensionId: extension.id,
|
|
18857
18971
|
marketplaceId: extension.marketplaceId,
|
|
18858
18972
|
success: false,
|
|
@@ -18860,7 +18974,7 @@ async function installExtension(ide, extension) {
|
|
|
18860
18974
|
error: stderr || error.message
|
|
18861
18975
|
});
|
|
18862
18976
|
} else {
|
|
18863
|
-
|
|
18977
|
+
resolve9({
|
|
18864
18978
|
extensionId: extension.id,
|
|
18865
18979
|
marketplaceId: extension.marketplaceId,
|
|
18866
18980
|
success: true,
|