@adhdev/daemon-core 0.8.11 → 0.8.13
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 +305 -187
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -186
- 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 +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +27 -48
- package/src/cli-adapters/pty-transport.ts +14 -2
- package/src/cli-adapters/spawn-env.ts +12 -0
- package/src/cli-adapters/terminal-screen.ts +12 -3
- package/src/commands/cdp-commands.ts +45 -8
- package/src/commands/cli-manager.ts +13 -2
- 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}`
|
|
@@ -735,11 +742,21 @@ var init_pty_transport = __esm({
|
|
|
735
742
|
NodePtyTransportFactory = class {
|
|
736
743
|
spawn(command, args, options) {
|
|
737
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
|
+
}
|
|
738
755
|
const handle = pty.spawn(command, args, {
|
|
739
|
-
name:
|
|
756
|
+
name: "xterm-256color",
|
|
740
757
|
cols: options.cols,
|
|
741
758
|
rows: options.rows,
|
|
742
|
-
cwd
|
|
759
|
+
cwd,
|
|
743
760
|
env: options.env
|
|
744
761
|
});
|
|
745
762
|
return new NodePtyRuntimeTransport(handle);
|
|
@@ -748,6 +765,18 @@ var init_pty_transport = __esm({
|
|
|
748
765
|
}
|
|
749
766
|
});
|
|
750
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
|
+
|
|
751
780
|
// src/cli-adapters/provider-cli-adapter.ts
|
|
752
781
|
var provider_cli_adapter_exports = {};
|
|
753
782
|
__export(provider_cli_adapter_exports, {
|
|
@@ -766,20 +795,6 @@ function stripTerminalNoise(str) {
|
|
|
766
795
|
function sanitizeTerminalText(str) {
|
|
767
796
|
return stripTerminalNoise(stripAnsi(str));
|
|
768
797
|
}
|
|
769
|
-
function buildCliSpawnEnv(baseEnv, overrides) {
|
|
770
|
-
const env = {};
|
|
771
|
-
const source = { ...baseEnv, ...overrides || {} };
|
|
772
|
-
for (const [key, value] of Object.entries(source)) {
|
|
773
|
-
if (typeof value !== "string") continue;
|
|
774
|
-
env[key] = value;
|
|
775
|
-
}
|
|
776
|
-
for (const key of Object.keys(env)) {
|
|
777
|
-
if (key === "INIT_CWD" || key === "NO_COLOR" || key === "FORCE_COLOR" || 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_")) {
|
|
778
|
-
delete env[key];
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return env;
|
|
782
|
-
}
|
|
783
798
|
function computeTerminalQueryTail(buffer) {
|
|
784
799
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
785
800
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -908,34 +923,21 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
908
923
|
}
|
|
909
924
|
};
|
|
910
925
|
}
|
|
911
|
-
var pty2, ProviderCliAdapter;
|
|
926
|
+
var pty2, buildCliSpawnEnv, ProviderCliAdapter;
|
|
912
927
|
var init_provider_cli_adapter = __esm({
|
|
913
928
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
914
929
|
"use strict";
|
|
915
930
|
init_logger();
|
|
916
931
|
init_terminal_screen();
|
|
917
932
|
init_pty_transport();
|
|
933
|
+
init_spawn_env();
|
|
918
934
|
try {
|
|
919
935
|
pty2 = __require("node-pty");
|
|
920
|
-
|
|
921
|
-
try {
|
|
922
|
-
const fs15 = __require("fs");
|
|
923
|
-
const ptyDir = path7.resolve(path7.dirname(__require.resolve("node-pty")), "..");
|
|
924
|
-
const platformArch = `${os8.platform()}-${os8.arch()}`;
|
|
925
|
-
const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
926
|
-
if (fs15.existsSync(helper)) {
|
|
927
|
-
const stat = fs15.statSync(helper);
|
|
928
|
-
if (!(stat.mode & 73)) {
|
|
929
|
-
fs15.chmodSync(helper, stat.mode | 493);
|
|
930
|
-
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
} catch {
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
+
ensureNodePtySpawnHelperPermissions((msg) => LOG.info("CLI", msg));
|
|
936
937
|
} catch {
|
|
937
938
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
|
|
938
939
|
}
|
|
940
|
+
buildCliSpawnEnv = sanitizeSpawnEnv;
|
|
939
941
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
940
942
|
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
941
943
|
this.extraArgs = extraArgs;
|
|
@@ -1302,6 +1304,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1302
1304
|
shellArgs = ["-l", "-c", fullCmd];
|
|
1303
1305
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
1304
1306
|
} else {
|
|
1307
|
+
if (isWin) {
|
|
1308
|
+
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})` : "";
|
|
1309
|
+
if (hint) {
|
|
1310
|
+
throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1305
1313
|
throw err;
|
|
1306
1314
|
}
|
|
1307
1315
|
}
|
|
@@ -1476,7 +1484,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1476
1484
|
`[${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)}`
|
|
1477
1485
|
);
|
|
1478
1486
|
}
|
|
1479
|
-
await new Promise((
|
|
1487
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1480
1488
|
}
|
|
1481
1489
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1482
1490
|
LOG.warn(
|
|
@@ -1863,7 +1871,7 @@ ${data.message || ""}`.trim();
|
|
|
1863
1871
|
if (this.startupParseGate) {
|
|
1864
1872
|
const deadline = Date.now() + 1e4;
|
|
1865
1873
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
1866
|
-
await new Promise((
|
|
1874
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1867
1875
|
}
|
|
1868
1876
|
}
|
|
1869
1877
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
@@ -2054,7 +2062,8 @@ ${data.message || ""}`.trim();
|
|
|
2054
2062
|
const payload = stopCommand.endsWith("\r") || stopCommand.endsWith("\n") ? stopCommand : `${stopCommand}${this.sendKey}`;
|
|
2055
2063
|
this.ptyProcess.write(payload);
|
|
2056
2064
|
};
|
|
2057
|
-
|
|
2065
|
+
const interruptGraceMs = typeof resume.interruptGraceMs === "number" ? Math.max(100, resume.interruptGraceMs) : 500;
|
|
2066
|
+
if (wasProcessing) setTimeout(writeCommand, interruptGraceMs);
|
|
2058
2067
|
else writeCommand();
|
|
2059
2068
|
} else {
|
|
2060
2069
|
this.ptyProcess.write("");
|
|
@@ -2070,17 +2079,17 @@ ${data.message || ""}`.trim();
|
|
|
2070
2079
|
}
|
|
2071
2080
|
}
|
|
2072
2081
|
waitForStopped(timeoutMs) {
|
|
2073
|
-
return new Promise((
|
|
2082
|
+
return new Promise((resolve9) => {
|
|
2074
2083
|
const startedAt = Date.now();
|
|
2075
2084
|
const timer = setInterval(() => {
|
|
2076
2085
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
2077
2086
|
clearInterval(timer);
|
|
2078
|
-
|
|
2087
|
+
resolve9(true);
|
|
2079
2088
|
return;
|
|
2080
2089
|
}
|
|
2081
2090
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
2082
2091
|
clearInterval(timer);
|
|
2083
|
-
|
|
2092
|
+
resolve9(false);
|
|
2084
2093
|
}
|
|
2085
2094
|
}, 100);
|
|
2086
2095
|
});
|
|
@@ -2099,6 +2108,18 @@ ${data.message || ""}`.trim();
|
|
|
2099
2108
|
clearTimeout(this.submitRetryTimer);
|
|
2100
2109
|
this.submitRetryTimer = null;
|
|
2101
2110
|
}
|
|
2111
|
+
if (this.responseTimeout) {
|
|
2112
|
+
clearTimeout(this.responseTimeout);
|
|
2113
|
+
this.responseTimeout = null;
|
|
2114
|
+
}
|
|
2115
|
+
if (this.idleTimeout) {
|
|
2116
|
+
clearTimeout(this.idleTimeout);
|
|
2117
|
+
this.idleTimeout = null;
|
|
2118
|
+
}
|
|
2119
|
+
if (this.pendingScriptStatusTimer) {
|
|
2120
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2121
|
+
this.pendingScriptStatusTimer = null;
|
|
2122
|
+
}
|
|
2102
2123
|
if (this.pendingOutputParseTimer) {
|
|
2103
2124
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2104
2125
|
this.pendingOutputParseTimer = null;
|
|
@@ -2140,6 +2161,18 @@ ${data.message || ""}`.trim();
|
|
|
2140
2161
|
clearTimeout(this.submitRetryTimer);
|
|
2141
2162
|
this.submitRetryTimer = null;
|
|
2142
2163
|
}
|
|
2164
|
+
if (this.responseTimeout) {
|
|
2165
|
+
clearTimeout(this.responseTimeout);
|
|
2166
|
+
this.responseTimeout = null;
|
|
2167
|
+
}
|
|
2168
|
+
if (this.idleTimeout) {
|
|
2169
|
+
clearTimeout(this.idleTimeout);
|
|
2170
|
+
this.idleTimeout = null;
|
|
2171
|
+
}
|
|
2172
|
+
if (this.pendingScriptStatusTimer) {
|
|
2173
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2174
|
+
this.pendingScriptStatusTimer = null;
|
|
2175
|
+
}
|
|
2143
2176
|
if (this.pendingOutputParseTimer) {
|
|
2144
2177
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2145
2178
|
this.pendingOutputParseTimer = null;
|
|
@@ -2666,8 +2699,8 @@ async function detectIDEs() {
|
|
|
2666
2699
|
if (existsSync3(bundledCli)) resolvedCli = bundledCli;
|
|
2667
2700
|
}
|
|
2668
2701
|
if (!resolvedCli && appPath && os18 === "win32") {
|
|
2669
|
-
const { dirname:
|
|
2670
|
-
const appDir =
|
|
2702
|
+
const { dirname: dirname6 } = await import("path");
|
|
2703
|
+
const appDir = dirname6(appPath);
|
|
2671
2704
|
const candidates = [
|
|
2672
2705
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
2673
2706
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -2705,20 +2738,20 @@ function parseVersion(raw) {
|
|
|
2705
2738
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
2706
2739
|
}
|
|
2707
2740
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
2708
|
-
return new Promise((
|
|
2741
|
+
return new Promise((resolve9) => {
|
|
2709
2742
|
const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
2710
2743
|
if (err || !stdout?.trim()) {
|
|
2711
|
-
|
|
2744
|
+
resolve9(null);
|
|
2712
2745
|
} else {
|
|
2713
|
-
|
|
2746
|
+
resolve9(stdout.trim());
|
|
2714
2747
|
}
|
|
2715
2748
|
});
|
|
2716
|
-
child.on("error", () =>
|
|
2749
|
+
child.on("error", () => resolve9(null));
|
|
2717
2750
|
});
|
|
2718
2751
|
}
|
|
2719
2752
|
async function detectCLIs(providerLoader) {
|
|
2720
|
-
const
|
|
2721
|
-
const whichCmd =
|
|
2753
|
+
const platform9 = os2.platform();
|
|
2754
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
2722
2755
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
2723
2756
|
const results = await Promise.all(
|
|
2724
2757
|
cliList.map(async (cli) => {
|
|
@@ -2753,6 +2786,39 @@ async function detectCLIs(providerLoader) {
|
|
|
2753
2786
|
}
|
|
2754
2787
|
async function detectCLI(cliId, providerLoader) {
|
|
2755
2788
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
2789
|
+
if (providerLoader) {
|
|
2790
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
2791
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
2792
|
+
if (target) {
|
|
2793
|
+
const platform9 = os2.platform();
|
|
2794
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
2795
|
+
try {
|
|
2796
|
+
const pathResult = await execAsync(`${whichCmd} ${target.command}`);
|
|
2797
|
+
if (!pathResult) return null;
|
|
2798
|
+
const firstPath = pathResult.split("\n")[0];
|
|
2799
|
+
let version;
|
|
2800
|
+
try {
|
|
2801
|
+
const versionCommands = [
|
|
2802
|
+
target.versionCommand,
|
|
2803
|
+
`${target.command} --version`,
|
|
2804
|
+
`${target.command} -V`,
|
|
2805
|
+
`${target.command} -v`
|
|
2806
|
+
].filter((v) => !!v);
|
|
2807
|
+
for (const versionCommand of versionCommands) {
|
|
2808
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
2809
|
+
if (versionResult) {
|
|
2810
|
+
version = parseVersion(versionResult);
|
|
2811
|
+
break;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
} catch {
|
|
2815
|
+
}
|
|
2816
|
+
return { ...target, installed: true, version, path: firstPath };
|
|
2817
|
+
} catch {
|
|
2818
|
+
return null;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2756
2822
|
const all = await detectCLIs(providerLoader);
|
|
2757
2823
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
2758
2824
|
}
|
|
@@ -2880,7 +2946,7 @@ var DaemonCdpManager = class {
|
|
|
2880
2946
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
2881
2947
|
*/
|
|
2882
2948
|
static listAllTargets(port) {
|
|
2883
|
-
return new Promise((
|
|
2949
|
+
return new Promise((resolve9) => {
|
|
2884
2950
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2885
2951
|
let data = "";
|
|
2886
2952
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2896,16 +2962,16 @@ var DaemonCdpManager = class {
|
|
|
2896
2962
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
2897
2963
|
);
|
|
2898
2964
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
2899
|
-
|
|
2965
|
+
resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
2900
2966
|
} catch {
|
|
2901
|
-
|
|
2967
|
+
resolve9([]);
|
|
2902
2968
|
}
|
|
2903
2969
|
});
|
|
2904
2970
|
});
|
|
2905
|
-
req.on("error", () =>
|
|
2971
|
+
req.on("error", () => resolve9([]));
|
|
2906
2972
|
req.setTimeout(2e3, () => {
|
|
2907
2973
|
req.destroy();
|
|
2908
|
-
|
|
2974
|
+
resolve9([]);
|
|
2909
2975
|
});
|
|
2910
2976
|
});
|
|
2911
2977
|
}
|
|
@@ -2945,7 +3011,7 @@ var DaemonCdpManager = class {
|
|
|
2945
3011
|
}
|
|
2946
3012
|
}
|
|
2947
3013
|
findTargetOnPort(port) {
|
|
2948
|
-
return new Promise((
|
|
3014
|
+
return new Promise((resolve9) => {
|
|
2949
3015
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2950
3016
|
let data = "";
|
|
2951
3017
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2956,7 +3022,7 @@ var DaemonCdpManager = class {
|
|
|
2956
3022
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
2957
3023
|
);
|
|
2958
3024
|
if (pages.length === 0) {
|
|
2959
|
-
|
|
3025
|
+
resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
2960
3026
|
return;
|
|
2961
3027
|
}
|
|
2962
3028
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -2966,24 +3032,24 @@ var DaemonCdpManager = class {
|
|
|
2966
3032
|
const specific = list.find((t) => t.id === this._targetId);
|
|
2967
3033
|
if (specific) {
|
|
2968
3034
|
this._pageTitle = specific.title || "";
|
|
2969
|
-
|
|
3035
|
+
resolve9(specific);
|
|
2970
3036
|
} else {
|
|
2971
3037
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
2972
|
-
|
|
3038
|
+
resolve9(null);
|
|
2973
3039
|
}
|
|
2974
3040
|
return;
|
|
2975
3041
|
}
|
|
2976
3042
|
this._pageTitle = list[0]?.title || "";
|
|
2977
|
-
|
|
3043
|
+
resolve9(list[0]);
|
|
2978
3044
|
} catch {
|
|
2979
|
-
|
|
3045
|
+
resolve9(null);
|
|
2980
3046
|
}
|
|
2981
3047
|
});
|
|
2982
3048
|
});
|
|
2983
|
-
req.on("error", () =>
|
|
3049
|
+
req.on("error", () => resolve9(null));
|
|
2984
3050
|
req.setTimeout(2e3, () => {
|
|
2985
3051
|
req.destroy();
|
|
2986
|
-
|
|
3052
|
+
resolve9(null);
|
|
2987
3053
|
});
|
|
2988
3054
|
});
|
|
2989
3055
|
}
|
|
@@ -2994,7 +3060,7 @@ var DaemonCdpManager = class {
|
|
|
2994
3060
|
this.extensionProviders = providers;
|
|
2995
3061
|
}
|
|
2996
3062
|
connectToTarget(wsUrl) {
|
|
2997
|
-
return new Promise((
|
|
3063
|
+
return new Promise((resolve9) => {
|
|
2998
3064
|
this.ws = new WebSocket(wsUrl);
|
|
2999
3065
|
this.ws.on("open", async () => {
|
|
3000
3066
|
this._connected = true;
|
|
@@ -3004,17 +3070,17 @@ var DaemonCdpManager = class {
|
|
|
3004
3070
|
}
|
|
3005
3071
|
this.connectBrowserWs().catch(() => {
|
|
3006
3072
|
});
|
|
3007
|
-
|
|
3073
|
+
resolve9(true);
|
|
3008
3074
|
});
|
|
3009
3075
|
this.ws.on("message", (data) => {
|
|
3010
3076
|
try {
|
|
3011
3077
|
const msg = JSON.parse(data.toString());
|
|
3012
3078
|
if (msg.id && this.pending.has(msg.id)) {
|
|
3013
|
-
const { resolve:
|
|
3079
|
+
const { resolve: resolve10, reject } = this.pending.get(msg.id);
|
|
3014
3080
|
this.pending.delete(msg.id);
|
|
3015
3081
|
this.failureCount = 0;
|
|
3016
3082
|
if (msg.error) reject(new Error(msg.error.message));
|
|
3017
|
-
else
|
|
3083
|
+
else resolve10(msg.result);
|
|
3018
3084
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
3019
3085
|
this.contexts.add(msg.params.context.id);
|
|
3020
3086
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -3037,7 +3103,7 @@ var DaemonCdpManager = class {
|
|
|
3037
3103
|
this.ws.on("error", (err) => {
|
|
3038
3104
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
3039
3105
|
this._connected = false;
|
|
3040
|
-
|
|
3106
|
+
resolve9(false);
|
|
3041
3107
|
});
|
|
3042
3108
|
});
|
|
3043
3109
|
}
|
|
@@ -3051,7 +3117,7 @@ var DaemonCdpManager = class {
|
|
|
3051
3117
|
return;
|
|
3052
3118
|
}
|
|
3053
3119
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
3054
|
-
await new Promise((
|
|
3120
|
+
await new Promise((resolve9, reject) => {
|
|
3055
3121
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
3056
3122
|
this.browserWs.on("open", async () => {
|
|
3057
3123
|
this._browserConnected = true;
|
|
@@ -3061,16 +3127,16 @@ var DaemonCdpManager = class {
|
|
|
3061
3127
|
} catch (e) {
|
|
3062
3128
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
3063
3129
|
}
|
|
3064
|
-
|
|
3130
|
+
resolve9();
|
|
3065
3131
|
});
|
|
3066
3132
|
this.browserWs.on("message", (data) => {
|
|
3067
3133
|
try {
|
|
3068
3134
|
const msg = JSON.parse(data.toString());
|
|
3069
3135
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
3070
|
-
const { resolve:
|
|
3136
|
+
const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
|
|
3071
3137
|
this.browserPending.delete(msg.id);
|
|
3072
3138
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
3073
|
-
else
|
|
3139
|
+
else resolve10(msg.result);
|
|
3074
3140
|
}
|
|
3075
3141
|
} catch {
|
|
3076
3142
|
}
|
|
@@ -3090,31 +3156,31 @@ var DaemonCdpManager = class {
|
|
|
3090
3156
|
}
|
|
3091
3157
|
}
|
|
3092
3158
|
getBrowserWsUrl() {
|
|
3093
|
-
return new Promise((
|
|
3159
|
+
return new Promise((resolve9) => {
|
|
3094
3160
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
3095
3161
|
let data = "";
|
|
3096
3162
|
res.on("data", (chunk) => data += chunk.toString());
|
|
3097
3163
|
res.on("end", () => {
|
|
3098
3164
|
try {
|
|
3099
3165
|
const info = JSON.parse(data);
|
|
3100
|
-
|
|
3166
|
+
resolve9(info.webSocketDebuggerUrl || null);
|
|
3101
3167
|
} catch {
|
|
3102
|
-
|
|
3168
|
+
resolve9(null);
|
|
3103
3169
|
}
|
|
3104
3170
|
});
|
|
3105
3171
|
});
|
|
3106
|
-
req.on("error", () =>
|
|
3172
|
+
req.on("error", () => resolve9(null));
|
|
3107
3173
|
req.setTimeout(3e3, () => {
|
|
3108
3174
|
req.destroy();
|
|
3109
|
-
|
|
3175
|
+
resolve9(null);
|
|
3110
3176
|
});
|
|
3111
3177
|
});
|
|
3112
3178
|
}
|
|
3113
3179
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
3114
|
-
return new Promise((
|
|
3180
|
+
return new Promise((resolve9, reject) => {
|
|
3115
3181
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
3116
3182
|
const id = this.browserMsgId++;
|
|
3117
|
-
this.browserPending.set(id, { resolve:
|
|
3183
|
+
this.browserPending.set(id, { resolve: resolve9, reject });
|
|
3118
3184
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
3119
3185
|
setTimeout(() => {
|
|
3120
3186
|
if (this.browserPending.has(id)) {
|
|
@@ -3154,11 +3220,11 @@ var DaemonCdpManager = class {
|
|
|
3154
3220
|
}
|
|
3155
3221
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
3156
3222
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
3157
|
-
return new Promise((
|
|
3223
|
+
return new Promise((resolve9, reject) => {
|
|
3158
3224
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
3159
3225
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
3160
3226
|
const id = this.msgId++;
|
|
3161
|
-
this.pending.set(id, { resolve:
|
|
3227
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
3162
3228
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
3163
3229
|
setTimeout(() => {
|
|
3164
3230
|
if (this.pending.has(id)) {
|
|
@@ -3407,7 +3473,7 @@ var DaemonCdpManager = class {
|
|
|
3407
3473
|
const browserWs = this.browserWs;
|
|
3408
3474
|
let msgId = this.browserMsgId;
|
|
3409
3475
|
const sendWs = (method, params = {}, sessionId) => {
|
|
3410
|
-
return new Promise((
|
|
3476
|
+
return new Promise((resolve9, reject) => {
|
|
3411
3477
|
const mid = msgId++;
|
|
3412
3478
|
this.browserMsgId = msgId;
|
|
3413
3479
|
const handler = (raw) => {
|
|
@@ -3416,7 +3482,7 @@ var DaemonCdpManager = class {
|
|
|
3416
3482
|
if (msg.id === mid) {
|
|
3417
3483
|
browserWs.removeListener("message", handler);
|
|
3418
3484
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
3419
|
-
else
|
|
3485
|
+
else resolve9(msg.result);
|
|
3420
3486
|
}
|
|
3421
3487
|
} catch {
|
|
3422
3488
|
}
|
|
@@ -3607,14 +3673,14 @@ var DaemonCdpManager = class {
|
|
|
3607
3673
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
3608
3674
|
throw new Error("CDP not connected");
|
|
3609
3675
|
}
|
|
3610
|
-
return new Promise((
|
|
3676
|
+
return new Promise((resolve9, reject) => {
|
|
3611
3677
|
const id = getNextId();
|
|
3612
3678
|
pendingMap.set(id, {
|
|
3613
3679
|
resolve: (result) => {
|
|
3614
3680
|
if (result?.result?.subtype === "error") {
|
|
3615
3681
|
reject(new Error(result.result.description));
|
|
3616
3682
|
} else {
|
|
3617
|
-
|
|
3683
|
+
resolve9(result?.result?.value);
|
|
3618
3684
|
}
|
|
3619
3685
|
},
|
|
3620
3686
|
reject
|
|
@@ -3646,10 +3712,10 @@ var DaemonCdpManager = class {
|
|
|
3646
3712
|
throw new Error("CDP not connected");
|
|
3647
3713
|
}
|
|
3648
3714
|
const sendViaSession = (method, params = {}) => {
|
|
3649
|
-
return new Promise((
|
|
3715
|
+
return new Promise((resolve9, reject) => {
|
|
3650
3716
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
3651
3717
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
3652
|
-
pendingMap.set(id, { resolve:
|
|
3718
|
+
pendingMap.set(id, { resolve: resolve9, reject });
|
|
3653
3719
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
3654
3720
|
setTimeout(() => {
|
|
3655
3721
|
if (pendingMap.has(id)) {
|
|
@@ -6867,17 +6933,44 @@ async function handleDiscoverAgents(h, args) {
|
|
|
6867
6933
|
const agents = await h.getCdp().discoverAgentWebviews();
|
|
6868
6934
|
return { success: true, agents };
|
|
6869
6935
|
}
|
|
6936
|
+
function normalizeWindowsRequestedPath(requestedPath) {
|
|
6937
|
+
const trimmed = requestedPath.trim();
|
|
6938
|
+
if (!trimmed) return ".";
|
|
6939
|
+
const slashDriveMatch = trimmed.match(/^[/\\]([A-Za-z])(?:[/\\](.*))?$/);
|
|
6940
|
+
if (slashDriveMatch) {
|
|
6941
|
+
const drive = slashDriveMatch[1].toUpperCase();
|
|
6942
|
+
const rest = (slashDriveMatch[2] || "").replace(/[/\\]+/g, "\\");
|
|
6943
|
+
return rest ? `${drive}:\\${rest}` : `${drive}:\\`;
|
|
6944
|
+
}
|
|
6945
|
+
if (/^[A-Za-z]:$/.test(trimmed)) {
|
|
6946
|
+
return `${trimmed[0].toUpperCase()}:\\`;
|
|
6947
|
+
}
|
|
6948
|
+
if (/^[A-Za-z]:[^/\\].*$/.test(trimmed)) {
|
|
6949
|
+
return `${trimmed[0].toUpperCase()}:\\${trimmed.slice(2).replace(/[/\\]+/g, "\\")}`;
|
|
6950
|
+
}
|
|
6951
|
+
if (/^[A-Za-z]:[/\\]/.test(trimmed)) {
|
|
6952
|
+
return `${trimmed[0].toUpperCase()}:${trimmed.slice(2)}`;
|
|
6953
|
+
}
|
|
6954
|
+
return trimmed;
|
|
6955
|
+
}
|
|
6870
6956
|
function resolveSafePath(requestedPath) {
|
|
6957
|
+
const rawPath = typeof requestedPath === "string" ? requestedPath.trim() : "";
|
|
6958
|
+
const inputPath = rawPath || ".";
|
|
6871
6959
|
const home = os6.homedir();
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
resolved = path6.join(home, requestedPath.slice(1));
|
|
6875
|
-
} else if (path6.isAbsolute(requestedPath)) {
|
|
6876
|
-
resolved = requestedPath;
|
|
6877
|
-
} else {
|
|
6878
|
-
resolved = path6.resolve(requestedPath);
|
|
6960
|
+
if (inputPath.startsWith("~")) {
|
|
6961
|
+
return path6.resolve(path6.join(home, inputPath.slice(1)));
|
|
6879
6962
|
}
|
|
6880
|
-
|
|
6963
|
+
if (process.platform === "win32") {
|
|
6964
|
+
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
6965
|
+
if (path6.win32.isAbsolute(normalized)) {
|
|
6966
|
+
return path6.win32.normalize(normalized);
|
|
6967
|
+
}
|
|
6968
|
+
return path6.win32.resolve(normalized);
|
|
6969
|
+
}
|
|
6970
|
+
if (path6.isAbsolute(inputPath)) {
|
|
6971
|
+
return path6.normalize(inputPath);
|
|
6972
|
+
}
|
|
6973
|
+
return path6.resolve(inputPath);
|
|
6881
6974
|
}
|
|
6882
6975
|
function listDirectoryEntriesSafe(dirPath) {
|
|
6883
6976
|
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
@@ -7623,7 +7716,7 @@ var DaemonCommandHandler = class {
|
|
|
7623
7716
|
try {
|
|
7624
7717
|
const http3 = await import("http");
|
|
7625
7718
|
const postData = JSON.stringify(body);
|
|
7626
|
-
const result = await new Promise((
|
|
7719
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7627
7720
|
const req = http3.request({
|
|
7628
7721
|
hostname: "127.0.0.1",
|
|
7629
7722
|
port: 19280,
|
|
@@ -7635,9 +7728,9 @@ var DaemonCommandHandler = class {
|
|
|
7635
7728
|
res.on("data", (chunk) => data += chunk);
|
|
7636
7729
|
res.on("end", () => {
|
|
7637
7730
|
try {
|
|
7638
|
-
|
|
7731
|
+
resolve9(JSON.parse(data));
|
|
7639
7732
|
} catch {
|
|
7640
|
-
|
|
7733
|
+
resolve9({ raw: data });
|
|
7641
7734
|
}
|
|
7642
7735
|
});
|
|
7643
7736
|
});
|
|
@@ -7655,15 +7748,15 @@ var DaemonCommandHandler = class {
|
|
|
7655
7748
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
7656
7749
|
try {
|
|
7657
7750
|
const http3 = await import("http");
|
|
7658
|
-
const result = await new Promise((
|
|
7751
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7659
7752
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
7660
7753
|
let data = "";
|
|
7661
7754
|
res.on("data", (chunk) => data += chunk);
|
|
7662
7755
|
res.on("end", () => {
|
|
7663
7756
|
try {
|
|
7664
|
-
|
|
7757
|
+
resolve9(JSON.parse(data));
|
|
7665
7758
|
} catch {
|
|
7666
|
-
|
|
7759
|
+
resolve9({ raw: data });
|
|
7667
7760
|
}
|
|
7668
7761
|
});
|
|
7669
7762
|
}).on("error", reject);
|
|
@@ -7677,7 +7770,7 @@ var DaemonCommandHandler = class {
|
|
|
7677
7770
|
try {
|
|
7678
7771
|
const http3 = await import("http");
|
|
7679
7772
|
const postData = JSON.stringify(args || {});
|
|
7680
|
-
const result = await new Promise((
|
|
7773
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7681
7774
|
const req = http3.request({
|
|
7682
7775
|
hostname: "127.0.0.1",
|
|
7683
7776
|
port: 19280,
|
|
@@ -7689,9 +7782,9 @@ var DaemonCommandHandler = class {
|
|
|
7689
7782
|
res.on("data", (chunk) => data += chunk);
|
|
7690
7783
|
res.on("end", () => {
|
|
7691
7784
|
try {
|
|
7692
|
-
|
|
7785
|
+
resolve9(JSON.parse(data));
|
|
7693
7786
|
} catch {
|
|
7694
|
-
|
|
7787
|
+
resolve9({ raw: data });
|
|
7695
7788
|
}
|
|
7696
7789
|
});
|
|
7697
7790
|
});
|
|
@@ -7804,17 +7897,60 @@ var CliProviderInstance = class {
|
|
|
7804
7897
|
async onTick() {
|
|
7805
7898
|
if (this.providerSessionId) return;
|
|
7806
7899
|
let probedSessionId = null;
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7900
|
+
const probeConfig = this.provider.sessionProbe;
|
|
7901
|
+
if (probeConfig) {
|
|
7902
|
+
probedSessionId = this.probeSessionIdFromConfig(probeConfig);
|
|
7903
|
+
} else {
|
|
7904
|
+
if (this.type === "opencode-cli") {
|
|
7905
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7906
|
+
dbPath: "~/.local/share/opencode/opencode.db",
|
|
7907
|
+
query: "select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1",
|
|
7908
|
+
timestampFormat: "unix_ms"
|
|
7909
|
+
});
|
|
7910
|
+
} else if (this.type === "codex-cli") {
|
|
7911
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7912
|
+
dbPath: "~/.codex/state_5.sqlite",
|
|
7913
|
+
query: "select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1",
|
|
7914
|
+
timestampFormat: "unix_s"
|
|
7915
|
+
});
|
|
7916
|
+
} else if (this.type === "goose-cli") {
|
|
7917
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7918
|
+
dbPath: "~/.local/share/goose/sessions/sessions.db",
|
|
7919
|
+
query: "select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1",
|
|
7920
|
+
timestampFormat: "iso"
|
|
7921
|
+
});
|
|
7922
|
+
}
|
|
7813
7923
|
}
|
|
7814
7924
|
if (probedSessionId) {
|
|
7815
7925
|
this.promoteProviderSessionId(probedSessionId);
|
|
7816
7926
|
}
|
|
7817
7927
|
}
|
|
7928
|
+
/**
|
|
7929
|
+
* Generic session ID probe using declarative ProviderSessionProbe config.
|
|
7930
|
+
* Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
|
|
7931
|
+
*/
|
|
7932
|
+
probeSessionIdFromConfig(probe) {
|
|
7933
|
+
const resolvedDbPath = probe.dbPath.replace(/^~/, os9.homedir());
|
|
7934
|
+
if (!fs5.existsSync(resolvedDbPath)) return null;
|
|
7935
|
+
const directories = this.getProbeDirectories();
|
|
7936
|
+
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
7937
|
+
const tsFormat = probe.timestampFormat || "unix_ms";
|
|
7938
|
+
let timestampParam;
|
|
7939
|
+
if (tsFormat === "unix_s") {
|
|
7940
|
+
timestampParam = Math.floor(minCreatedAt / 1e3);
|
|
7941
|
+
} else if (tsFormat === "iso") {
|
|
7942
|
+
timestampParam = new Date(minCreatedAt).toISOString().slice(0, 19).replace("T", " ");
|
|
7943
|
+
} else {
|
|
7944
|
+
timestampParam = minCreatedAt;
|
|
7945
|
+
}
|
|
7946
|
+
const placeholders = this.buildSqlPlaceholderList(directories.length);
|
|
7947
|
+
const query = probe.query.replace("{dirs}", placeholders);
|
|
7948
|
+
try {
|
|
7949
|
+
return this.querySqliteText(resolvedDbPath, query, [...directories, timestampParam]);
|
|
7950
|
+
} catch {
|
|
7951
|
+
return null;
|
|
7952
|
+
}
|
|
7953
|
+
}
|
|
7818
7954
|
getState() {
|
|
7819
7955
|
const adapterStatus = this.adapter.getStatus();
|
|
7820
7956
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
@@ -8112,34 +8248,6 @@ var CliProviderInstance = class {
|
|
|
8112
8248
|
});
|
|
8113
8249
|
LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
8114
8250
|
}
|
|
8115
|
-
probeOpenCodeSessionId() {
|
|
8116
|
-
const dbPath = path8.join(os9.homedir(), ".local", "share", "opencode", "opencode.db");
|
|
8117
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8118
|
-
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
8119
|
-
const directories = this.getProbeDirectories();
|
|
8120
|
-
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;`;
|
|
8121
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8122
|
-
}
|
|
8123
|
-
probeCodexSessionId() {
|
|
8124
|
-
const dbPath = path8.join(os9.homedir(), ".codex", "state_5.sqlite");
|
|
8125
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8126
|
-
const minCreatedAt = Math.max(0, Math.floor((this.startedAt - 6e4) / 1e3));
|
|
8127
|
-
const directories = this.getProbeDirectories();
|
|
8128
|
-
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;`;
|
|
8129
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8130
|
-
}
|
|
8131
|
-
probeGooseSessionId() {
|
|
8132
|
-
const dbPath = path8.join(os9.homedir(), ".local", "share", "goose", "sessions", "sessions.db");
|
|
8133
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8134
|
-
const minCreatedAtIso = new Date(Math.max(0, this.startedAt - 6e4)).toISOString().slice(0, 19).replace("T", " ");
|
|
8135
|
-
const directories = this.getProbeDirectories();
|
|
8136
|
-
const query = `select id from sessions where working_dir in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? order by updated_at desc limit 1;`;
|
|
8137
|
-
try {
|
|
8138
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAtIso]);
|
|
8139
|
-
} catch {
|
|
8140
|
-
return null;
|
|
8141
|
-
}
|
|
8142
|
-
}
|
|
8143
8251
|
getProbeDirectories() {
|
|
8144
8252
|
const dirs = /* @__PURE__ */ new Set();
|
|
8145
8253
|
const addDir = (value) => {
|
|
@@ -8616,13 +8724,13 @@ var AcpProviderInstance = class {
|
|
|
8616
8724
|
}
|
|
8617
8725
|
this.currentStatus = "waiting_approval";
|
|
8618
8726
|
this.detectStatusTransition();
|
|
8619
|
-
const approved = await new Promise((
|
|
8620
|
-
this.permissionResolvers.push(
|
|
8727
|
+
const approved = await new Promise((resolve9) => {
|
|
8728
|
+
this.permissionResolvers.push(resolve9);
|
|
8621
8729
|
setTimeout(() => {
|
|
8622
|
-
const idx = this.permissionResolvers.indexOf(
|
|
8730
|
+
const idx = this.permissionResolvers.indexOf(resolve9);
|
|
8623
8731
|
if (idx >= 0) {
|
|
8624
8732
|
this.permissionResolvers.splice(idx, 1);
|
|
8625
|
-
|
|
8733
|
+
resolve9(false);
|
|
8626
8734
|
}
|
|
8627
8735
|
}, 3e5);
|
|
8628
8736
|
});
|
|
@@ -9413,7 +9521,19 @@ ${installInfo}`
|
|
|
9413
9521
|
return { runtimeSessionId: sessionId };
|
|
9414
9522
|
}
|
|
9415
9523
|
const cliInfo = await detectCLI(cliType, this.providerLoader);
|
|
9416
|
-
if (!cliInfo)
|
|
9524
|
+
if (!cliInfo) {
|
|
9525
|
+
const installHint = provider?.install || "";
|
|
9526
|
+
const displayName = provider?.displayName || provider?.name || cliType;
|
|
9527
|
+
const spawnCmd = provider?.spawn?.command || cliType;
|
|
9528
|
+
throw new Error(
|
|
9529
|
+
`${displayName} is not installed.
|
|
9530
|
+
Command '${spawnCmd}' not found on PATH.
|
|
9531
|
+
` + (installHint ? `
|
|
9532
|
+
${installHint}
|
|
9533
|
+
` : "") + `
|
|
9534
|
+
Run 'adhdev doctor' for detailed diagnostics.`
|
|
9535
|
+
);
|
|
9536
|
+
}
|
|
9417
9537
|
console.log(colorize("yellow", ` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
9418
9538
|
if (provider) {
|
|
9419
9539
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
@@ -9729,8 +9849,9 @@ ${installInfo}`
|
|
|
9729
9849
|
const dir = rdir.path;
|
|
9730
9850
|
if (!cliType) throw new Error("cliType required");
|
|
9731
9851
|
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9852
|
+
const prevCliArgs = found ? found.adapter.extraArgs : void 0;
|
|
9732
9853
|
if (found) await this.stopSession(found.key);
|
|
9733
|
-
await this.startSession(cliType, dir);
|
|
9854
|
+
await this.startSession(cliType, dir, args?.cliArgs || prevCliArgs, args?.initialModel);
|
|
9734
9855
|
return { success: true, restarted: true };
|
|
9735
9856
|
}
|
|
9736
9857
|
case "agent_command": {
|
|
@@ -10348,7 +10469,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10348
10469
|
return { updated: false };
|
|
10349
10470
|
}
|
|
10350
10471
|
try {
|
|
10351
|
-
const etag = await new Promise((
|
|
10472
|
+
const etag = await new Promise((resolve9, reject) => {
|
|
10352
10473
|
const options = {
|
|
10353
10474
|
method: "HEAD",
|
|
10354
10475
|
hostname: "github.com",
|
|
@@ -10366,7 +10487,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10366
10487
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
10367
10488
|
timeout: 1e4
|
|
10368
10489
|
}, (res2) => {
|
|
10369
|
-
|
|
10490
|
+
resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
10370
10491
|
});
|
|
10371
10492
|
req2.on("error", reject);
|
|
10372
10493
|
req2.on("timeout", () => {
|
|
@@ -10375,7 +10496,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10375
10496
|
});
|
|
10376
10497
|
req2.end();
|
|
10377
10498
|
} else {
|
|
10378
|
-
|
|
10499
|
+
resolve9(res.headers.etag || res.headers["last-modified"] || "");
|
|
10379
10500
|
}
|
|
10380
10501
|
});
|
|
10381
10502
|
req.on("error", reject);
|
|
@@ -10439,7 +10560,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10439
10560
|
downloadFile(url, destPath) {
|
|
10440
10561
|
const https = __require("https");
|
|
10441
10562
|
const http3 = __require("http");
|
|
10442
|
-
return new Promise((
|
|
10563
|
+
return new Promise((resolve9, reject) => {
|
|
10443
10564
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
10444
10565
|
if (redirectCount > 5) {
|
|
10445
10566
|
reject(new Error("Too many redirects"));
|
|
@@ -10459,7 +10580,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10459
10580
|
res.pipe(ws);
|
|
10460
10581
|
ws.on("finish", () => {
|
|
10461
10582
|
ws.close();
|
|
10462
|
-
|
|
10583
|
+
resolve9();
|
|
10463
10584
|
});
|
|
10464
10585
|
ws.on("error", reject);
|
|
10465
10586
|
});
|
|
@@ -10779,9 +10900,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10779
10900
|
}
|
|
10780
10901
|
}
|
|
10781
10902
|
compareVersions(a, b) {
|
|
10782
|
-
const
|
|
10783
|
-
const pa =
|
|
10784
|
-
const pb =
|
|
10903
|
+
const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
|
|
10904
|
+
const pa = normalize3(a);
|
|
10905
|
+
const pb = normalize3(b);
|
|
10785
10906
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
10786
10907
|
const va = pa[i] || 0;
|
|
10787
10908
|
const vb = pb[i] || 0;
|
|
@@ -10824,17 +10945,17 @@ async function findFreePort(ports) {
|
|
|
10824
10945
|
throw new Error("No free port found");
|
|
10825
10946
|
}
|
|
10826
10947
|
function checkPortFree(port) {
|
|
10827
|
-
return new Promise((
|
|
10948
|
+
return new Promise((resolve9) => {
|
|
10828
10949
|
const server = net.createServer();
|
|
10829
10950
|
server.unref();
|
|
10830
|
-
server.on("error", () =>
|
|
10951
|
+
server.on("error", () => resolve9(false));
|
|
10831
10952
|
server.listen(port, "127.0.0.1", () => {
|
|
10832
|
-
server.close(() =>
|
|
10953
|
+
server.close(() => resolve9(true));
|
|
10833
10954
|
});
|
|
10834
10955
|
});
|
|
10835
10956
|
}
|
|
10836
10957
|
async function isCdpActive(port) {
|
|
10837
|
-
return new Promise((
|
|
10958
|
+
return new Promise((resolve9) => {
|
|
10838
10959
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
10839
10960
|
timeout: 2e3
|
|
10840
10961
|
}, (res) => {
|
|
@@ -10843,16 +10964,16 @@ async function isCdpActive(port) {
|
|
|
10843
10964
|
res.on("end", () => {
|
|
10844
10965
|
try {
|
|
10845
10966
|
const info = JSON.parse(data);
|
|
10846
|
-
|
|
10967
|
+
resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
10847
10968
|
} catch {
|
|
10848
|
-
|
|
10969
|
+
resolve9(false);
|
|
10849
10970
|
}
|
|
10850
10971
|
});
|
|
10851
10972
|
});
|
|
10852
|
-
req.on("error", () =>
|
|
10973
|
+
req.on("error", () => resolve9(false));
|
|
10853
10974
|
req.on("timeout", () => {
|
|
10854
10975
|
req.destroy();
|
|
10855
|
-
|
|
10976
|
+
resolve9(false);
|
|
10856
10977
|
});
|
|
10857
10978
|
});
|
|
10858
10979
|
}
|
|
@@ -10994,7 +11115,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
10994
11115
|
return void 0;
|
|
10995
11116
|
}
|
|
10996
11117
|
async function launchWithCdp(options = {}) {
|
|
10997
|
-
const
|
|
11118
|
+
const platform9 = os12.platform();
|
|
10998
11119
|
let targetIde;
|
|
10999
11120
|
const ides = await detectIDEs();
|
|
11000
11121
|
if (options.ideId) {
|
|
@@ -11063,9 +11184,9 @@ async function launchWithCdp(options = {}) {
|
|
|
11063
11184
|
}
|
|
11064
11185
|
const port = await findFreePort(portPair);
|
|
11065
11186
|
try {
|
|
11066
|
-
if (
|
|
11187
|
+
if (platform9 === "darwin") {
|
|
11067
11188
|
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
11068
|
-
} else if (
|
|
11189
|
+
} else if (platform9 === "win32") {
|
|
11069
11190
|
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
11070
11191
|
} else {
|
|
11071
11192
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
@@ -11464,7 +11585,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
11464
11585
|
while (Date.now() - start < timeoutMs) {
|
|
11465
11586
|
try {
|
|
11466
11587
|
process.kill(pid, 0);
|
|
11467
|
-
await new Promise((
|
|
11588
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
11468
11589
|
} catch {
|
|
11469
11590
|
return;
|
|
11470
11591
|
}
|
|
@@ -13012,7 +13133,7 @@ import * as fs10 from "fs";
|
|
|
13012
13133
|
import * as path14 from "path";
|
|
13013
13134
|
import * as os16 from "os";
|
|
13014
13135
|
import { execSync as execSync5 } from "child_process";
|
|
13015
|
-
import { platform as
|
|
13136
|
+
import { platform as platform7 } from "os";
|
|
13016
13137
|
var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
|
|
13017
13138
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
13018
13139
|
var VersionArchive = class {
|
|
@@ -13038,7 +13159,7 @@ var VersionArchive = class {
|
|
|
13038
13159
|
entries.push({
|
|
13039
13160
|
version,
|
|
13040
13161
|
detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13041
|
-
os:
|
|
13162
|
+
os: platform7()
|
|
13042
13163
|
});
|
|
13043
13164
|
if (entries.length > MAX_ENTRIES_PER_PROVIDER) {
|
|
13044
13165
|
this.history[type] = entries.slice(-MAX_ENTRIES_PER_PROVIDER);
|
|
@@ -13078,7 +13199,7 @@ function runCommand(cmd, timeout = 1e4) {
|
|
|
13078
13199
|
}
|
|
13079
13200
|
}
|
|
13080
13201
|
function findBinary2(name) {
|
|
13081
|
-
const cmd =
|
|
13202
|
+
const cmd = platform7() === "win32" ? `where ${name}` : `which ${name}`;
|
|
13082
13203
|
const result = runCommand(cmd, 5e3);
|
|
13083
13204
|
return result ? result.split("\n")[0] : null;
|
|
13084
13205
|
}
|
|
@@ -13110,7 +13231,7 @@ function checkPathExists2(paths) {
|
|
|
13110
13231
|
return null;
|
|
13111
13232
|
}
|
|
13112
13233
|
function getMacAppVersion(appPath) {
|
|
13113
|
-
if (
|
|
13234
|
+
if (platform7() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
13114
13235
|
const plistPath = path14.join(appPath, "Contents", "Info.plist");
|
|
13115
13236
|
if (!fs10.existsSync(plistPath)) return null;
|
|
13116
13237
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
@@ -13118,7 +13239,7 @@ function getMacAppVersion(appPath) {
|
|
|
13118
13239
|
}
|
|
13119
13240
|
async function detectAllVersions(loader, archive) {
|
|
13120
13241
|
const results = [];
|
|
13121
|
-
const currentOs =
|
|
13242
|
+
const currentOs = platform7();
|
|
13122
13243
|
for (const provider of loader.getAll()) {
|
|
13123
13244
|
const info = {
|
|
13124
13245
|
type: provider.type,
|
|
@@ -14697,7 +14818,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
14697
14818
|
return { target, instance, adapter };
|
|
14698
14819
|
}
|
|
14699
14820
|
function sleep(ms) {
|
|
14700
|
-
return new Promise((
|
|
14821
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
14701
14822
|
}
|
|
14702
14823
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
14703
14824
|
const startedAt = Date.now();
|
|
@@ -16867,15 +16988,15 @@ var DevServer = class _DevServer {
|
|
|
16867
16988
|
this.json(res, 500, { error: e.message });
|
|
16868
16989
|
}
|
|
16869
16990
|
});
|
|
16870
|
-
return new Promise((
|
|
16991
|
+
return new Promise((resolve9, reject) => {
|
|
16871
16992
|
this.server.listen(port, "127.0.0.1", () => {
|
|
16872
16993
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
16873
|
-
|
|
16994
|
+
resolve9();
|
|
16874
16995
|
});
|
|
16875
16996
|
this.server.on("error", (e) => {
|
|
16876
16997
|
if (e.code === "EADDRINUSE") {
|
|
16877
16998
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
16878
|
-
|
|
16999
|
+
resolve9();
|
|
16879
17000
|
} else {
|
|
16880
17001
|
reject(e);
|
|
16881
17002
|
}
|
|
@@ -16958,20 +17079,20 @@ var DevServer = class _DevServer {
|
|
|
16958
17079
|
child.stderr?.on("data", (d) => {
|
|
16959
17080
|
stderr += d.toString().slice(0, 2e3);
|
|
16960
17081
|
});
|
|
16961
|
-
await new Promise((
|
|
17082
|
+
await new Promise((resolve9) => {
|
|
16962
17083
|
const timer = setTimeout(() => {
|
|
16963
17084
|
child.kill();
|
|
16964
|
-
|
|
17085
|
+
resolve9();
|
|
16965
17086
|
}, 3e3);
|
|
16966
17087
|
child.on("exit", () => {
|
|
16967
17088
|
clearTimeout(timer);
|
|
16968
|
-
|
|
17089
|
+
resolve9();
|
|
16969
17090
|
});
|
|
16970
17091
|
child.stdout?.once("data", () => {
|
|
16971
17092
|
setTimeout(() => {
|
|
16972
17093
|
child.kill();
|
|
16973
17094
|
clearTimeout(timer);
|
|
16974
|
-
|
|
17095
|
+
resolve9();
|
|
16975
17096
|
}, 500);
|
|
16976
17097
|
});
|
|
16977
17098
|
});
|
|
@@ -17480,14 +17601,14 @@ var DevServer = class _DevServer {
|
|
|
17480
17601
|
child.stderr?.on("data", (d) => {
|
|
17481
17602
|
stderr += d.toString();
|
|
17482
17603
|
});
|
|
17483
|
-
await new Promise((
|
|
17604
|
+
await new Promise((resolve9) => {
|
|
17484
17605
|
const timer = setTimeout(() => {
|
|
17485
17606
|
child.kill();
|
|
17486
|
-
|
|
17607
|
+
resolve9();
|
|
17487
17608
|
}, timeout);
|
|
17488
17609
|
child.on("exit", () => {
|
|
17489
17610
|
clearTimeout(timer);
|
|
17490
|
-
|
|
17611
|
+
resolve9();
|
|
17491
17612
|
});
|
|
17492
17613
|
});
|
|
17493
17614
|
const elapsed = Date.now() - start;
|
|
@@ -18162,14 +18283,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
18162
18283
|
res.end(JSON.stringify(data, null, 2));
|
|
18163
18284
|
}
|
|
18164
18285
|
async readBody(req) {
|
|
18165
|
-
return new Promise((
|
|
18286
|
+
return new Promise((resolve9) => {
|
|
18166
18287
|
let body = "";
|
|
18167
18288
|
req.on("data", (chunk) => body += chunk);
|
|
18168
18289
|
req.on("end", () => {
|
|
18169
18290
|
try {
|
|
18170
|
-
|
|
18291
|
+
resolve9(JSON.parse(body));
|
|
18171
18292
|
} catch {
|
|
18172
|
-
|
|
18293
|
+
resolve9({});
|
|
18173
18294
|
}
|
|
18174
18295
|
});
|
|
18175
18296
|
});
|
|
@@ -18638,7 +18759,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
18638
18759
|
const deadline = Date.now() + timeoutMs;
|
|
18639
18760
|
while (Date.now() < deadline) {
|
|
18640
18761
|
if (await canConnect(endpoint)) return;
|
|
18641
|
-
await new Promise((
|
|
18762
|
+
await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
|
|
18642
18763
|
}
|
|
18643
18764
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
18644
18765
|
}
|
|
@@ -18794,10 +18915,10 @@ async function installExtension(ide, extension) {
|
|
|
18794
18915
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
18795
18916
|
const fs15 = await import("fs");
|
|
18796
18917
|
fs15.writeFileSync(vsixPath, buffer);
|
|
18797
|
-
return new Promise((
|
|
18918
|
+
return new Promise((resolve9) => {
|
|
18798
18919
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
18799
18920
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
18800
|
-
|
|
18921
|
+
resolve9({
|
|
18801
18922
|
extensionId: extension.id,
|
|
18802
18923
|
marketplaceId: extension.marketplaceId,
|
|
18803
18924
|
success: !error,
|
|
@@ -18810,11 +18931,11 @@ async function installExtension(ide, extension) {
|
|
|
18810
18931
|
} catch (e) {
|
|
18811
18932
|
}
|
|
18812
18933
|
}
|
|
18813
|
-
return new Promise((
|
|
18934
|
+
return new Promise((resolve9) => {
|
|
18814
18935
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
18815
18936
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
18816
18937
|
if (error) {
|
|
18817
|
-
|
|
18938
|
+
resolve9({
|
|
18818
18939
|
extensionId: extension.id,
|
|
18819
18940
|
marketplaceId: extension.marketplaceId,
|
|
18820
18941
|
success: false,
|
|
@@ -18822,7 +18943,7 @@ async function installExtension(ide, extension) {
|
|
|
18822
18943
|
error: stderr || error.message
|
|
18823
18944
|
});
|
|
18824
18945
|
} else {
|
|
18825
|
-
|
|
18946
|
+
resolve9({
|
|
18826
18947
|
extensionId: extension.id,
|
|
18827
18948
|
marketplaceId: extension.marketplaceId,
|
|
18828
18949
|
success: true,
|