@adhdev/daemon-core 0.6.72 → 0.6.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +25 -24
- package/dist/index.js +275 -198
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/boot/daemon-lifecycle.ts +24 -0
- package/src/cli-adapters/provider-cli-adapter.ts +39 -8
- package/src/daemon/dev-server.ts +108 -57
- package/src/index.ts +2 -2
- package/src/providers/provider-loader.ts +51 -59
package/dist/index.js
CHANGED
|
@@ -912,6 +912,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
912
912
|
spawnAt = 0;
|
|
913
913
|
// PTY I/O
|
|
914
914
|
onPtyDataCallback = null;
|
|
915
|
+
pendingOutputParseBuffer = "";
|
|
916
|
+
pendingOutputParseTimer = null;
|
|
915
917
|
ptyOutputBuffer = "";
|
|
916
918
|
ptyOutputFlushTimer = null;
|
|
917
919
|
// Server log forwarding
|
|
@@ -1007,6 +1009,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
1007
1009
|
setOnPtyData(callback) {
|
|
1008
1010
|
this.onPtyDataCallback = callback;
|
|
1009
1011
|
}
|
|
1012
|
+
flushPendingOutputParse() {
|
|
1013
|
+
if (this.pendingOutputParseTimer) {
|
|
1014
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
1015
|
+
this.pendingOutputParseTimer = null;
|
|
1016
|
+
}
|
|
1017
|
+
if (!this.pendingOutputParseBuffer) return;
|
|
1018
|
+
const rawData = this.pendingOutputParseBuffer;
|
|
1019
|
+
this.pendingOutputParseBuffer = "";
|
|
1020
|
+
this.handleOutput(rawData);
|
|
1021
|
+
}
|
|
1010
1022
|
async spawn() {
|
|
1011
1023
|
if (this.ptyProcess) return;
|
|
1012
1024
|
if (!pty) throw new Error("node-pty is not installed");
|
|
@@ -1055,7 +1067,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
1055
1067
|
}
|
|
1056
1068
|
}
|
|
1057
1069
|
this.ptyProcess.onData((data) => {
|
|
1058
|
-
|
|
1070
|
+
if (Date.now() < this.resizeSuppressUntil) return;
|
|
1071
|
+
if (data.includes("\x1B[6n") || data.includes("\x1B[?6n")) {
|
|
1072
|
+
this.ptyProcess?.write("\x1B[1;1R");
|
|
1073
|
+
}
|
|
1074
|
+
this.pendingOutputParseBuffer += data;
|
|
1075
|
+
if (!this.pendingOutputParseTimer) {
|
|
1076
|
+
this.pendingOutputParseTimer = setTimeout(() => {
|
|
1077
|
+
this.pendingOutputParseTimer = null;
|
|
1078
|
+
this.flushPendingOutputParse();
|
|
1079
|
+
}, this.timeouts.ptyFlush);
|
|
1080
|
+
}
|
|
1059
1081
|
if (this.onPtyDataCallback) {
|
|
1060
1082
|
this.ptyOutputBuffer += data;
|
|
1061
1083
|
if (!this.ptyOutputFlushTimer) {
|
|
@@ -1071,6 +1093,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1071
1093
|
});
|
|
1072
1094
|
this.ptyProcess.onExit(({ exitCode }) => {
|
|
1073
1095
|
LOG.info("CLI", `[${this.cliType}] Exit code ${exitCode}`);
|
|
1096
|
+
this.flushPendingOutputParse();
|
|
1074
1097
|
this.ptyProcess = null;
|
|
1075
1098
|
this.setStatus("stopped", "pty_exit");
|
|
1076
1099
|
this.ready = false;
|
|
@@ -1090,10 +1113,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
1090
1113
|
}
|
|
1091
1114
|
// ─── Output Handling ────────────────────────────
|
|
1092
1115
|
handleOutput(rawData) {
|
|
1093
|
-
if (Date.now() < this.resizeSuppressUntil) return;
|
|
1094
|
-
if (rawData.includes("\x1B[6n") || rawData.includes("\x1B[?6n")) {
|
|
1095
|
-
this.ptyProcess?.write("\x1B[1;1R");
|
|
1096
|
-
}
|
|
1097
1116
|
this.terminalScreen.write(rawData);
|
|
1098
1117
|
this.terminalHistory = mergeTerminalHistory(this.terminalHistory, this.terminalScreen.getText());
|
|
1099
1118
|
const cleanData = stripAnsi(rawData);
|
|
@@ -1444,7 +1463,7 @@ ${data.message || ""}`.trim();
|
|
|
1444
1463
|
if (this.startupParseGate) {
|
|
1445
1464
|
const deadline = Date.now() + 1e4;
|
|
1446
1465
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
1447
|
-
await new Promise((
|
|
1466
|
+
await new Promise((resolve8) => setTimeout(resolve8, 50));
|
|
1448
1467
|
}
|
|
1449
1468
|
}
|
|
1450
1469
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
@@ -1581,6 +1600,16 @@ ${data.message || ""}`.trim();
|
|
|
1581
1600
|
clearTimeout(this.submitRetryTimer);
|
|
1582
1601
|
this.submitRetryTimer = null;
|
|
1583
1602
|
}
|
|
1603
|
+
if (this.pendingOutputParseTimer) {
|
|
1604
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
1605
|
+
this.pendingOutputParseTimer = null;
|
|
1606
|
+
}
|
|
1607
|
+
this.pendingOutputParseBuffer = "";
|
|
1608
|
+
if (this.ptyOutputFlushTimer) {
|
|
1609
|
+
clearTimeout(this.ptyOutputFlushTimer);
|
|
1610
|
+
this.ptyOutputFlushTimer = null;
|
|
1611
|
+
}
|
|
1612
|
+
this.ptyOutputBuffer = "";
|
|
1584
1613
|
if (this.ptyProcess) {
|
|
1585
1614
|
this.ptyProcess.write("");
|
|
1586
1615
|
setTimeout(() => {
|
|
@@ -1606,6 +1635,16 @@ ${data.message || ""}`.trim();
|
|
|
1606
1635
|
this.currentTurnScope = null;
|
|
1607
1636
|
this.submitRetryUsed = false;
|
|
1608
1637
|
this.submitRetryPromptSnippet = "";
|
|
1638
|
+
if (this.pendingOutputParseTimer) {
|
|
1639
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
1640
|
+
this.pendingOutputParseTimer = null;
|
|
1641
|
+
}
|
|
1642
|
+
this.pendingOutputParseBuffer = "";
|
|
1643
|
+
if (this.ptyOutputFlushTimer) {
|
|
1644
|
+
clearTimeout(this.ptyOutputFlushTimer);
|
|
1645
|
+
this.ptyOutputFlushTimer = null;
|
|
1646
|
+
}
|
|
1647
|
+
this.ptyOutputBuffer = "";
|
|
1609
1648
|
this.terminalScreen.reset();
|
|
1610
1649
|
this.onStatusChange?.();
|
|
1611
1650
|
}
|
|
@@ -1683,6 +1722,8 @@ ${data.message || ""}`.trim();
|
|
|
1683
1722
|
scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
|
|
1684
1723
|
statusHistory: this.statusHistory.slice(-30),
|
|
1685
1724
|
timeouts: this.timeouts,
|
|
1725
|
+
pendingOutputParseBufferLength: this.pendingOutputParseBuffer.length,
|
|
1726
|
+
pendingOutputParseScheduled: !!this.pendingOutputParseTimer,
|
|
1686
1727
|
ptyAlive: !!this.ptyProcess
|
|
1687
1728
|
};
|
|
1688
1729
|
}
|
|
@@ -1756,6 +1797,7 @@ __export(index_exports, {
|
|
|
1756
1797
|
setLogLevel: () => setLogLevel,
|
|
1757
1798
|
setupIdeInstance: () => setupIdeInstance,
|
|
1758
1799
|
shutdownDaemonComponents: () => shutdownDaemonComponents,
|
|
1800
|
+
startDaemonDevSupport: () => startDaemonDevSupport,
|
|
1759
1801
|
updateConfig: () => updateConfig
|
|
1760
1802
|
});
|
|
1761
1803
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -1905,15 +1947,15 @@ async function detectIDEs() {
|
|
|
1905
1947
|
var import_child_process2 = require("child_process");
|
|
1906
1948
|
var os2 = __toESM(require("os"));
|
|
1907
1949
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
1908
|
-
return new Promise((
|
|
1950
|
+
return new Promise((resolve8) => {
|
|
1909
1951
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
1910
1952
|
if (err || !stdout?.trim()) {
|
|
1911
|
-
|
|
1953
|
+
resolve8(null);
|
|
1912
1954
|
} else {
|
|
1913
|
-
|
|
1955
|
+
resolve8(stdout.trim());
|
|
1914
1956
|
}
|
|
1915
1957
|
});
|
|
1916
|
-
child.on("error", () =>
|
|
1958
|
+
child.on("error", () => resolve8(null));
|
|
1917
1959
|
});
|
|
1918
1960
|
}
|
|
1919
1961
|
async function detectCLIs(providerLoader) {
|
|
@@ -2072,7 +2114,7 @@ var DaemonCdpManager = class {
|
|
|
2072
2114
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
2073
2115
|
*/
|
|
2074
2116
|
static listAllTargets(port) {
|
|
2075
|
-
return new Promise((
|
|
2117
|
+
return new Promise((resolve8) => {
|
|
2076
2118
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2077
2119
|
let data = "";
|
|
2078
2120
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2088,16 +2130,16 @@ var DaemonCdpManager = class {
|
|
|
2088
2130
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
2089
2131
|
);
|
|
2090
2132
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
2091
|
-
|
|
2133
|
+
resolve8(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
2092
2134
|
} catch {
|
|
2093
|
-
|
|
2135
|
+
resolve8([]);
|
|
2094
2136
|
}
|
|
2095
2137
|
});
|
|
2096
2138
|
});
|
|
2097
|
-
req.on("error", () =>
|
|
2139
|
+
req.on("error", () => resolve8([]));
|
|
2098
2140
|
req.setTimeout(2e3, () => {
|
|
2099
2141
|
req.destroy();
|
|
2100
|
-
|
|
2142
|
+
resolve8([]);
|
|
2101
2143
|
});
|
|
2102
2144
|
});
|
|
2103
2145
|
}
|
|
@@ -2137,7 +2179,7 @@ var DaemonCdpManager = class {
|
|
|
2137
2179
|
}
|
|
2138
2180
|
}
|
|
2139
2181
|
findTargetOnPort(port) {
|
|
2140
|
-
return new Promise((
|
|
2182
|
+
return new Promise((resolve8) => {
|
|
2141
2183
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
2142
2184
|
let data = "";
|
|
2143
2185
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -2148,7 +2190,7 @@ var DaemonCdpManager = class {
|
|
|
2148
2190
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
2149
2191
|
);
|
|
2150
2192
|
if (pages.length === 0) {
|
|
2151
|
-
|
|
2193
|
+
resolve8(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
2152
2194
|
return;
|
|
2153
2195
|
}
|
|
2154
2196
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -2158,24 +2200,24 @@ var DaemonCdpManager = class {
|
|
|
2158
2200
|
const specific = list.find((t) => t.id === this._targetId);
|
|
2159
2201
|
if (specific) {
|
|
2160
2202
|
this._pageTitle = specific.title || "";
|
|
2161
|
-
|
|
2203
|
+
resolve8(specific);
|
|
2162
2204
|
} else {
|
|
2163
2205
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
2164
|
-
|
|
2206
|
+
resolve8(null);
|
|
2165
2207
|
}
|
|
2166
2208
|
return;
|
|
2167
2209
|
}
|
|
2168
2210
|
this._pageTitle = list[0]?.title || "";
|
|
2169
|
-
|
|
2211
|
+
resolve8(list[0]);
|
|
2170
2212
|
} catch {
|
|
2171
|
-
|
|
2213
|
+
resolve8(null);
|
|
2172
2214
|
}
|
|
2173
2215
|
});
|
|
2174
2216
|
});
|
|
2175
|
-
req.on("error", () =>
|
|
2217
|
+
req.on("error", () => resolve8(null));
|
|
2176
2218
|
req.setTimeout(2e3, () => {
|
|
2177
2219
|
req.destroy();
|
|
2178
|
-
|
|
2220
|
+
resolve8(null);
|
|
2179
2221
|
});
|
|
2180
2222
|
});
|
|
2181
2223
|
}
|
|
@@ -2186,7 +2228,7 @@ var DaemonCdpManager = class {
|
|
|
2186
2228
|
this.extensionProviders = providers;
|
|
2187
2229
|
}
|
|
2188
2230
|
connectToTarget(wsUrl) {
|
|
2189
|
-
return new Promise((
|
|
2231
|
+
return new Promise((resolve8) => {
|
|
2190
2232
|
this.ws = new import_ws.default(wsUrl);
|
|
2191
2233
|
this.ws.on("open", async () => {
|
|
2192
2234
|
this._connected = true;
|
|
@@ -2196,17 +2238,17 @@ var DaemonCdpManager = class {
|
|
|
2196
2238
|
}
|
|
2197
2239
|
this.connectBrowserWs().catch(() => {
|
|
2198
2240
|
});
|
|
2199
|
-
|
|
2241
|
+
resolve8(true);
|
|
2200
2242
|
});
|
|
2201
2243
|
this.ws.on("message", (data) => {
|
|
2202
2244
|
try {
|
|
2203
2245
|
const msg = JSON.parse(data.toString());
|
|
2204
2246
|
if (msg.id && this.pending.has(msg.id)) {
|
|
2205
|
-
const { resolve:
|
|
2247
|
+
const { resolve: resolve9, reject } = this.pending.get(msg.id);
|
|
2206
2248
|
this.pending.delete(msg.id);
|
|
2207
2249
|
this.failureCount = 0;
|
|
2208
2250
|
if (msg.error) reject(new Error(msg.error.message));
|
|
2209
|
-
else
|
|
2251
|
+
else resolve9(msg.result);
|
|
2210
2252
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
2211
2253
|
this.contexts.add(msg.params.context.id);
|
|
2212
2254
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -2229,7 +2271,7 @@ var DaemonCdpManager = class {
|
|
|
2229
2271
|
this.ws.on("error", (err) => {
|
|
2230
2272
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
2231
2273
|
this._connected = false;
|
|
2232
|
-
|
|
2274
|
+
resolve8(false);
|
|
2233
2275
|
});
|
|
2234
2276
|
});
|
|
2235
2277
|
}
|
|
@@ -2243,7 +2285,7 @@ var DaemonCdpManager = class {
|
|
|
2243
2285
|
return;
|
|
2244
2286
|
}
|
|
2245
2287
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
2246
|
-
await new Promise((
|
|
2288
|
+
await new Promise((resolve8, reject) => {
|
|
2247
2289
|
this.browserWs = new import_ws.default(browserWsUrl);
|
|
2248
2290
|
this.browserWs.on("open", async () => {
|
|
2249
2291
|
this._browserConnected = true;
|
|
@@ -2253,16 +2295,16 @@ var DaemonCdpManager = class {
|
|
|
2253
2295
|
} catch (e) {
|
|
2254
2296
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
2255
2297
|
}
|
|
2256
|
-
|
|
2298
|
+
resolve8();
|
|
2257
2299
|
});
|
|
2258
2300
|
this.browserWs.on("message", (data) => {
|
|
2259
2301
|
try {
|
|
2260
2302
|
const msg = JSON.parse(data.toString());
|
|
2261
2303
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
2262
|
-
const { resolve:
|
|
2304
|
+
const { resolve: resolve9, reject: reject2 } = this.browserPending.get(msg.id);
|
|
2263
2305
|
this.browserPending.delete(msg.id);
|
|
2264
2306
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
2265
|
-
else
|
|
2307
|
+
else resolve9(msg.result);
|
|
2266
2308
|
}
|
|
2267
2309
|
} catch {
|
|
2268
2310
|
}
|
|
@@ -2282,31 +2324,31 @@ var DaemonCdpManager = class {
|
|
|
2282
2324
|
}
|
|
2283
2325
|
}
|
|
2284
2326
|
getBrowserWsUrl() {
|
|
2285
|
-
return new Promise((
|
|
2327
|
+
return new Promise((resolve8) => {
|
|
2286
2328
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
2287
2329
|
let data = "";
|
|
2288
2330
|
res.on("data", (chunk) => data += chunk.toString());
|
|
2289
2331
|
res.on("end", () => {
|
|
2290
2332
|
try {
|
|
2291
2333
|
const info = JSON.parse(data);
|
|
2292
|
-
|
|
2334
|
+
resolve8(info.webSocketDebuggerUrl || null);
|
|
2293
2335
|
} catch {
|
|
2294
|
-
|
|
2336
|
+
resolve8(null);
|
|
2295
2337
|
}
|
|
2296
2338
|
});
|
|
2297
2339
|
});
|
|
2298
|
-
req.on("error", () =>
|
|
2340
|
+
req.on("error", () => resolve8(null));
|
|
2299
2341
|
req.setTimeout(3e3, () => {
|
|
2300
2342
|
req.destroy();
|
|
2301
|
-
|
|
2343
|
+
resolve8(null);
|
|
2302
2344
|
});
|
|
2303
2345
|
});
|
|
2304
2346
|
}
|
|
2305
2347
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
2306
|
-
return new Promise((
|
|
2348
|
+
return new Promise((resolve8, reject) => {
|
|
2307
2349
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
2308
2350
|
const id = this.browserMsgId++;
|
|
2309
|
-
this.browserPending.set(id, { resolve:
|
|
2351
|
+
this.browserPending.set(id, { resolve: resolve8, reject });
|
|
2310
2352
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
2311
2353
|
setTimeout(() => {
|
|
2312
2354
|
if (this.browserPending.has(id)) {
|
|
@@ -2346,11 +2388,11 @@ var DaemonCdpManager = class {
|
|
|
2346
2388
|
}
|
|
2347
2389
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
2348
2390
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
2349
|
-
return new Promise((
|
|
2391
|
+
return new Promise((resolve8, reject) => {
|
|
2350
2392
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
2351
2393
|
if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
2352
2394
|
const id = this.msgId++;
|
|
2353
|
-
this.pending.set(id, { resolve:
|
|
2395
|
+
this.pending.set(id, { resolve: resolve8, reject });
|
|
2354
2396
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
2355
2397
|
setTimeout(() => {
|
|
2356
2398
|
if (this.pending.has(id)) {
|
|
@@ -2599,7 +2641,7 @@ var DaemonCdpManager = class {
|
|
|
2599
2641
|
const browserWs = this.browserWs;
|
|
2600
2642
|
let msgId = this.browserMsgId;
|
|
2601
2643
|
const sendWs = (method, params = {}, sessionId) => {
|
|
2602
|
-
return new Promise((
|
|
2644
|
+
return new Promise((resolve8, reject) => {
|
|
2603
2645
|
const mid = msgId++;
|
|
2604
2646
|
this.browserMsgId = msgId;
|
|
2605
2647
|
const handler = (raw) => {
|
|
@@ -2608,7 +2650,7 @@ var DaemonCdpManager = class {
|
|
|
2608
2650
|
if (msg.id === mid) {
|
|
2609
2651
|
browserWs.removeListener("message", handler);
|
|
2610
2652
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
2611
|
-
else
|
|
2653
|
+
else resolve8(msg.result);
|
|
2612
2654
|
}
|
|
2613
2655
|
} catch {
|
|
2614
2656
|
}
|
|
@@ -2790,14 +2832,14 @@ var DaemonCdpManager = class {
|
|
|
2790
2832
|
if (!ws || ws.readyState !== import_ws.default.OPEN) {
|
|
2791
2833
|
throw new Error("CDP not connected");
|
|
2792
2834
|
}
|
|
2793
|
-
return new Promise((
|
|
2835
|
+
return new Promise((resolve8, reject) => {
|
|
2794
2836
|
const id = getNextId();
|
|
2795
2837
|
pendingMap.set(id, {
|
|
2796
2838
|
resolve: (result) => {
|
|
2797
2839
|
if (result?.result?.subtype === "error") {
|
|
2798
2840
|
reject(new Error(result.result.description));
|
|
2799
2841
|
} else {
|
|
2800
|
-
|
|
2842
|
+
resolve8(result?.result?.value);
|
|
2801
2843
|
}
|
|
2802
2844
|
},
|
|
2803
2845
|
reject
|
|
@@ -2829,10 +2871,10 @@ var DaemonCdpManager = class {
|
|
|
2829
2871
|
throw new Error("CDP not connected");
|
|
2830
2872
|
}
|
|
2831
2873
|
const sendViaSession = (method, params = {}) => {
|
|
2832
|
-
return new Promise((
|
|
2874
|
+
return new Promise((resolve8, reject) => {
|
|
2833
2875
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
2834
2876
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
2835
|
-
pendingMap.set(id, { resolve:
|
|
2877
|
+
pendingMap.set(id, { resolve: resolve8, reject });
|
|
2836
2878
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
2837
2879
|
setTimeout(() => {
|
|
2838
2880
|
if (pendingMap.has(id)) {
|
|
@@ -6237,7 +6279,7 @@ var DaemonCommandHandler = class {
|
|
|
6237
6279
|
try {
|
|
6238
6280
|
const http3 = await import("http");
|
|
6239
6281
|
const postData = JSON.stringify(body);
|
|
6240
|
-
const result = await new Promise((
|
|
6282
|
+
const result = await new Promise((resolve8, reject) => {
|
|
6241
6283
|
const req = http3.request({
|
|
6242
6284
|
hostname: "127.0.0.1",
|
|
6243
6285
|
port: 19280,
|
|
@@ -6249,9 +6291,9 @@ var DaemonCommandHandler = class {
|
|
|
6249
6291
|
res.on("data", (chunk) => data += chunk);
|
|
6250
6292
|
res.on("end", () => {
|
|
6251
6293
|
try {
|
|
6252
|
-
|
|
6294
|
+
resolve8(JSON.parse(data));
|
|
6253
6295
|
} catch {
|
|
6254
|
-
|
|
6296
|
+
resolve8({ raw: data });
|
|
6255
6297
|
}
|
|
6256
6298
|
});
|
|
6257
6299
|
});
|
|
@@ -6269,15 +6311,15 @@ var DaemonCommandHandler = class {
|
|
|
6269
6311
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
6270
6312
|
try {
|
|
6271
6313
|
const http3 = await import("http");
|
|
6272
|
-
const result = await new Promise((
|
|
6314
|
+
const result = await new Promise((resolve8, reject) => {
|
|
6273
6315
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
6274
6316
|
let data = "";
|
|
6275
6317
|
res.on("data", (chunk) => data += chunk);
|
|
6276
6318
|
res.on("end", () => {
|
|
6277
6319
|
try {
|
|
6278
|
-
|
|
6320
|
+
resolve8(JSON.parse(data));
|
|
6279
6321
|
} catch {
|
|
6280
|
-
|
|
6322
|
+
resolve8({ raw: data });
|
|
6281
6323
|
}
|
|
6282
6324
|
});
|
|
6283
6325
|
}).on("error", reject);
|
|
@@ -6291,7 +6333,7 @@ var DaemonCommandHandler = class {
|
|
|
6291
6333
|
try {
|
|
6292
6334
|
const http3 = await import("http");
|
|
6293
6335
|
const postData = JSON.stringify(args || {});
|
|
6294
|
-
const result = await new Promise((
|
|
6336
|
+
const result = await new Promise((resolve8, reject) => {
|
|
6295
6337
|
const req = http3.request({
|
|
6296
6338
|
hostname: "127.0.0.1",
|
|
6297
6339
|
port: 19280,
|
|
@@ -6303,9 +6345,9 @@ var DaemonCommandHandler = class {
|
|
|
6303
6345
|
res.on("data", (chunk) => data += chunk);
|
|
6304
6346
|
res.on("end", () => {
|
|
6305
6347
|
try {
|
|
6306
|
-
|
|
6348
|
+
resolve8(JSON.parse(data));
|
|
6307
6349
|
} catch {
|
|
6308
|
-
|
|
6350
|
+
resolve8({ raw: data });
|
|
6309
6351
|
}
|
|
6310
6352
|
});
|
|
6311
6353
|
});
|
|
@@ -6330,10 +6372,10 @@ var path7 = __toESM(require("path"));
|
|
|
6330
6372
|
var fs5 = __toESM(require("fs"));
|
|
6331
6373
|
var path6 = __toESM(require("path"));
|
|
6332
6374
|
var os7 = __toESM(require("os"));
|
|
6375
|
+
var chokidar = __toESM(require("chokidar"));
|
|
6333
6376
|
init_logger();
|
|
6334
6377
|
var ProviderLoader = class _ProviderLoader {
|
|
6335
6378
|
providers = /* @__PURE__ */ new Map();
|
|
6336
|
-
builtinDirs;
|
|
6337
6379
|
userDir;
|
|
6338
6380
|
upstreamDir;
|
|
6339
6381
|
disableUpstream;
|
|
@@ -6348,36 +6390,31 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6348
6390
|
static GITHUB_TARBALL_URL = "https://github.com/vilmire/adhdev-providers/archive/refs/heads/main.tar.gz";
|
|
6349
6391
|
static META_FILE = ".meta.json";
|
|
6350
6392
|
constructor(options) {
|
|
6351
|
-
|
|
6352
|
-
|
|
6393
|
+
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
6394
|
+
const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
|
|
6395
|
+
if (options?.userDir) {
|
|
6396
|
+
this.userDir = options.userDir;
|
|
6397
|
+
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
6353
6398
|
} else {
|
|
6354
|
-
|
|
6399
|
+
const localRepoPath = path6.resolve(__dirname, "../../../../../adhdev-providers");
|
|
6400
|
+
if (fs5.existsSync(localRepoPath)) {
|
|
6401
|
+
this.userDir = localRepoPath;
|
|
6402
|
+
this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
|
|
6403
|
+
} else {
|
|
6404
|
+
this.userDir = defaultProvidersDir;
|
|
6405
|
+
this.log(`Using default user providers directory: ${this.userDir}`);
|
|
6406
|
+
}
|
|
6355
6407
|
}
|
|
6356
|
-
const defaultProvidersDir = path6.join(os7.homedir(), ".adhdev", "providers");
|
|
6357
|
-
this.userDir = options?.userDir || defaultProvidersDir;
|
|
6358
6408
|
this.upstreamDir = path6.join(defaultProvidersDir, ".upstream");
|
|
6359
6409
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
6360
|
-
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
6361
6410
|
}
|
|
6362
6411
|
log(msg) {
|
|
6363
6412
|
this.logFn(`[ProviderLoader] ${msg}`);
|
|
6364
6413
|
}
|
|
6365
6414
|
// ─── Public API ────────────────────────────────
|
|
6366
6415
|
/**
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
getBuiltinDirs() {
|
|
6370
|
-
return [...this.builtinDirs];
|
|
6371
|
-
}
|
|
6372
|
-
/**
|
|
6373
|
-
* Primary builtin root used for local scaffolding/reference flows.
|
|
6374
|
-
*/
|
|
6375
|
-
getPrimaryBuiltinDir() {
|
|
6376
|
-
return this.builtinDirs[0];
|
|
6377
|
-
}
|
|
6378
|
-
/**
|
|
6379
|
-
* User override root (~/.adhdev/providers by default).
|
|
6380
|
-
*/
|
|
6416
|
+
* User override root (~/.adhdev/providers by default).
|
|
6417
|
+
*/
|
|
6381
6418
|
getUserDir() {
|
|
6382
6419
|
return this.userDir;
|
|
6383
6420
|
}
|
|
@@ -6388,11 +6425,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6388
6425
|
return this.upstreamDir;
|
|
6389
6426
|
}
|
|
6390
6427
|
/**
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6428
|
+
* Provider search order for on-disk lookups.
|
|
6429
|
+
* Highest-priority editable overrides come first.
|
|
6430
|
+
*/
|
|
6394
6431
|
getProviderRoots() {
|
|
6395
|
-
return [this.userDir, this.upstreamDir
|
|
6432
|
+
return [this.userDir, this.upstreamDir];
|
|
6396
6433
|
}
|
|
6397
6434
|
/**
|
|
6398
6435
|
* Canonical provider directory shape for a given root.
|
|
@@ -6413,16 +6450,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6413
6450
|
return this.getProviderDir(this.upstreamDir, category, type);
|
|
6414
6451
|
}
|
|
6415
6452
|
/**
|
|
6416
|
-
*
|
|
6453
|
+
* Find the on-disk directory for a provider by type.
|
|
6454
|
+
* Search order: user override → upstream.
|
|
6417
6455
|
*/
|
|
6418
|
-
getBuiltinProviderDir(category, type) {
|
|
6419
|
-
const builtinRoot = this.getPrimaryBuiltinDir();
|
|
6420
|
-
return builtinRoot ? this.getProviderDir(builtinRoot, category, type) : "";
|
|
6421
|
-
}
|
|
6422
|
-
/**
|
|
6423
|
-
* Find the on-disk directory for a provider by type.
|
|
6424
|
-
* Search order: user override → upstream → builtin fallback.
|
|
6425
|
-
*/
|
|
6426
6456
|
findProviderDir(type) {
|
|
6427
6457
|
return this.findProviderDirInternal(type);
|
|
6428
6458
|
}
|
|
@@ -6787,13 +6817,12 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6787
6817
|
}
|
|
6788
6818
|
}
|
|
6789
6819
|
const result = this.buildScriptWrappersFromDir(dir);
|
|
6790
|
-
this.log(` [loadScriptsFromDir] ${type}: built wrappers from ${dir} (${Object.keys(result).length} scripts)`);
|
|
6791
6820
|
this.scriptsCache.set(dir, result);
|
|
6792
6821
|
return result;
|
|
6793
6822
|
}
|
|
6794
6823
|
/**
|
|
6795
|
-
|
|
6796
|
-
|
|
6824
|
+
* Hot-reload: start watching for file changes
|
|
6825
|
+
*/
|
|
6797
6826
|
watch() {
|
|
6798
6827
|
this.stopWatch();
|
|
6799
6828
|
const watchDir = (dir) => {
|
|
@@ -6805,18 +6834,27 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6805
6834
|
}
|
|
6806
6835
|
}
|
|
6807
6836
|
try {
|
|
6808
|
-
const watcher =
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6837
|
+
const watcher = chokidar.watch(dir, {
|
|
6838
|
+
ignored: /(^|[\/\\])\.\./,
|
|
6839
|
+
// ignore dotfiles
|
|
6840
|
+
persistent: true,
|
|
6841
|
+
ignoreInitial: true,
|
|
6842
|
+
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
6813
6843
|
});
|
|
6844
|
+
const handleChange = (filePath) => {
|
|
6845
|
+
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
6846
|
+
this.log(`File changed: ${path6.basename(filePath)}, reloading...`);
|
|
6847
|
+
this.reload();
|
|
6848
|
+
}
|
|
6849
|
+
};
|
|
6850
|
+
watcher.on("add", handleChange).on("change", handleChange).on("unlink", handleChange);
|
|
6851
|
+
watcher.on("error", (err) => this.log(`Watch error: ${err.message}`));
|
|
6814
6852
|
this.watchers.push(watcher);
|
|
6853
|
+
this.log(`Hot-reload watcher active: ${dir}`);
|
|
6815
6854
|
} catch (e) {
|
|
6816
6855
|
this.log(`Watch failed for ${dir}: ${e.message}`);
|
|
6817
6856
|
}
|
|
6818
6857
|
};
|
|
6819
|
-
this.builtinDirs.forEach((dir) => watchDir(dir));
|
|
6820
6858
|
watchDir(this.userDir);
|
|
6821
6859
|
}
|
|
6822
6860
|
/**
|
|
@@ -6877,7 +6915,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6877
6915
|
return { updated: false };
|
|
6878
6916
|
}
|
|
6879
6917
|
try {
|
|
6880
|
-
const etag = await new Promise((
|
|
6918
|
+
const etag = await new Promise((resolve8, reject) => {
|
|
6881
6919
|
const options = {
|
|
6882
6920
|
method: "HEAD",
|
|
6883
6921
|
hostname: "github.com",
|
|
@@ -6895,7 +6933,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6895
6933
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
6896
6934
|
timeout: 1e4
|
|
6897
6935
|
}, (res2) => {
|
|
6898
|
-
|
|
6936
|
+
resolve8(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
6899
6937
|
});
|
|
6900
6938
|
req2.on("error", reject);
|
|
6901
6939
|
req2.on("timeout", () => {
|
|
@@ -6904,7 +6942,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6904
6942
|
});
|
|
6905
6943
|
req2.end();
|
|
6906
6944
|
} else {
|
|
6907
|
-
|
|
6945
|
+
resolve8(res.headers.etag || res.headers["last-modified"] || "");
|
|
6908
6946
|
}
|
|
6909
6947
|
});
|
|
6910
6948
|
req.on("error", reject);
|
|
@@ -6968,7 +7006,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6968
7006
|
downloadFile(url, destPath) {
|
|
6969
7007
|
const https = require("https");
|
|
6970
7008
|
const http3 = require("http");
|
|
6971
|
-
return new Promise((
|
|
7009
|
+
return new Promise((resolve8, reject) => {
|
|
6972
7010
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
6973
7011
|
if (redirectCount > 5) {
|
|
6974
7012
|
reject(new Error("Too many redirects"));
|
|
@@ -6988,7 +7026,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6988
7026
|
res.pipe(ws);
|
|
6989
7027
|
ws.on("finish", () => {
|
|
6990
7028
|
ws.close();
|
|
6991
|
-
|
|
7029
|
+
resolve8();
|
|
6992
7030
|
});
|
|
6993
7031
|
ws.on("error", reject);
|
|
6994
7032
|
});
|
|
@@ -7260,8 +7298,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
7260
7298
|
const existed = this.providers.has(mod.type);
|
|
7261
7299
|
this.providers.set(mod.type, mod);
|
|
7262
7300
|
count++;
|
|
7263
|
-
const source = d.startsWith(this.userDir) && !d.includes(".upstream") ? "user" :
|
|
7264
|
-
const overrideWarning = existed && source === "user" ? " \u26A0 OVERRIDES
|
|
7301
|
+
const source = d.startsWith(this.userDir) && !d.includes(".upstream") ? "user" : "upstream";
|
|
7302
|
+
const overrideWarning = existed && source === "user" ? " \u26A0 OVERRIDES upstream" : "";
|
|
7265
7303
|
this.log(` ${existed ? "\u{1F504}" : "\u2705"} ${mod.type} (${mod.category}) \u2014 ${mod.name} [${source}]${overrideWarning}`);
|
|
7266
7304
|
}
|
|
7267
7305
|
} catch (e) {
|
|
@@ -7353,17 +7391,17 @@ async function findFreePort(ports) {
|
|
|
7353
7391
|
throw new Error("No free port found");
|
|
7354
7392
|
}
|
|
7355
7393
|
function checkPortFree(port) {
|
|
7356
|
-
return new Promise((
|
|
7394
|
+
return new Promise((resolve8) => {
|
|
7357
7395
|
const server = net.createServer();
|
|
7358
7396
|
server.unref();
|
|
7359
|
-
server.on("error", () =>
|
|
7397
|
+
server.on("error", () => resolve8(false));
|
|
7360
7398
|
server.listen(port, "127.0.0.1", () => {
|
|
7361
|
-
server.close(() =>
|
|
7399
|
+
server.close(() => resolve8(true));
|
|
7362
7400
|
});
|
|
7363
7401
|
});
|
|
7364
7402
|
}
|
|
7365
7403
|
async function isCdpActive(port) {
|
|
7366
|
-
return new Promise((
|
|
7404
|
+
return new Promise((resolve8) => {
|
|
7367
7405
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
7368
7406
|
timeout: 2e3
|
|
7369
7407
|
}, (res) => {
|
|
@@ -7372,16 +7410,16 @@ async function isCdpActive(port) {
|
|
|
7372
7410
|
res.on("end", () => {
|
|
7373
7411
|
try {
|
|
7374
7412
|
const info = JSON.parse(data);
|
|
7375
|
-
|
|
7413
|
+
resolve8(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
7376
7414
|
} catch {
|
|
7377
|
-
|
|
7415
|
+
resolve8(false);
|
|
7378
7416
|
}
|
|
7379
7417
|
});
|
|
7380
7418
|
});
|
|
7381
|
-
req.on("error", () =>
|
|
7419
|
+
req.on("error", () => resolve8(false));
|
|
7382
7420
|
req.on("timeout", () => {
|
|
7383
7421
|
req.destroy();
|
|
7384
|
-
|
|
7422
|
+
resolve8(false);
|
|
7385
7423
|
});
|
|
7386
7424
|
});
|
|
7387
7425
|
}
|
|
@@ -9042,13 +9080,13 @@ var AcpProviderInstance = class {
|
|
|
9042
9080
|
}
|
|
9043
9081
|
this.currentStatus = "waiting_approval";
|
|
9044
9082
|
this.detectStatusTransition();
|
|
9045
|
-
const approved = await new Promise((
|
|
9046
|
-
this.permissionResolvers.push(
|
|
9083
|
+
const approved = await new Promise((resolve8) => {
|
|
9084
|
+
this.permissionResolvers.push(resolve8);
|
|
9047
9085
|
setTimeout(() => {
|
|
9048
|
-
const idx = this.permissionResolvers.indexOf(
|
|
9086
|
+
const idx = this.permissionResolvers.indexOf(resolve8);
|
|
9049
9087
|
if (idx >= 0) {
|
|
9050
9088
|
this.permissionResolvers.splice(idx, 1);
|
|
9051
|
-
|
|
9089
|
+
resolve8(false);
|
|
9052
9090
|
}
|
|
9053
9091
|
}, 3e5);
|
|
9054
9092
|
});
|
|
@@ -11152,15 +11190,15 @@ var DevServer = class _DevServer {
|
|
|
11152
11190
|
this.json(res, 500, { error: e.message });
|
|
11153
11191
|
}
|
|
11154
11192
|
});
|
|
11155
|
-
return new Promise((
|
|
11193
|
+
return new Promise((resolve8, reject) => {
|
|
11156
11194
|
this.server.listen(port, "127.0.0.1", () => {
|
|
11157
11195
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
11158
|
-
|
|
11196
|
+
resolve8();
|
|
11159
11197
|
});
|
|
11160
11198
|
this.server.on("error", (e) => {
|
|
11161
11199
|
if (e.code === "EADDRINUSE") {
|
|
11162
11200
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
11163
|
-
|
|
11201
|
+
resolve8();
|
|
11164
11202
|
} else {
|
|
11165
11203
|
reject(e);
|
|
11166
11204
|
}
|
|
@@ -11243,20 +11281,20 @@ var DevServer = class _DevServer {
|
|
|
11243
11281
|
child.stderr?.on("data", (d) => {
|
|
11244
11282
|
stderr += d.toString().slice(0, 2e3);
|
|
11245
11283
|
});
|
|
11246
|
-
await new Promise((
|
|
11284
|
+
await new Promise((resolve8) => {
|
|
11247
11285
|
const timer = setTimeout(() => {
|
|
11248
11286
|
child.kill();
|
|
11249
|
-
|
|
11287
|
+
resolve8();
|
|
11250
11288
|
}, 3e3);
|
|
11251
11289
|
child.on("exit", () => {
|
|
11252
11290
|
clearTimeout(timer);
|
|
11253
|
-
|
|
11291
|
+
resolve8();
|
|
11254
11292
|
});
|
|
11255
11293
|
child.stdout?.once("data", () => {
|
|
11256
11294
|
setTimeout(() => {
|
|
11257
11295
|
child.kill();
|
|
11258
11296
|
clearTimeout(timer);
|
|
11259
|
-
|
|
11297
|
+
resolve8();
|
|
11260
11298
|
}, 500);
|
|
11261
11299
|
});
|
|
11262
11300
|
});
|
|
@@ -12000,14 +12038,14 @@ var DevServer = class _DevServer {
|
|
|
12000
12038
|
child.stderr?.on("data", (d) => {
|
|
12001
12039
|
stderr += d.toString();
|
|
12002
12040
|
});
|
|
12003
|
-
await new Promise((
|
|
12041
|
+
await new Promise((resolve8) => {
|
|
12004
12042
|
const timer = setTimeout(() => {
|
|
12005
12043
|
child.kill();
|
|
12006
|
-
|
|
12044
|
+
resolve8();
|
|
12007
12045
|
}, timeout);
|
|
12008
12046
|
child.on("exit", () => {
|
|
12009
12047
|
clearTimeout(timer);
|
|
12010
|
-
|
|
12048
|
+
resolve8();
|
|
12011
12049
|
});
|
|
12012
12050
|
});
|
|
12013
12051
|
const elapsed = Date.now() - start;
|
|
@@ -12851,25 +12889,63 @@ var DevServer = class _DevServer {
|
|
|
12851
12889
|
const ref = this.providerLoader.resolve(desired) || this.providerLoader.getMeta(desired);
|
|
12852
12890
|
if (ref?.category === category) return desired;
|
|
12853
12891
|
const all = this.providerLoader.getAll();
|
|
12854
|
-
const fallback = all.
|
|
12892
|
+
const fallback = all.filter((p) => p.category === category && p.type !== targetType).sort((a, b) => String(a.type || "").localeCompare(String(b.type || ""), void 0, { numeric: true, sensitivity: "base" }))[0];
|
|
12855
12893
|
return fallback?.type || null;
|
|
12856
12894
|
}
|
|
12857
|
-
|
|
12858
|
-
if (!
|
|
12859
|
-
const refDir = this.providerLoader.getUpstreamProviderDir(category, referenceType);
|
|
12860
|
-
if (!fs9.existsSync(refDir)) return {};
|
|
12861
|
-
const referenceScripts = {};
|
|
12862
|
-
const scriptsDir = path12.join(refDir, "scripts");
|
|
12863
|
-
if (!fs9.existsSync(scriptsDir)) return referenceScripts;
|
|
12895
|
+
getLatestScriptVersionDir(scriptsDir) {
|
|
12896
|
+
if (!fs9.existsSync(scriptsDir)) return null;
|
|
12864
12897
|
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
12865
12898
|
try {
|
|
12866
12899
|
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
12867
12900
|
} catch {
|
|
12868
12901
|
return false;
|
|
12869
12902
|
}
|
|
12870
|
-
}).sort().
|
|
12871
|
-
if (versions.length === 0) return
|
|
12872
|
-
|
|
12903
|
+
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
12904
|
+
if (versions.length === 0) return null;
|
|
12905
|
+
return path12.join(scriptsDir, versions[0]);
|
|
12906
|
+
}
|
|
12907
|
+
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
12908
|
+
const canonicalUserDir = path12.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
12909
|
+
const desiredDir = requestedDir ? path12.resolve(requestedDir) : canonicalUserDir;
|
|
12910
|
+
if (desiredDir !== canonicalUserDir) {
|
|
12911
|
+
return null;
|
|
12912
|
+
}
|
|
12913
|
+
const userRoot = path12.resolve(this.providerLoader.getUserDir());
|
|
12914
|
+
if (desiredDir !== userRoot && !desiredDir.startsWith(`${userRoot}${path12.sep}`)) {
|
|
12915
|
+
return null;
|
|
12916
|
+
}
|
|
12917
|
+
const sourceDir = this.findProviderDir(type);
|
|
12918
|
+
if (!sourceDir) {
|
|
12919
|
+
return null;
|
|
12920
|
+
}
|
|
12921
|
+
if (!fs9.existsSync(desiredDir)) {
|
|
12922
|
+
fs9.mkdirSync(path12.dirname(desiredDir), { recursive: true });
|
|
12923
|
+
fs9.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
12924
|
+
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
12925
|
+
}
|
|
12926
|
+
const providerJson = path12.join(desiredDir, "provider.json");
|
|
12927
|
+
if (!fs9.existsSync(providerJson)) {
|
|
12928
|
+
return null;
|
|
12929
|
+
}
|
|
12930
|
+
try {
|
|
12931
|
+
const providerData = JSON.parse(fs9.readFileSync(providerJson, "utf-8"));
|
|
12932
|
+
if (providerData.disableUpstream !== true) {
|
|
12933
|
+
providerData.disableUpstream = true;
|
|
12934
|
+
fs9.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
12935
|
+
}
|
|
12936
|
+
} catch {
|
|
12937
|
+
return null;
|
|
12938
|
+
}
|
|
12939
|
+
return desiredDir;
|
|
12940
|
+
}
|
|
12941
|
+
loadAutoImplReferenceScripts(referenceType) {
|
|
12942
|
+
if (!referenceType) return {};
|
|
12943
|
+
const refDir = this.findProviderDir(referenceType);
|
|
12944
|
+
if (!refDir || !fs9.existsSync(refDir)) return {};
|
|
12945
|
+
const referenceScripts = {};
|
|
12946
|
+
const scriptsDir = path12.join(refDir, "scripts");
|
|
12947
|
+
const latestDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
12948
|
+
if (!latestDir) return referenceScripts;
|
|
12873
12949
|
for (const file of fs9.readdirSync(latestDir)) {
|
|
12874
12950
|
if (!file.endsWith(".js")) continue;
|
|
12875
12951
|
try {
|
|
@@ -12881,7 +12957,7 @@ var DevServer = class _DevServer {
|
|
|
12881
12957
|
}
|
|
12882
12958
|
async handleAutoImplement(type, req, res) {
|
|
12883
12959
|
const body = await this.readBody(req);
|
|
12884
|
-
const { agent = "claude-cli", functions, reference
|
|
12960
|
+
const { agent = "claude-cli", functions, reference, model, comment, providerDir: requestedProviderDir } = body;
|
|
12885
12961
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
12886
12962
|
this.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
12887
12963
|
return;
|
|
@@ -12895,9 +12971,11 @@ var DevServer = class _DevServer {
|
|
|
12895
12971
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
12896
12972
|
return;
|
|
12897
12973
|
}
|
|
12898
|
-
const providerDir = this.
|
|
12974
|
+
const providerDir = this.resolveAutoImplWritableProviderDir(provider.category, type, requestedProviderDir);
|
|
12899
12975
|
if (!providerDir) {
|
|
12900
|
-
this.json(res,
|
|
12976
|
+
this.json(res, 409, {
|
|
12977
|
+
error: `Auto-implement only writes to the canonical user provider directory for '${type}'.`
|
|
12978
|
+
});
|
|
12901
12979
|
return;
|
|
12902
12980
|
}
|
|
12903
12981
|
try {
|
|
@@ -12919,7 +12997,7 @@ var DevServer = class _DevServer {
|
|
|
12919
12997
|
message: `Loading reference script (${resolvedReference || "none"})...`
|
|
12920
12998
|
}
|
|
12921
12999
|
});
|
|
12922
|
-
const referenceScripts = this.loadAutoImplReferenceScripts(
|
|
13000
|
+
const referenceScripts = this.loadAutoImplReferenceScripts(resolvedReference);
|
|
12923
13001
|
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
12924
13002
|
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
12925
13003
|
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
@@ -13275,29 +13353,20 @@ var DevServer = class _DevServer {
|
|
|
13275
13353
|
lines.push("These are the files you need to EDIT. They contain TODO stubs \u2014 replace them with working implementations.");
|
|
13276
13354
|
lines.push("");
|
|
13277
13355
|
const scriptsDir = path12.join(providerDir, "scripts");
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
try {
|
|
13293
|
-
const content = fs9.readFileSync(path12.join(vDir, file), "utf-8");
|
|
13294
|
-
lines.push(`### \`${file}\``);
|
|
13295
|
-
lines.push("```javascript");
|
|
13296
|
-
lines.push(content);
|
|
13297
|
-
lines.push("```");
|
|
13298
|
-
lines.push("");
|
|
13299
|
-
} catch {
|
|
13300
|
-
}
|
|
13356
|
+
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
13357
|
+
if (latestScriptsDir) {
|
|
13358
|
+
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
13359
|
+
lines.push("");
|
|
13360
|
+
for (const file of fs9.readdirSync(latestScriptsDir)) {
|
|
13361
|
+
if (file.endsWith(".js")) {
|
|
13362
|
+
try {
|
|
13363
|
+
const content = fs9.readFileSync(path12.join(latestScriptsDir, file), "utf-8");
|
|
13364
|
+
lines.push(`### \`${file}\``);
|
|
13365
|
+
lines.push("```javascript");
|
|
13366
|
+
lines.push(content);
|
|
13367
|
+
lines.push("```");
|
|
13368
|
+
lines.push("");
|
|
13369
|
+
} catch {
|
|
13301
13370
|
}
|
|
13302
13371
|
}
|
|
13303
13372
|
}
|
|
@@ -13378,7 +13447,7 @@ var DevServer = class _DevServer {
|
|
|
13378
13447
|
lines.push("## Rules");
|
|
13379
13448
|
lines.push("1. **Scripts WITHOUT params** \u2192 IIFE: `(() => { ... })()`");
|
|
13380
13449
|
lines.push("2. **Scripts WITH params** \u2192 arrow: `(params) => { ... }` \u2014 router calls `(${script})(${JSON.stringify(params)})`");
|
|
13381
|
-
lines.push("3.
|
|
13450
|
+
lines.push("3. If live DOM analysis is included above, use it. Otherwise, discover selectors yourself via CDP before coding.");
|
|
13382
13451
|
lines.push("4. Always wrap in try-catch, return `JSON.stringify(result)`");
|
|
13383
13452
|
lines.push("5. Do NOT modify `scripts.js` router \u2014 only edit individual `*.js` files");
|
|
13384
13453
|
lines.push("6. All scripts run in the browser (CDP evaluate) \u2014 use DOM APIs only");
|
|
@@ -13427,8 +13496,12 @@ var DevServer = class _DevServer {
|
|
|
13427
13496
|
lines.push(" - `listSessions`: If sessions are unmounted when the panel is closed, try to explicitly interact with the UI to open the history/sessions view (e.g., clicking a history icon usually found near the chat header) BEFORE scraping.");
|
|
13428
13497
|
lines.push(" - `switchSession`: Prove your switch was successful by subsequently calling `readChat` and explicitly checking that the chat context has actually changed.");
|
|
13429
13498
|
lines.push("");
|
|
13430
|
-
lines.push("##
|
|
13431
|
-
|
|
13499
|
+
lines.push("## DOM Exploration");
|
|
13500
|
+
if (domContext) {
|
|
13501
|
+
lines.push("A lightweight DOM snapshot is included above, but you MUST still verify selectors yourself before finalizing the scripts.");
|
|
13502
|
+
} else {
|
|
13503
|
+
lines.push("No DOM snapshot is included here. You MUST use your command-line tools to discover the IDE structure dynamically.");
|
|
13504
|
+
}
|
|
13432
13505
|
lines.push("");
|
|
13433
13506
|
lines.push("### 1. Evaluate JS to explore IDE DOM");
|
|
13434
13507
|
lines.push("Use cURL to run JavaScript inside the IDE:");
|
|
@@ -13515,29 +13588,20 @@ var DevServer = class _DevServer {
|
|
|
13515
13588
|
lines.push("These are the files you need to edit. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
13516
13589
|
lines.push("");
|
|
13517
13590
|
const scriptsDir = path12.join(providerDir, "scripts");
|
|
13518
|
-
|
|
13519
|
-
|
|
13591
|
+
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
13592
|
+
if (latestScriptsDir) {
|
|
13593
|
+
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
13594
|
+
lines.push("");
|
|
13595
|
+
for (const file of fs9.readdirSync(latestScriptsDir)) {
|
|
13596
|
+
if (!file.endsWith(".js")) continue;
|
|
13520
13597
|
try {
|
|
13521
|
-
|
|
13598
|
+
const content = fs9.readFileSync(path12.join(latestScriptsDir, file), "utf-8");
|
|
13599
|
+
lines.push(`### \`${file}\``);
|
|
13600
|
+
lines.push("```javascript");
|
|
13601
|
+
lines.push(content);
|
|
13602
|
+
lines.push("```");
|
|
13603
|
+
lines.push("");
|
|
13522
13604
|
} catch {
|
|
13523
|
-
return false;
|
|
13524
|
-
}
|
|
13525
|
-
}).sort().reverse();
|
|
13526
|
-
if (versions.length > 0) {
|
|
13527
|
-
const vDir = path12.join(scriptsDir, versions[0]);
|
|
13528
|
-
lines.push(`Scripts version directory: \`${vDir}\``);
|
|
13529
|
-
lines.push("");
|
|
13530
|
-
for (const file of fs9.readdirSync(vDir)) {
|
|
13531
|
-
if (!file.endsWith(".js")) continue;
|
|
13532
|
-
try {
|
|
13533
|
-
const content = fs9.readFileSync(path12.join(vDir, file), "utf-8");
|
|
13534
|
-
lines.push(`### \`${file}\``);
|
|
13535
|
-
lines.push("```javascript");
|
|
13536
|
-
lines.push(content);
|
|
13537
|
-
lines.push("```");
|
|
13538
|
-
lines.push("");
|
|
13539
|
-
} catch {
|
|
13540
|
-
}
|
|
13541
13605
|
}
|
|
13542
13606
|
}
|
|
13543
13607
|
}
|
|
@@ -13751,14 +13815,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
13751
13815
|
res.end(JSON.stringify(data, null, 2));
|
|
13752
13816
|
}
|
|
13753
13817
|
async readBody(req) {
|
|
13754
|
-
return new Promise((
|
|
13818
|
+
return new Promise((resolve8) => {
|
|
13755
13819
|
let body = "";
|
|
13756
13820
|
req.on("data", (chunk) => body += chunk);
|
|
13757
13821
|
req.on("end", () => {
|
|
13758
13822
|
try {
|
|
13759
|
-
|
|
13823
|
+
resolve8(JSON.parse(body));
|
|
13760
13824
|
} catch {
|
|
13761
|
-
|
|
13825
|
+
resolve8({});
|
|
13762
13826
|
}
|
|
13763
13827
|
});
|
|
13764
13828
|
});
|
|
@@ -14138,10 +14202,10 @@ async function installExtension(ide, extension) {
|
|
|
14138
14202
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
14139
14203
|
const fs10 = await import("fs");
|
|
14140
14204
|
fs10.writeFileSync(vsixPath, buffer);
|
|
14141
|
-
return new Promise((
|
|
14205
|
+
return new Promise((resolve8) => {
|
|
14142
14206
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
14143
14207
|
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
14144
|
-
|
|
14208
|
+
resolve8({
|
|
14145
14209
|
extensionId: extension.id,
|
|
14146
14210
|
marketplaceId: extension.marketplaceId,
|
|
14147
14211
|
success: !error,
|
|
@@ -14154,11 +14218,11 @@ async function installExtension(ide, extension) {
|
|
|
14154
14218
|
} catch (e) {
|
|
14155
14219
|
}
|
|
14156
14220
|
}
|
|
14157
|
-
return new Promise((
|
|
14221
|
+
return new Promise((resolve8) => {
|
|
14158
14222
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
14159
14223
|
(0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
14160
14224
|
if (error) {
|
|
14161
|
-
|
|
14225
|
+
resolve8({
|
|
14162
14226
|
extensionId: extension.id,
|
|
14163
14227
|
marketplaceId: extension.marketplaceId,
|
|
14164
14228
|
success: false,
|
|
@@ -14166,7 +14230,7 @@ async function installExtension(ide, extension) {
|
|
|
14166
14230
|
error: stderr || error.message
|
|
14167
14231
|
});
|
|
14168
14232
|
} else {
|
|
14169
|
-
|
|
14233
|
+
resolve8({
|
|
14170
14234
|
extensionId: extension.id,
|
|
14171
14235
|
marketplaceId: extension.marketplaceId,
|
|
14172
14236
|
success: true,
|
|
@@ -14321,6 +14385,18 @@ async function initDaemonComponents(config) {
|
|
|
14321
14385
|
detectedIdes: detectedIdesRef
|
|
14322
14386
|
};
|
|
14323
14387
|
}
|
|
14388
|
+
async function startDaemonDevSupport(options) {
|
|
14389
|
+
const devServer = new DevServer({
|
|
14390
|
+
providerLoader: options.components.providerLoader,
|
|
14391
|
+
cdpManagers: options.components.cdpManagers,
|
|
14392
|
+
instanceManager: options.components.instanceManager,
|
|
14393
|
+
cliManager: options.components.cliManager,
|
|
14394
|
+
logFn: options.logFn
|
|
14395
|
+
});
|
|
14396
|
+
await devServer.start();
|
|
14397
|
+
options.components.providerLoader.watch();
|
|
14398
|
+
return devServer;
|
|
14399
|
+
}
|
|
14324
14400
|
async function shutdownDaemonComponents(components) {
|
|
14325
14401
|
const {
|
|
14326
14402
|
poller,
|
|
@@ -14421,6 +14497,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
14421
14497
|
setLogLevel,
|
|
14422
14498
|
setupIdeInstance,
|
|
14423
14499
|
shutdownDaemonComponents,
|
|
14500
|
+
startDaemonDevSupport,
|
|
14424
14501
|
updateConfig
|
|
14425
14502
|
});
|
|
14426
14503
|
//# sourceMappingURL=index.js.map
|