@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.js
CHANGED
|
@@ -637,6 +637,13 @@ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind)
|
|
|
637
637
|
const key = `${preference}:${ghosttyAvailable}:${backendKind}`;
|
|
638
638
|
if (loggedTerminalBackends.has(key)) return;
|
|
639
639
|
loggedTerminalBackends.add(key);
|
|
640
|
+
if (backendKind === "xterm" && preference !== "xterm" && !ghosttyAvailable) {
|
|
641
|
+
LOG.warn(
|
|
642
|
+
"Terminal",
|
|
643
|
+
`[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`
|
|
644
|
+
);
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
640
647
|
LOG.info(
|
|
641
648
|
"Terminal",
|
|
642
649
|
`[terminal-screen] backend=${backendKind} preference=${preference} ghosttyAvailable=${ghosttyAvailable}`
|
|
@@ -740,11 +747,21 @@ var init_pty_transport = __esm({
|
|
|
740
747
|
NodePtyTransportFactory = class {
|
|
741
748
|
spawn(command, args, options) {
|
|
742
749
|
if (!pty) throw new Error("node-pty is not installed");
|
|
750
|
+
let cwd = options.cwd;
|
|
751
|
+
if (cwd) {
|
|
752
|
+
try {
|
|
753
|
+
const fs15 = require("fs");
|
|
754
|
+
const stat = fs15.statSync(cwd);
|
|
755
|
+
if (!stat.isDirectory()) cwd = os7.homedir();
|
|
756
|
+
} catch {
|
|
757
|
+
cwd = os7.homedir();
|
|
758
|
+
}
|
|
759
|
+
}
|
|
743
760
|
const handle = pty.spawn(command, args, {
|
|
744
|
-
name:
|
|
761
|
+
name: "xterm-256color",
|
|
745
762
|
cols: options.cols,
|
|
746
763
|
rows: options.rows,
|
|
747
|
-
cwd
|
|
764
|
+
cwd,
|
|
748
765
|
env: options.env
|
|
749
766
|
});
|
|
750
767
|
return new NodePtyRuntimeTransport(handle);
|
|
@@ -753,6 +770,15 @@ var init_pty_transport = __esm({
|
|
|
753
770
|
}
|
|
754
771
|
});
|
|
755
772
|
|
|
773
|
+
// src/cli-adapters/spawn-env.ts
|
|
774
|
+
var import_session_host_core;
|
|
775
|
+
var init_spawn_env = __esm({
|
|
776
|
+
"src/cli-adapters/spawn-env.ts"() {
|
|
777
|
+
"use strict";
|
|
778
|
+
import_session_host_core = require("@adhdev/session-host-core");
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
|
|
756
782
|
// src/cli-adapters/provider-cli-adapter.ts
|
|
757
783
|
var provider_cli_adapter_exports = {};
|
|
758
784
|
__export(provider_cli_adapter_exports, {
|
|
@@ -768,20 +794,6 @@ function stripTerminalNoise(str) {
|
|
|
768
794
|
function sanitizeTerminalText(str) {
|
|
769
795
|
return stripTerminalNoise(stripAnsi(str));
|
|
770
796
|
}
|
|
771
|
-
function buildCliSpawnEnv(baseEnv, overrides) {
|
|
772
|
-
const env = {};
|
|
773
|
-
const source = { ...baseEnv, ...overrides || {} };
|
|
774
|
-
for (const [key, value] of Object.entries(source)) {
|
|
775
|
-
if (typeof value !== "string") continue;
|
|
776
|
-
env[key] = value;
|
|
777
|
-
}
|
|
778
|
-
for (const key of Object.keys(env)) {
|
|
779
|
-
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_")) {
|
|
780
|
-
delete env[key];
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
return env;
|
|
784
|
-
}
|
|
785
797
|
function computeTerminalQueryTail(buffer) {
|
|
786
798
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
787
799
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -910,7 +922,7 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
910
922
|
}
|
|
911
923
|
};
|
|
912
924
|
}
|
|
913
|
-
var os8, path7, import_child_process4, pty2, ProviderCliAdapter;
|
|
925
|
+
var os8, path7, import_child_process4, pty2, buildCliSpawnEnv, ProviderCliAdapter;
|
|
914
926
|
var init_provider_cli_adapter = __esm({
|
|
915
927
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
916
928
|
"use strict";
|
|
@@ -920,27 +932,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
920
932
|
init_logger();
|
|
921
933
|
init_terminal_screen();
|
|
922
934
|
init_pty_transport();
|
|
935
|
+
init_spawn_env();
|
|
923
936
|
try {
|
|
924
937
|
pty2 = require("node-pty");
|
|
925
|
-
|
|
926
|
-
try {
|
|
927
|
-
const fs15 = require("fs");
|
|
928
|
-
const ptyDir = path7.resolve(path7.dirname(require.resolve("node-pty")), "..");
|
|
929
|
-
const platformArch = `${os8.platform()}-${os8.arch()}`;
|
|
930
|
-
const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
931
|
-
if (fs15.existsSync(helper)) {
|
|
932
|
-
const stat = fs15.statSync(helper);
|
|
933
|
-
if (!(stat.mode & 73)) {
|
|
934
|
-
fs15.chmodSync(helper, stat.mode | 493);
|
|
935
|
-
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
} catch {
|
|
939
|
-
}
|
|
940
|
-
}
|
|
938
|
+
(0, import_session_host_core.ensureNodePtySpawnHelperPermissions)((msg) => LOG.info("CLI", msg));
|
|
941
939
|
} catch {
|
|
942
940
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
|
|
943
941
|
}
|
|
942
|
+
buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
|
|
944
943
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
945
944
|
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
946
945
|
this.extraArgs = extraArgs;
|
|
@@ -1307,6 +1306,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
1307
1306
|
shellArgs = ["-l", "-c", fullCmd];
|
|
1308
1307
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
1309
1308
|
} else {
|
|
1309
|
+
if (isWin) {
|
|
1310
|
+
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})` : "";
|
|
1311
|
+
if (hint) {
|
|
1312
|
+
throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1310
1315
|
throw err;
|
|
1311
1316
|
}
|
|
1312
1317
|
}
|
|
@@ -1481,7 +1486,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1481
1486
|
`[${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)}`
|
|
1482
1487
|
);
|
|
1483
1488
|
}
|
|
1484
|
-
await new Promise((
|
|
1489
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1485
1490
|
}
|
|
1486
1491
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
1487
1492
|
LOG.warn(
|
|
@@ -1868,7 +1873,7 @@ ${data.message || ""}`.trim();
|
|
|
1868
1873
|
if (this.startupParseGate) {
|
|
1869
1874
|
const deadline = Date.now() + 1e4;
|
|
1870
1875
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
1871
|
-
await new Promise((
|
|
1876
|
+
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
1872
1877
|
}
|
|
1873
1878
|
}
|
|
1874
1879
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
@@ -2059,7 +2064,8 @@ ${data.message || ""}`.trim();
|
|
|
2059
2064
|
const payload = stopCommand.endsWith("\r") || stopCommand.endsWith("\n") ? stopCommand : `${stopCommand}${this.sendKey}`;
|
|
2060
2065
|
this.ptyProcess.write(payload);
|
|
2061
2066
|
};
|
|
2062
|
-
|
|
2067
|
+
const interruptGraceMs = typeof resume.interruptGraceMs === "number" ? Math.max(100, resume.interruptGraceMs) : 500;
|
|
2068
|
+
if (wasProcessing) setTimeout(writeCommand, interruptGraceMs);
|
|
2063
2069
|
else writeCommand();
|
|
2064
2070
|
} else {
|
|
2065
2071
|
this.ptyProcess.write("");
|
|
@@ -2075,17 +2081,17 @@ ${data.message || ""}`.trim();
|
|
|
2075
2081
|
}
|
|
2076
2082
|
}
|
|
2077
2083
|
waitForStopped(timeoutMs) {
|
|
2078
|
-
return new Promise((
|
|
2084
|
+
return new Promise((resolve9) => {
|
|
2079
2085
|
const startedAt = Date.now();
|
|
2080
2086
|
const timer = setInterval(() => {
|
|
2081
2087
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
2082
2088
|
clearInterval(timer);
|
|
2083
|
-
|
|
2089
|
+
resolve9(true);
|
|
2084
2090
|
return;
|
|
2085
2091
|
}
|
|
2086
2092
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
2087
2093
|
clearInterval(timer);
|
|
2088
|
-
|
|
2094
|
+
resolve9(false);
|
|
2089
2095
|
}
|
|
2090
2096
|
}, 100);
|
|
2091
2097
|
});
|
|
@@ -2104,6 +2110,18 @@ ${data.message || ""}`.trim();
|
|
|
2104
2110
|
clearTimeout(this.submitRetryTimer);
|
|
2105
2111
|
this.submitRetryTimer = null;
|
|
2106
2112
|
}
|
|
2113
|
+
if (this.responseTimeout) {
|
|
2114
|
+
clearTimeout(this.responseTimeout);
|
|
2115
|
+
this.responseTimeout = null;
|
|
2116
|
+
}
|
|
2117
|
+
if (this.idleTimeout) {
|
|
2118
|
+
clearTimeout(this.idleTimeout);
|
|
2119
|
+
this.idleTimeout = null;
|
|
2120
|
+
}
|
|
2121
|
+
if (this.pendingScriptStatusTimer) {
|
|
2122
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2123
|
+
this.pendingScriptStatusTimer = null;
|
|
2124
|
+
}
|
|
2107
2125
|
if (this.pendingOutputParseTimer) {
|
|
2108
2126
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2109
2127
|
this.pendingOutputParseTimer = null;
|
|
@@ -2145,6 +2163,18 @@ ${data.message || ""}`.trim();
|
|
|
2145
2163
|
clearTimeout(this.submitRetryTimer);
|
|
2146
2164
|
this.submitRetryTimer = null;
|
|
2147
2165
|
}
|
|
2166
|
+
if (this.responseTimeout) {
|
|
2167
|
+
clearTimeout(this.responseTimeout);
|
|
2168
|
+
this.responseTimeout = null;
|
|
2169
|
+
}
|
|
2170
|
+
if (this.idleTimeout) {
|
|
2171
|
+
clearTimeout(this.idleTimeout);
|
|
2172
|
+
this.idleTimeout = null;
|
|
2173
|
+
}
|
|
2174
|
+
if (this.pendingScriptStatusTimer) {
|
|
2175
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
2176
|
+
this.pendingScriptStatusTimer = null;
|
|
2177
|
+
}
|
|
2148
2178
|
if (this.pendingOutputParseTimer) {
|
|
2149
2179
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2150
2180
|
this.pendingOutputParseTimer = null;
|
|
@@ -2750,8 +2780,8 @@ async function detectIDEs() {
|
|
|
2750
2780
|
if ((0, import_fs2.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
2751
2781
|
}
|
|
2752
2782
|
if (!resolvedCli && appPath && os18 === "win32") {
|
|
2753
|
-
const { dirname:
|
|
2754
|
-
const appDir =
|
|
2783
|
+
const { dirname: dirname6 } = await import("path");
|
|
2784
|
+
const appDir = dirname6(appPath);
|
|
2755
2785
|
const candidates = [
|
|
2756
2786
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
2757
2787
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -2789,20 +2819,20 @@ function parseVersion(raw) {
|
|
|
2789
2819
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
2790
2820
|
}
|
|
2791
2821
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
2792
|
-
return new Promise((
|
|
2822
|
+
return new Promise((resolve9) => {
|
|
2793
2823
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
2794
2824
|
if (err || !stdout?.trim()) {
|
|
2795
|
-
|
|
2825
|
+
resolve9(null);
|
|
2796
2826
|
} else {
|
|
2797
|
-
|
|
2827
|
+
resolve9(stdout.trim());
|
|
2798
2828
|
}
|
|
2799
2829
|
});
|
|
2800
|
-
child.on("error", () =>
|
|
2830
|
+
child.on("error", () => resolve9(null));
|
|
2801
2831
|
});
|
|
2802
2832
|
}
|
|
2803
2833
|
async function detectCLIs(providerLoader) {
|
|
2804
|
-
const
|
|
2805
|
-
const whichCmd =
|
|
2834
|
+
const platform9 = os2.platform();
|
|
2835
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
2806
2836
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
2807
2837
|
const results = await Promise.all(
|
|
2808
2838
|
cliList.map(async (cli) => {
|
|
@@ -2837,6 +2867,39 @@ async function detectCLIs(providerLoader) {
|
|
|
2837
2867
|
}
|
|
2838
2868
|
async function detectCLI(cliId, providerLoader) {
|
|
2839
2869
|
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
2870
|
+
if (providerLoader) {
|
|
2871
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
2872
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
2873
|
+
if (target) {
|
|
2874
|
+
const platform9 = os2.platform();
|
|
2875
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
2876
|
+
try {
|
|
2877
|
+
const pathResult = await execAsync(`${whichCmd} ${target.command}`);
|
|
2878
|
+
if (!pathResult) return null;
|
|
2879
|
+
const firstPath = pathResult.split("\n")[0];
|
|
2880
|
+
let version;
|
|
2881
|
+
try {
|
|
2882
|
+
const versionCommands = [
|
|
2883
|
+
target.versionCommand,
|
|
2884
|
+
`${target.command} --version`,
|
|
2885
|
+
`${target.command} -V`,
|
|
2886
|
+
`${target.command} -v`
|
|
2887
|
+
].filter((v) => !!v);
|
|
2888
|
+
for (const versionCommand of versionCommands) {
|
|
2889
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
2890
|
+
if (versionResult) {
|
|
2891
|
+
version = parseVersion(versionResult);
|
|
2892
|
+
break;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
} catch {
|
|
2896
|
+
}
|
|
2897
|
+
return { ...target, installed: true, version, path: firstPath };
|
|
2898
|
+
} catch {
|
|
2899
|
+
return null;
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2840
2903
|
const all = await detectCLIs(providerLoader);
|
|
2841
2904
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
2842
2905
|
}
|
|
@@ -2964,7 +3027,7 @@ var DaemonCdpManager = class {
|
|
|
2964
3027
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
2965
3028
|
*/
|
|
2966
3029
|
static listAllTargets(port) {
|
|
2967
|
-
return new Promise((
|
|
3030
|
+
return new Promise((resolve9) => {
|
|
2968
3031
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2969
3032
|
let data = "";
|
|
2970
3033
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2980,16 +3043,16 @@ var DaemonCdpManager = class {
|
|
|
2980
3043
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
2981
3044
|
);
|
|
2982
3045
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
2983
|
-
|
|
3046
|
+
resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
2984
3047
|
} catch {
|
|
2985
|
-
|
|
3048
|
+
resolve9([]);
|
|
2986
3049
|
}
|
|
2987
3050
|
});
|
|
2988
3051
|
});
|
|
2989
|
-
req.on("error", () =>
|
|
3052
|
+
req.on("error", () => resolve9([]));
|
|
2990
3053
|
req.setTimeout(2e3, () => {
|
|
2991
3054
|
req.destroy();
|
|
2992
|
-
|
|
3055
|
+
resolve9([]);
|
|
2993
3056
|
});
|
|
2994
3057
|
});
|
|
2995
3058
|
}
|
|
@@ -3029,7 +3092,7 @@ var DaemonCdpManager = class {
|
|
|
3029
3092
|
}
|
|
3030
3093
|
}
|
|
3031
3094
|
findTargetOnPort(port) {
|
|
3032
|
-
return new Promise((
|
|
3095
|
+
return new Promise((resolve9) => {
|
|
3033
3096
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
3034
3097
|
let data = "";
|
|
3035
3098
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -3040,7 +3103,7 @@ var DaemonCdpManager = class {
|
|
|
3040
3103
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
3041
3104
|
);
|
|
3042
3105
|
if (pages.length === 0) {
|
|
3043
|
-
|
|
3106
|
+
resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
3044
3107
|
return;
|
|
3045
3108
|
}
|
|
3046
3109
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -3050,24 +3113,24 @@ var DaemonCdpManager = class {
|
|
|
3050
3113
|
const specific = list.find((t) => t.id === this._targetId);
|
|
3051
3114
|
if (specific) {
|
|
3052
3115
|
this._pageTitle = specific.title || "";
|
|
3053
|
-
|
|
3116
|
+
resolve9(specific);
|
|
3054
3117
|
} else {
|
|
3055
3118
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
3056
|
-
|
|
3119
|
+
resolve9(null);
|
|
3057
3120
|
}
|
|
3058
3121
|
return;
|
|
3059
3122
|
}
|
|
3060
3123
|
this._pageTitle = list[0]?.title || "";
|
|
3061
|
-
|
|
3124
|
+
resolve9(list[0]);
|
|
3062
3125
|
} catch {
|
|
3063
|
-
|
|
3126
|
+
resolve9(null);
|
|
3064
3127
|
}
|
|
3065
3128
|
});
|
|
3066
3129
|
});
|
|
3067
|
-
req.on("error", () =>
|
|
3130
|
+
req.on("error", () => resolve9(null));
|
|
3068
3131
|
req.setTimeout(2e3, () => {
|
|
3069
3132
|
req.destroy();
|
|
3070
|
-
|
|
3133
|
+
resolve9(null);
|
|
3071
3134
|
});
|
|
3072
3135
|
});
|
|
3073
3136
|
}
|
|
@@ -3078,7 +3141,7 @@ var DaemonCdpManager = class {
|
|
|
3078
3141
|
this.extensionProviders = providers;
|
|
3079
3142
|
}
|
|
3080
3143
|
connectToTarget(wsUrl) {
|
|
3081
|
-
return new Promise((
|
|
3144
|
+
return new Promise((resolve9) => {
|
|
3082
3145
|
this.ws = new import_ws.default(wsUrl);
|
|
3083
3146
|
this.ws.on("open", async () => {
|
|
3084
3147
|
this._connected = true;
|
|
@@ -3088,17 +3151,17 @@ var DaemonCdpManager = class {
|
|
|
3088
3151
|
}
|
|
3089
3152
|
this.connectBrowserWs().catch(() => {
|
|
3090
3153
|
});
|
|
3091
|
-
|
|
3154
|
+
resolve9(true);
|
|
3092
3155
|
});
|
|
3093
3156
|
this.ws.on("message", (data) => {
|
|
3094
3157
|
try {
|
|
3095
3158
|
const msg = JSON.parse(data.toString());
|
|
3096
3159
|
if (msg.id && this.pending.has(msg.id)) {
|
|
3097
|
-
const { resolve:
|
|
3160
|
+
const { resolve: resolve10, reject } = this.pending.get(msg.id);
|
|
3098
3161
|
this.pending.delete(msg.id);
|
|
3099
3162
|
this.failureCount = 0;
|
|
3100
3163
|
if (msg.error) reject(new Error(msg.error.message));
|
|
3101
|
-
else
|
|
3164
|
+
else resolve10(msg.result);
|
|
3102
3165
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
3103
3166
|
this.contexts.add(msg.params.context.id);
|
|
3104
3167
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -3121,7 +3184,7 @@ var DaemonCdpManager = class {
|
|
|
3121
3184
|
this.ws.on("error", (err) => {
|
|
3122
3185
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
3123
3186
|
this._connected = false;
|
|
3124
|
-
|
|
3187
|
+
resolve9(false);
|
|
3125
3188
|
});
|
|
3126
3189
|
});
|
|
3127
3190
|
}
|
|
@@ -3135,7 +3198,7 @@ var DaemonCdpManager = class {
|
|
|
3135
3198
|
return;
|
|
3136
3199
|
}
|
|
3137
3200
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
3138
|
-
await new Promise((
|
|
3201
|
+
await new Promise((resolve9, reject) => {
|
|
3139
3202
|
this.browserWs = new import_ws.default(browserWsUrl);
|
|
3140
3203
|
this.browserWs.on("open", async () => {
|
|
3141
3204
|
this._browserConnected = true;
|
|
@@ -3145,16 +3208,16 @@ var DaemonCdpManager = class {
|
|
|
3145
3208
|
} catch (e) {
|
|
3146
3209
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
3147
3210
|
}
|
|
3148
|
-
|
|
3211
|
+
resolve9();
|
|
3149
3212
|
});
|
|
3150
3213
|
this.browserWs.on("message", (data) => {
|
|
3151
3214
|
try {
|
|
3152
3215
|
const msg = JSON.parse(data.toString());
|
|
3153
3216
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
3154
|
-
const { resolve:
|
|
3217
|
+
const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
|
|
3155
3218
|
this.browserPending.delete(msg.id);
|
|
3156
3219
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
3157
|
-
else
|
|
3220
|
+
else resolve10(msg.result);
|
|
3158
3221
|
}
|
|
3159
3222
|
} catch {
|
|
3160
3223
|
}
|
|
@@ -3174,31 +3237,31 @@ var DaemonCdpManager = class {
|
|
|
3174
3237
|
}
|
|
3175
3238
|
}
|
|
3176
3239
|
getBrowserWsUrl() {
|
|
3177
|
-
return new Promise((
|
|
3240
|
+
return new Promise((resolve9) => {
|
|
3178
3241
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
3179
3242
|
let data = "";
|
|
3180
3243
|
res.on("data", (chunk) => data += chunk.toString());
|
|
3181
3244
|
res.on("end", () => {
|
|
3182
3245
|
try {
|
|
3183
3246
|
const info = JSON.parse(data);
|
|
3184
|
-
|
|
3247
|
+
resolve9(info.webSocketDebuggerUrl || null);
|
|
3185
3248
|
} catch {
|
|
3186
|
-
|
|
3249
|
+
resolve9(null);
|
|
3187
3250
|
}
|
|
3188
3251
|
});
|
|
3189
3252
|
});
|
|
3190
|
-
req.on("error", () =>
|
|
3253
|
+
req.on("error", () => resolve9(null));
|
|
3191
3254
|
req.setTimeout(3e3, () => {
|
|
3192
3255
|
req.destroy();
|
|
3193
|
-
|
|
3256
|
+
resolve9(null);
|
|
3194
3257
|
});
|
|
3195
3258
|
});
|
|
3196
3259
|
}
|
|
3197
3260
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
3198
|
-
return new Promise((
|
|
3261
|
+
return new Promise((resolve9, reject) => {
|
|
3199
3262
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
3200
3263
|
const id = this.browserMsgId++;
|
|
3201
|
-
this.browserPending.set(id, { resolve:
|
|
3264
|
+
this.browserPending.set(id, { resolve: resolve9, reject });
|
|
3202
3265
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
3203
3266
|
setTimeout(() => {
|
|
3204
3267
|
if (this.browserPending.has(id)) {
|
|
@@ -3238,11 +3301,11 @@ var DaemonCdpManager = class {
|
|
|
3238
3301
|
}
|
|
3239
3302
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
3240
3303
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
3241
|
-
return new Promise((
|
|
3304
|
+
return new Promise((resolve9, reject) => {
|
|
3242
3305
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
3243
3306
|
if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
3244
3307
|
const id = this.msgId++;
|
|
3245
|
-
this.pending.set(id, { resolve:
|
|
3308
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
3246
3309
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
3247
3310
|
setTimeout(() => {
|
|
3248
3311
|
if (this.pending.has(id)) {
|
|
@@ -3491,7 +3554,7 @@ var DaemonCdpManager = class {
|
|
|
3491
3554
|
const browserWs = this.browserWs;
|
|
3492
3555
|
let msgId = this.browserMsgId;
|
|
3493
3556
|
const sendWs = (method, params = {}, sessionId) => {
|
|
3494
|
-
return new Promise((
|
|
3557
|
+
return new Promise((resolve9, reject) => {
|
|
3495
3558
|
const mid = msgId++;
|
|
3496
3559
|
this.browserMsgId = msgId;
|
|
3497
3560
|
const handler = (raw) => {
|
|
@@ -3500,7 +3563,7 @@ var DaemonCdpManager = class {
|
|
|
3500
3563
|
if (msg.id === mid) {
|
|
3501
3564
|
browserWs.removeListener("message", handler);
|
|
3502
3565
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
3503
|
-
else
|
|
3566
|
+
else resolve9(msg.result);
|
|
3504
3567
|
}
|
|
3505
3568
|
} catch {
|
|
3506
3569
|
}
|
|
@@ -3691,14 +3754,14 @@ var DaemonCdpManager = class {
|
|
|
3691
3754
|
if (!ws || ws.readyState !== import_ws.default.OPEN) {
|
|
3692
3755
|
throw new Error("CDP not connected");
|
|
3693
3756
|
}
|
|
3694
|
-
return new Promise((
|
|
3757
|
+
return new Promise((resolve9, reject) => {
|
|
3695
3758
|
const id = getNextId();
|
|
3696
3759
|
pendingMap.set(id, {
|
|
3697
3760
|
resolve: (result) => {
|
|
3698
3761
|
if (result?.result?.subtype === "error") {
|
|
3699
3762
|
reject(new Error(result.result.description));
|
|
3700
3763
|
} else {
|
|
3701
|
-
|
|
3764
|
+
resolve9(result?.result?.value);
|
|
3702
3765
|
}
|
|
3703
3766
|
},
|
|
3704
3767
|
reject
|
|
@@ -3730,10 +3793,10 @@ var DaemonCdpManager = class {
|
|
|
3730
3793
|
throw new Error("CDP not connected");
|
|
3731
3794
|
}
|
|
3732
3795
|
const sendViaSession = (method, params = {}) => {
|
|
3733
|
-
return new Promise((
|
|
3796
|
+
return new Promise((resolve9, reject) => {
|
|
3734
3797
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
3735
3798
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
3736
|
-
pendingMap.set(id, { resolve:
|
|
3799
|
+
pendingMap.set(id, { resolve: resolve9, reject });
|
|
3737
3800
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
3738
3801
|
setTimeout(() => {
|
|
3739
3802
|
if (pendingMap.has(id)) {
|
|
@@ -6951,17 +7014,44 @@ async function handleDiscoverAgents(h, args) {
|
|
|
6951
7014
|
const agents = await h.getCdp().discoverAgentWebviews();
|
|
6952
7015
|
return { success: true, agents };
|
|
6953
7016
|
}
|
|
7017
|
+
function normalizeWindowsRequestedPath(requestedPath) {
|
|
7018
|
+
const trimmed = requestedPath.trim();
|
|
7019
|
+
if (!trimmed) return ".";
|
|
7020
|
+
const slashDriveMatch = trimmed.match(/^[/\\]([A-Za-z])(?:[/\\](.*))?$/);
|
|
7021
|
+
if (slashDriveMatch) {
|
|
7022
|
+
const drive = slashDriveMatch[1].toUpperCase();
|
|
7023
|
+
const rest = (slashDriveMatch[2] || "").replace(/[/\\]+/g, "\\");
|
|
7024
|
+
return rest ? `${drive}:\\${rest}` : `${drive}:\\`;
|
|
7025
|
+
}
|
|
7026
|
+
if (/^[A-Za-z]:$/.test(trimmed)) {
|
|
7027
|
+
return `${trimmed[0].toUpperCase()}:\\`;
|
|
7028
|
+
}
|
|
7029
|
+
if (/^[A-Za-z]:[^/\\].*$/.test(trimmed)) {
|
|
7030
|
+
return `${trimmed[0].toUpperCase()}:\\${trimmed.slice(2).replace(/[/\\]+/g, "\\")}`;
|
|
7031
|
+
}
|
|
7032
|
+
if (/^[A-Za-z]:[/\\]/.test(trimmed)) {
|
|
7033
|
+
return `${trimmed[0].toUpperCase()}:${trimmed.slice(2)}`;
|
|
7034
|
+
}
|
|
7035
|
+
return trimmed;
|
|
7036
|
+
}
|
|
6954
7037
|
function resolveSafePath(requestedPath) {
|
|
7038
|
+
const rawPath = typeof requestedPath === "string" ? requestedPath.trim() : "";
|
|
7039
|
+
const inputPath = rawPath || ".";
|
|
6955
7040
|
const home = os6.homedir();
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
7041
|
+
if (inputPath.startsWith("~")) {
|
|
7042
|
+
return path6.resolve(path6.join(home, inputPath.slice(1)));
|
|
7043
|
+
}
|
|
7044
|
+
if (process.platform === "win32") {
|
|
7045
|
+
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
7046
|
+
if (path6.win32.isAbsolute(normalized)) {
|
|
7047
|
+
return path6.win32.normalize(normalized);
|
|
7048
|
+
}
|
|
7049
|
+
return path6.win32.resolve(normalized);
|
|
6963
7050
|
}
|
|
6964
|
-
|
|
7051
|
+
if (path6.isAbsolute(inputPath)) {
|
|
7052
|
+
return path6.normalize(inputPath);
|
|
7053
|
+
}
|
|
7054
|
+
return path6.resolve(inputPath);
|
|
6965
7055
|
}
|
|
6966
7056
|
function listDirectoryEntriesSafe(dirPath) {
|
|
6967
7057
|
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
@@ -7707,7 +7797,7 @@ var DaemonCommandHandler = class {
|
|
|
7707
7797
|
try {
|
|
7708
7798
|
const http3 = await import("http");
|
|
7709
7799
|
const postData = JSON.stringify(body);
|
|
7710
|
-
const result = await new Promise((
|
|
7800
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7711
7801
|
const req = http3.request({
|
|
7712
7802
|
hostname: "127.0.0.1",
|
|
7713
7803
|
port: 19280,
|
|
@@ -7719,9 +7809,9 @@ var DaemonCommandHandler = class {
|
|
|
7719
7809
|
res.on("data", (chunk) => data += chunk);
|
|
7720
7810
|
res.on("end", () => {
|
|
7721
7811
|
try {
|
|
7722
|
-
|
|
7812
|
+
resolve9(JSON.parse(data));
|
|
7723
7813
|
} catch {
|
|
7724
|
-
|
|
7814
|
+
resolve9({ raw: data });
|
|
7725
7815
|
}
|
|
7726
7816
|
});
|
|
7727
7817
|
});
|
|
@@ -7739,15 +7829,15 @@ var DaemonCommandHandler = class {
|
|
|
7739
7829
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
7740
7830
|
try {
|
|
7741
7831
|
const http3 = await import("http");
|
|
7742
|
-
const result = await new Promise((
|
|
7832
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7743
7833
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
7744
7834
|
let data = "";
|
|
7745
7835
|
res.on("data", (chunk) => data += chunk);
|
|
7746
7836
|
res.on("end", () => {
|
|
7747
7837
|
try {
|
|
7748
|
-
|
|
7838
|
+
resolve9(JSON.parse(data));
|
|
7749
7839
|
} catch {
|
|
7750
|
-
|
|
7840
|
+
resolve9({ raw: data });
|
|
7751
7841
|
}
|
|
7752
7842
|
});
|
|
7753
7843
|
}).on("error", reject);
|
|
@@ -7761,7 +7851,7 @@ var DaemonCommandHandler = class {
|
|
|
7761
7851
|
try {
|
|
7762
7852
|
const http3 = await import("http");
|
|
7763
7853
|
const postData = JSON.stringify(args || {});
|
|
7764
|
-
const result = await new Promise((
|
|
7854
|
+
const result = await new Promise((resolve9, reject) => {
|
|
7765
7855
|
const req = http3.request({
|
|
7766
7856
|
hostname: "127.0.0.1",
|
|
7767
7857
|
port: 19280,
|
|
@@ -7773,9 +7863,9 @@ var DaemonCommandHandler = class {
|
|
|
7773
7863
|
res.on("data", (chunk) => data += chunk);
|
|
7774
7864
|
res.on("end", () => {
|
|
7775
7865
|
try {
|
|
7776
|
-
|
|
7866
|
+
resolve9(JSON.parse(data));
|
|
7777
7867
|
} catch {
|
|
7778
|
-
|
|
7868
|
+
resolve9({ raw: data });
|
|
7779
7869
|
}
|
|
7780
7870
|
});
|
|
7781
7871
|
});
|
|
@@ -7888,17 +7978,60 @@ var CliProviderInstance = class {
|
|
|
7888
7978
|
async onTick() {
|
|
7889
7979
|
if (this.providerSessionId) return;
|
|
7890
7980
|
let probedSessionId = null;
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7981
|
+
const probeConfig = this.provider.sessionProbe;
|
|
7982
|
+
if (probeConfig) {
|
|
7983
|
+
probedSessionId = this.probeSessionIdFromConfig(probeConfig);
|
|
7984
|
+
} else {
|
|
7985
|
+
if (this.type === "opencode-cli") {
|
|
7986
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7987
|
+
dbPath: "~/.local/share/opencode/opencode.db",
|
|
7988
|
+
query: "select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1",
|
|
7989
|
+
timestampFormat: "unix_ms"
|
|
7990
|
+
});
|
|
7991
|
+
} else if (this.type === "codex-cli") {
|
|
7992
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7993
|
+
dbPath: "~/.codex/state_5.sqlite",
|
|
7994
|
+
query: "select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1",
|
|
7995
|
+
timestampFormat: "unix_s"
|
|
7996
|
+
});
|
|
7997
|
+
} else if (this.type === "goose-cli") {
|
|
7998
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
7999
|
+
dbPath: "~/.local/share/goose/sessions/sessions.db",
|
|
8000
|
+
query: "select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1",
|
|
8001
|
+
timestampFormat: "iso"
|
|
8002
|
+
});
|
|
8003
|
+
}
|
|
7897
8004
|
}
|
|
7898
8005
|
if (probedSessionId) {
|
|
7899
8006
|
this.promoteProviderSessionId(probedSessionId);
|
|
7900
8007
|
}
|
|
7901
8008
|
}
|
|
8009
|
+
/**
|
|
8010
|
+
* Generic session ID probe using declarative ProviderSessionProbe config.
|
|
8011
|
+
* Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
|
|
8012
|
+
*/
|
|
8013
|
+
probeSessionIdFromConfig(probe) {
|
|
8014
|
+
const resolvedDbPath = probe.dbPath.replace(/^~/, os9.homedir());
|
|
8015
|
+
if (!fs5.existsSync(resolvedDbPath)) return null;
|
|
8016
|
+
const directories = this.getProbeDirectories();
|
|
8017
|
+
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
8018
|
+
const tsFormat = probe.timestampFormat || "unix_ms";
|
|
8019
|
+
let timestampParam;
|
|
8020
|
+
if (tsFormat === "unix_s") {
|
|
8021
|
+
timestampParam = Math.floor(minCreatedAt / 1e3);
|
|
8022
|
+
} else if (tsFormat === "iso") {
|
|
8023
|
+
timestampParam = new Date(minCreatedAt).toISOString().slice(0, 19).replace("T", " ");
|
|
8024
|
+
} else {
|
|
8025
|
+
timestampParam = minCreatedAt;
|
|
8026
|
+
}
|
|
8027
|
+
const placeholders = this.buildSqlPlaceholderList(directories.length);
|
|
8028
|
+
const query = probe.query.replace("{dirs}", placeholders);
|
|
8029
|
+
try {
|
|
8030
|
+
return this.querySqliteText(resolvedDbPath, query, [...directories, timestampParam]);
|
|
8031
|
+
} catch {
|
|
8032
|
+
return null;
|
|
8033
|
+
}
|
|
8034
|
+
}
|
|
7902
8035
|
getState() {
|
|
7903
8036
|
const adapterStatus = this.adapter.getStatus();
|
|
7904
8037
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
@@ -8196,34 +8329,6 @@ var CliProviderInstance = class {
|
|
|
8196
8329
|
});
|
|
8197
8330
|
LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
8198
8331
|
}
|
|
8199
|
-
probeOpenCodeSessionId() {
|
|
8200
|
-
const dbPath = path8.join(os9.homedir(), ".local", "share", "opencode", "opencode.db");
|
|
8201
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8202
|
-
const minCreatedAt = Math.max(0, this.startedAt - 6e4);
|
|
8203
|
-
const directories = this.getProbeDirectories();
|
|
8204
|
-
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;`;
|
|
8205
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8206
|
-
}
|
|
8207
|
-
probeCodexSessionId() {
|
|
8208
|
-
const dbPath = path8.join(os9.homedir(), ".codex", "state_5.sqlite");
|
|
8209
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8210
|
-
const minCreatedAt = Math.max(0, Math.floor((this.startedAt - 6e4) / 1e3));
|
|
8211
|
-
const directories = this.getProbeDirectories();
|
|
8212
|
-
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;`;
|
|
8213
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
8214
|
-
}
|
|
8215
|
-
probeGooseSessionId() {
|
|
8216
|
-
const dbPath = path8.join(os9.homedir(), ".local", "share", "goose", "sessions", "sessions.db");
|
|
8217
|
-
if (!fs5.existsSync(dbPath)) return null;
|
|
8218
|
-
const minCreatedAtIso = new Date(Math.max(0, this.startedAt - 6e4)).toISOString().slice(0, 19).replace("T", " ");
|
|
8219
|
-
const directories = this.getProbeDirectories();
|
|
8220
|
-
const query = `select id from sessions where working_dir in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? order by updated_at desc limit 1;`;
|
|
8221
|
-
try {
|
|
8222
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAtIso]);
|
|
8223
|
-
} catch {
|
|
8224
|
-
return null;
|
|
8225
|
-
}
|
|
8226
|
-
}
|
|
8227
8332
|
getProbeDirectories() {
|
|
8228
8333
|
const dirs = /* @__PURE__ */ new Set();
|
|
8229
8334
|
const addDir = (value) => {
|
|
@@ -8695,13 +8800,13 @@ var AcpProviderInstance = class {
|
|
|
8695
8800
|
}
|
|
8696
8801
|
this.currentStatus = "waiting_approval";
|
|
8697
8802
|
this.detectStatusTransition();
|
|
8698
|
-
const approved = await new Promise((
|
|
8699
|
-
this.permissionResolvers.push(
|
|
8803
|
+
const approved = await new Promise((resolve9) => {
|
|
8804
|
+
this.permissionResolvers.push(resolve9);
|
|
8700
8805
|
setTimeout(() => {
|
|
8701
|
-
const idx = this.permissionResolvers.indexOf(
|
|
8806
|
+
const idx = this.permissionResolvers.indexOf(resolve9);
|
|
8702
8807
|
if (idx >= 0) {
|
|
8703
8808
|
this.permissionResolvers.splice(idx, 1);
|
|
8704
|
-
|
|
8809
|
+
resolve9(false);
|
|
8705
8810
|
}
|
|
8706
8811
|
}, 3e5);
|
|
8707
8812
|
});
|
|
@@ -9492,7 +9597,19 @@ ${installInfo}`
|
|
|
9492
9597
|
return { runtimeSessionId: sessionId };
|
|
9493
9598
|
}
|
|
9494
9599
|
const cliInfo = await detectCLI(cliType, this.providerLoader);
|
|
9495
|
-
if (!cliInfo)
|
|
9600
|
+
if (!cliInfo) {
|
|
9601
|
+
const installHint = provider?.install || "";
|
|
9602
|
+
const displayName = provider?.displayName || provider?.name || cliType;
|
|
9603
|
+
const spawnCmd = provider?.spawn?.command || cliType;
|
|
9604
|
+
throw new Error(
|
|
9605
|
+
`${displayName} is not installed.
|
|
9606
|
+
Command '${spawnCmd}' not found on PATH.
|
|
9607
|
+
` + (installHint ? `
|
|
9608
|
+
${installHint}
|
|
9609
|
+
` : "") + `
|
|
9610
|
+
Run 'adhdev doctor' for detailed diagnostics.`
|
|
9611
|
+
);
|
|
9612
|
+
}
|
|
9496
9613
|
console.log(colorize("yellow", ` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
9497
9614
|
if (provider) {
|
|
9498
9615
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
@@ -9808,8 +9925,9 @@ ${installInfo}`
|
|
|
9808
9925
|
const dir = rdir.path;
|
|
9809
9926
|
if (!cliType) throw new Error("cliType required");
|
|
9810
9927
|
const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
|
|
9928
|
+
const prevCliArgs = found ? found.adapter.extraArgs : void 0;
|
|
9811
9929
|
if (found) await this.stopSession(found.key);
|
|
9812
|
-
await this.startSession(cliType, dir);
|
|
9930
|
+
await this.startSession(cliType, dir, args?.cliArgs || prevCliArgs, args?.initialModel);
|
|
9813
9931
|
return { success: true, restarted: true };
|
|
9814
9932
|
}
|
|
9815
9933
|
case "agent_command": {
|
|
@@ -10427,7 +10545,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10427
10545
|
return { updated: false };
|
|
10428
10546
|
}
|
|
10429
10547
|
try {
|
|
10430
|
-
const etag = await new Promise((
|
|
10548
|
+
const etag = await new Promise((resolve9, reject) => {
|
|
10431
10549
|
const options = {
|
|
10432
10550
|
method: "HEAD",
|
|
10433
10551
|
hostname: "github.com",
|
|
@@ -10445,7 +10563,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10445
10563
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
10446
10564
|
timeout: 1e4
|
|
10447
10565
|
}, (res2) => {
|
|
10448
|
-
|
|
10566
|
+
resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
10449
10567
|
});
|
|
10450
10568
|
req2.on("error", reject);
|
|
10451
10569
|
req2.on("timeout", () => {
|
|
@@ -10454,7 +10572,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10454
10572
|
});
|
|
10455
10573
|
req2.end();
|
|
10456
10574
|
} else {
|
|
10457
|
-
|
|
10575
|
+
resolve9(res.headers.etag || res.headers["last-modified"] || "");
|
|
10458
10576
|
}
|
|
10459
10577
|
});
|
|
10460
10578
|
req.on("error", reject);
|
|
@@ -10518,7 +10636,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10518
10636
|
downloadFile(url, destPath) {
|
|
10519
10637
|
const https = require("https");
|
|
10520
10638
|
const http3 = require("http");
|
|
10521
|
-
return new Promise((
|
|
10639
|
+
return new Promise((resolve9, reject) => {
|
|
10522
10640
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
10523
10641
|
if (redirectCount > 5) {
|
|
10524
10642
|
reject(new Error("Too many redirects"));
|
|
@@ -10538,7 +10656,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10538
10656
|
res.pipe(ws);
|
|
10539
10657
|
ws.on("finish", () => {
|
|
10540
10658
|
ws.close();
|
|
10541
|
-
|
|
10659
|
+
resolve9();
|
|
10542
10660
|
});
|
|
10543
10661
|
ws.on("error", reject);
|
|
10544
10662
|
});
|
|
@@ -10858,9 +10976,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
10858
10976
|
}
|
|
10859
10977
|
}
|
|
10860
10978
|
compareVersions(a, b) {
|
|
10861
|
-
const
|
|
10862
|
-
const pa =
|
|
10863
|
-
const pb =
|
|
10979
|
+
const normalize3 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
|
|
10980
|
+
const pa = normalize3(a);
|
|
10981
|
+
const pb = normalize3(b);
|
|
10864
10982
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
10865
10983
|
const va = pa[i] || 0;
|
|
10866
10984
|
const vb = pb[i] || 0;
|
|
@@ -10903,17 +11021,17 @@ async function findFreePort(ports) {
|
|
|
10903
11021
|
throw new Error("No free port found");
|
|
10904
11022
|
}
|
|
10905
11023
|
function checkPortFree(port) {
|
|
10906
|
-
return new Promise((
|
|
11024
|
+
return new Promise((resolve9) => {
|
|
10907
11025
|
const server = net.createServer();
|
|
10908
11026
|
server.unref();
|
|
10909
|
-
server.on("error", () =>
|
|
11027
|
+
server.on("error", () => resolve9(false));
|
|
10910
11028
|
server.listen(port, "127.0.0.1", () => {
|
|
10911
|
-
server.close(() =>
|
|
11029
|
+
server.close(() => resolve9(true));
|
|
10912
11030
|
});
|
|
10913
11031
|
});
|
|
10914
11032
|
}
|
|
10915
11033
|
async function isCdpActive(port) {
|
|
10916
|
-
return new Promise((
|
|
11034
|
+
return new Promise((resolve9) => {
|
|
10917
11035
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
10918
11036
|
timeout: 2e3
|
|
10919
11037
|
}, (res) => {
|
|
@@ -10922,16 +11040,16 @@ async function isCdpActive(port) {
|
|
|
10922
11040
|
res.on("end", () => {
|
|
10923
11041
|
try {
|
|
10924
11042
|
const info = JSON.parse(data);
|
|
10925
|
-
|
|
11043
|
+
resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
10926
11044
|
} catch {
|
|
10927
|
-
|
|
11045
|
+
resolve9(false);
|
|
10928
11046
|
}
|
|
10929
11047
|
});
|
|
10930
11048
|
});
|
|
10931
|
-
req.on("error", () =>
|
|
11049
|
+
req.on("error", () => resolve9(false));
|
|
10932
11050
|
req.on("timeout", () => {
|
|
10933
11051
|
req.destroy();
|
|
10934
|
-
|
|
11052
|
+
resolve9(false);
|
|
10935
11053
|
});
|
|
10936
11054
|
});
|
|
10937
11055
|
}
|
|
@@ -11073,7 +11191,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
11073
11191
|
return void 0;
|
|
11074
11192
|
}
|
|
11075
11193
|
async function launchWithCdp(options = {}) {
|
|
11076
|
-
const
|
|
11194
|
+
const platform9 = os12.platform();
|
|
11077
11195
|
let targetIde;
|
|
11078
11196
|
const ides = await detectIDEs();
|
|
11079
11197
|
if (options.ideId) {
|
|
@@ -11142,9 +11260,9 @@ async function launchWithCdp(options = {}) {
|
|
|
11142
11260
|
}
|
|
11143
11261
|
const port = await findFreePort(portPair);
|
|
11144
11262
|
try {
|
|
11145
|
-
if (
|
|
11263
|
+
if (platform9 === "darwin") {
|
|
11146
11264
|
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
11147
|
-
} else if (
|
|
11265
|
+
} else if (platform9 === "win32") {
|
|
11148
11266
|
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
11149
11267
|
} else {
|
|
11150
11268
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
@@ -11543,7 +11661,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
11543
11661
|
while (Date.now() - start < timeoutMs) {
|
|
11544
11662
|
try {
|
|
11545
11663
|
process.kill(pid, 0);
|
|
11546
|
-
await new Promise((
|
|
11664
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
11547
11665
|
} catch {
|
|
11548
11666
|
return;
|
|
11549
11667
|
}
|
|
@@ -14776,7 +14894,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
14776
14894
|
return { target, instance, adapter };
|
|
14777
14895
|
}
|
|
14778
14896
|
function sleep(ms) {
|
|
14779
|
-
return new Promise((
|
|
14897
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
14780
14898
|
}
|
|
14781
14899
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
14782
14900
|
const startedAt = Date.now();
|
|
@@ -16946,15 +17064,15 @@ var DevServer = class _DevServer {
|
|
|
16946
17064
|
this.json(res, 500, { error: e.message });
|
|
16947
17065
|
}
|
|
16948
17066
|
});
|
|
16949
|
-
return new Promise((
|
|
17067
|
+
return new Promise((resolve9, reject) => {
|
|
16950
17068
|
this.server.listen(port, "127.0.0.1", () => {
|
|
16951
17069
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
16952
|
-
|
|
17070
|
+
resolve9();
|
|
16953
17071
|
});
|
|
16954
17072
|
this.server.on("error", (e) => {
|
|
16955
17073
|
if (e.code === "EADDRINUSE") {
|
|
16956
17074
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
16957
|
-
|
|
17075
|
+
resolve9();
|
|
16958
17076
|
} else {
|
|
16959
17077
|
reject(e);
|
|
16960
17078
|
}
|
|
@@ -17037,20 +17155,20 @@ var DevServer = class _DevServer {
|
|
|
17037
17155
|
child.stderr?.on("data", (d) => {
|
|
17038
17156
|
stderr += d.toString().slice(0, 2e3);
|
|
17039
17157
|
});
|
|
17040
|
-
await new Promise((
|
|
17158
|
+
await new Promise((resolve9) => {
|
|
17041
17159
|
const timer = setTimeout(() => {
|
|
17042
17160
|
child.kill();
|
|
17043
|
-
|
|
17161
|
+
resolve9();
|
|
17044
17162
|
}, 3e3);
|
|
17045
17163
|
child.on("exit", () => {
|
|
17046
17164
|
clearTimeout(timer);
|
|
17047
|
-
|
|
17165
|
+
resolve9();
|
|
17048
17166
|
});
|
|
17049
17167
|
child.stdout?.once("data", () => {
|
|
17050
17168
|
setTimeout(() => {
|
|
17051
17169
|
child.kill();
|
|
17052
17170
|
clearTimeout(timer);
|
|
17053
|
-
|
|
17171
|
+
resolve9();
|
|
17054
17172
|
}, 500);
|
|
17055
17173
|
});
|
|
17056
17174
|
});
|
|
@@ -17559,14 +17677,14 @@ var DevServer = class _DevServer {
|
|
|
17559
17677
|
child.stderr?.on("data", (d) => {
|
|
17560
17678
|
stderr += d.toString();
|
|
17561
17679
|
});
|
|
17562
|
-
await new Promise((
|
|
17680
|
+
await new Promise((resolve9) => {
|
|
17563
17681
|
const timer = setTimeout(() => {
|
|
17564
17682
|
child.kill();
|
|
17565
|
-
|
|
17683
|
+
resolve9();
|
|
17566
17684
|
}, timeout);
|
|
17567
17685
|
child.on("exit", () => {
|
|
17568
17686
|
clearTimeout(timer);
|
|
17569
|
-
|
|
17687
|
+
resolve9();
|
|
17570
17688
|
});
|
|
17571
17689
|
});
|
|
17572
17690
|
const elapsed = Date.now() - start;
|
|
@@ -18241,14 +18359,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
18241
18359
|
res.end(JSON.stringify(data, null, 2));
|
|
18242
18360
|
}
|
|
18243
18361
|
async readBody(req) {
|
|
18244
|
-
return new Promise((
|
|
18362
|
+
return new Promise((resolve9) => {
|
|
18245
18363
|
let body = "";
|
|
18246
18364
|
req.on("data", (chunk) => body += chunk);
|
|
18247
18365
|
req.on("end", () => {
|
|
18248
18366
|
try {
|
|
18249
|
-
|
|
18367
|
+
resolve9(JSON.parse(body));
|
|
18250
18368
|
} catch {
|
|
18251
|
-
|
|
18369
|
+
resolve9({});
|
|
18252
18370
|
}
|
|
18253
18371
|
});
|
|
18254
18372
|
});
|
|
@@ -18321,12 +18439,12 @@ init_provider_cli_adapter();
|
|
|
18321
18439
|
init_pty_transport();
|
|
18322
18440
|
|
|
18323
18441
|
// src/cli-adapters/session-host-transport.ts
|
|
18324
|
-
var
|
|
18442
|
+
var import_session_host_core2 = require("@adhdev/session-host-core");
|
|
18325
18443
|
init_logger();
|
|
18326
18444
|
var SessionHostRuntimeTransport = class {
|
|
18327
18445
|
constructor(options) {
|
|
18328
18446
|
this.options = options;
|
|
18329
|
-
this.client = new
|
|
18447
|
+
this.client = new import_session_host_core2.SessionHostClient({
|
|
18330
18448
|
endpoint: options.endpoint,
|
|
18331
18449
|
appName: options.appName
|
|
18332
18450
|
});
|
|
@@ -18695,11 +18813,11 @@ var SessionHostPtyTransportFactory = class {
|
|
|
18695
18813
|
};
|
|
18696
18814
|
|
|
18697
18815
|
// src/session-host/runtime-support.ts
|
|
18698
|
-
var
|
|
18816
|
+
var import_session_host_core3 = require("@adhdev/session-host-core");
|
|
18699
18817
|
var STARTUP_TIMEOUT_MS = 8e3;
|
|
18700
18818
|
var STARTUP_POLL_MS = 200;
|
|
18701
18819
|
async function canConnect(endpoint) {
|
|
18702
|
-
const client = new
|
|
18820
|
+
const client = new import_session_host_core3.SessionHostClient({ endpoint });
|
|
18703
18821
|
try {
|
|
18704
18822
|
await client.connect();
|
|
18705
18823
|
await client.close();
|
|
@@ -18712,19 +18830,19 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
18712
18830
|
const deadline = Date.now() + timeoutMs;
|
|
18713
18831
|
while (Date.now() < deadline) {
|
|
18714
18832
|
if (await canConnect(endpoint)) return;
|
|
18715
|
-
await new Promise((
|
|
18833
|
+
await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
|
|
18716
18834
|
}
|
|
18717
18835
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
18718
18836
|
}
|
|
18719
18837
|
async function ensureSessionHostReady(options) {
|
|
18720
|
-
const endpoint = (0,
|
|
18838
|
+
const endpoint = (0, import_session_host_core3.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
|
|
18721
18839
|
if (await canConnect(endpoint)) return endpoint;
|
|
18722
18840
|
options.spawnHost();
|
|
18723
18841
|
await waitForReady(endpoint, options.timeoutMs);
|
|
18724
18842
|
return endpoint;
|
|
18725
18843
|
}
|
|
18726
18844
|
async function listHostedCliRuntimes(endpoint) {
|
|
18727
|
-
const client = new
|
|
18845
|
+
const client = new import_session_host_core3.SessionHostClient({ endpoint });
|
|
18728
18846
|
try {
|
|
18729
18847
|
const response = await client.request({
|
|
18730
18848
|
type: "list_sessions",
|
|
@@ -18868,10 +18986,10 @@ async function installExtension(ide, extension) {
|
|
|
18868
18986
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
18869
18987
|
const fs15 = await import("fs");
|
|
18870
18988
|
fs15.writeFileSync(vsixPath, buffer);
|
|
18871
|
-
return new Promise((
|
|
18989
|
+
return new Promise((resolve9) => {
|
|
18872
18990
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
18873
18991
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
18874
|
-
|
|
18992
|
+
resolve9({
|
|
18875
18993
|
extensionId: extension.id,
|
|
18876
18994
|
marketplaceId: extension.marketplaceId,
|
|
18877
18995
|
success: !error,
|
|
@@ -18884,11 +19002,11 @@ async function installExtension(ide, extension) {
|
|
|
18884
19002
|
} catch (e) {
|
|
18885
19003
|
}
|
|
18886
19004
|
}
|
|
18887
|
-
return new Promise((
|
|
19005
|
+
return new Promise((resolve9) => {
|
|
18888
19006
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
18889
19007
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
18890
19008
|
if (error) {
|
|
18891
|
-
|
|
19009
|
+
resolve9({
|
|
18892
19010
|
extensionId: extension.id,
|
|
18893
19011
|
marketplaceId: extension.marketplaceId,
|
|
18894
19012
|
success: false,
|
|
@@ -18896,7 +19014,7 @@ async function installExtension(ide, extension) {
|
|
|
18896
19014
|
error: stderr || error.message
|
|
18897
19015
|
});
|
|
18898
19016
|
} else {
|
|
18899
|
-
|
|
19017
|
+
resolve9({
|
|
18900
19018
|
extensionId: extension.id,
|
|
18901
19019
|
marketplaceId: extension.marketplaceId,
|
|
18902
19020
|
success: true,
|