adhdev 0.6.57 → 0.6.59
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/index.js +381 -209
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +341 -169
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -536,15 +536,15 @@ var init_ide_detector = __esm({
|
|
|
536
536
|
|
|
537
537
|
// ../daemon-core/src/detection/cli-detector.ts
|
|
538
538
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
539
|
-
return new Promise((
|
|
539
|
+
return new Promise((resolve7) => {
|
|
540
540
|
const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
541
541
|
if (err || !stdout?.trim()) {
|
|
542
|
-
|
|
542
|
+
resolve7(null);
|
|
543
543
|
} else {
|
|
544
|
-
|
|
544
|
+
resolve7(stdout.trim());
|
|
545
545
|
}
|
|
546
546
|
});
|
|
547
|
-
child.on("error", () =>
|
|
547
|
+
child.on("error", () => resolve7(null));
|
|
548
548
|
});
|
|
549
549
|
}
|
|
550
550
|
async function detectCLIs(providerLoader) {
|
|
@@ -919,7 +919,7 @@ var init_manager = __esm({
|
|
|
919
919
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
920
920
|
*/
|
|
921
921
|
static listAllTargets(port) {
|
|
922
|
-
return new Promise((
|
|
922
|
+
return new Promise((resolve7) => {
|
|
923
923
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
924
924
|
let data = "";
|
|
925
925
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -935,16 +935,16 @@ var init_manager = __esm({
|
|
|
935
935
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
936
936
|
);
|
|
937
937
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
938
|
-
|
|
938
|
+
resolve7(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
939
939
|
} catch {
|
|
940
|
-
|
|
940
|
+
resolve7([]);
|
|
941
941
|
}
|
|
942
942
|
});
|
|
943
943
|
});
|
|
944
|
-
req.on("error", () =>
|
|
944
|
+
req.on("error", () => resolve7([]));
|
|
945
945
|
req.setTimeout(2e3, () => {
|
|
946
946
|
req.destroy();
|
|
947
|
-
|
|
947
|
+
resolve7([]);
|
|
948
948
|
});
|
|
949
949
|
});
|
|
950
950
|
}
|
|
@@ -984,7 +984,7 @@ var init_manager = __esm({
|
|
|
984
984
|
}
|
|
985
985
|
}
|
|
986
986
|
findTargetOnPort(port) {
|
|
987
|
-
return new Promise((
|
|
987
|
+
return new Promise((resolve7) => {
|
|
988
988
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
989
989
|
let data = "";
|
|
990
990
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -995,7 +995,7 @@ var init_manager = __esm({
|
|
|
995
995
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
996
996
|
);
|
|
997
997
|
if (pages.length === 0) {
|
|
998
|
-
|
|
998
|
+
resolve7(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
999
999
|
return;
|
|
1000
1000
|
}
|
|
1001
1001
|
const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -1005,24 +1005,24 @@ var init_manager = __esm({
|
|
|
1005
1005
|
const specific = list.find((t) => t.id === this._targetId);
|
|
1006
1006
|
if (specific) {
|
|
1007
1007
|
this._pageTitle = specific.title || "";
|
|
1008
|
-
|
|
1008
|
+
resolve7(specific);
|
|
1009
1009
|
} else {
|
|
1010
1010
|
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
1011
|
-
|
|
1011
|
+
resolve7(null);
|
|
1012
1012
|
}
|
|
1013
1013
|
return;
|
|
1014
1014
|
}
|
|
1015
1015
|
this._pageTitle = list[0]?.title || "";
|
|
1016
|
-
|
|
1016
|
+
resolve7(list[0]);
|
|
1017
1017
|
} catch {
|
|
1018
|
-
|
|
1018
|
+
resolve7(null);
|
|
1019
1019
|
}
|
|
1020
1020
|
});
|
|
1021
1021
|
});
|
|
1022
|
-
req.on("error", () =>
|
|
1022
|
+
req.on("error", () => resolve7(null));
|
|
1023
1023
|
req.setTimeout(2e3, () => {
|
|
1024
1024
|
req.destroy();
|
|
1025
|
-
|
|
1025
|
+
resolve7(null);
|
|
1026
1026
|
});
|
|
1027
1027
|
});
|
|
1028
1028
|
}
|
|
@@ -1033,7 +1033,7 @@ var init_manager = __esm({
|
|
|
1033
1033
|
this.extensionProviders = providers;
|
|
1034
1034
|
}
|
|
1035
1035
|
connectToTarget(wsUrl) {
|
|
1036
|
-
return new Promise((
|
|
1036
|
+
return new Promise((resolve7) => {
|
|
1037
1037
|
this.ws = new import_ws.default(wsUrl);
|
|
1038
1038
|
this.ws.on("open", async () => {
|
|
1039
1039
|
this._connected = true;
|
|
@@ -1043,17 +1043,17 @@ var init_manager = __esm({
|
|
|
1043
1043
|
}
|
|
1044
1044
|
this.connectBrowserWs().catch(() => {
|
|
1045
1045
|
});
|
|
1046
|
-
|
|
1046
|
+
resolve7(true);
|
|
1047
1047
|
});
|
|
1048
1048
|
this.ws.on("message", (data) => {
|
|
1049
1049
|
try {
|
|
1050
1050
|
const msg = JSON.parse(data.toString());
|
|
1051
1051
|
if (msg.id && this.pending.has(msg.id)) {
|
|
1052
|
-
const { resolve:
|
|
1052
|
+
const { resolve: resolve8, reject } = this.pending.get(msg.id);
|
|
1053
1053
|
this.pending.delete(msg.id);
|
|
1054
1054
|
this.failureCount = 0;
|
|
1055
1055
|
if (msg.error) reject(new Error(msg.error.message));
|
|
1056
|
-
else
|
|
1056
|
+
else resolve8(msg.result);
|
|
1057
1057
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
1058
1058
|
this.contexts.add(msg.params.context.id);
|
|
1059
1059
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -1076,7 +1076,7 @@ var init_manager = __esm({
|
|
|
1076
1076
|
this.ws.on("error", (err) => {
|
|
1077
1077
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
1078
1078
|
this._connected = false;
|
|
1079
|
-
|
|
1079
|
+
resolve7(false);
|
|
1080
1080
|
});
|
|
1081
1081
|
});
|
|
1082
1082
|
}
|
|
@@ -1090,7 +1090,7 @@ var init_manager = __esm({
|
|
|
1090
1090
|
return;
|
|
1091
1091
|
}
|
|
1092
1092
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
1093
|
-
await new Promise((
|
|
1093
|
+
await new Promise((resolve7, reject) => {
|
|
1094
1094
|
this.browserWs = new import_ws.default(browserWsUrl);
|
|
1095
1095
|
this.browserWs.on("open", async () => {
|
|
1096
1096
|
this._browserConnected = true;
|
|
@@ -1100,16 +1100,16 @@ var init_manager = __esm({
|
|
|
1100
1100
|
} catch (e) {
|
|
1101
1101
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
1102
1102
|
}
|
|
1103
|
-
|
|
1103
|
+
resolve7();
|
|
1104
1104
|
});
|
|
1105
1105
|
this.browserWs.on("message", (data) => {
|
|
1106
1106
|
try {
|
|
1107
1107
|
const msg = JSON.parse(data.toString());
|
|
1108
1108
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
1109
|
-
const { resolve:
|
|
1109
|
+
const { resolve: resolve8, reject: reject2 } = this.browserPending.get(msg.id);
|
|
1110
1110
|
this.browserPending.delete(msg.id);
|
|
1111
1111
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
1112
|
-
else
|
|
1112
|
+
else resolve8(msg.result);
|
|
1113
1113
|
}
|
|
1114
1114
|
} catch {
|
|
1115
1115
|
}
|
|
@@ -1129,31 +1129,31 @@ var init_manager = __esm({
|
|
|
1129
1129
|
}
|
|
1130
1130
|
}
|
|
1131
1131
|
getBrowserWsUrl() {
|
|
1132
|
-
return new Promise((
|
|
1132
|
+
return new Promise((resolve7) => {
|
|
1133
1133
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
1134
1134
|
let data = "";
|
|
1135
1135
|
res.on("data", (chunk) => data += chunk.toString());
|
|
1136
1136
|
res.on("end", () => {
|
|
1137
1137
|
try {
|
|
1138
1138
|
const info = JSON.parse(data);
|
|
1139
|
-
|
|
1139
|
+
resolve7(info.webSocketDebuggerUrl || null);
|
|
1140
1140
|
} catch {
|
|
1141
|
-
|
|
1141
|
+
resolve7(null);
|
|
1142
1142
|
}
|
|
1143
1143
|
});
|
|
1144
1144
|
});
|
|
1145
|
-
req.on("error", () =>
|
|
1145
|
+
req.on("error", () => resolve7(null));
|
|
1146
1146
|
req.setTimeout(3e3, () => {
|
|
1147
1147
|
req.destroy();
|
|
1148
|
-
|
|
1148
|
+
resolve7(null);
|
|
1149
1149
|
});
|
|
1150
1150
|
});
|
|
1151
1151
|
}
|
|
1152
1152
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
1153
|
-
return new Promise((
|
|
1153
|
+
return new Promise((resolve7, reject) => {
|
|
1154
1154
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
1155
1155
|
const id = this.browserMsgId++;
|
|
1156
|
-
this.browserPending.set(id, { resolve:
|
|
1156
|
+
this.browserPending.set(id, { resolve: resolve7, reject });
|
|
1157
1157
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
1158
1158
|
setTimeout(() => {
|
|
1159
1159
|
if (this.browserPending.has(id)) {
|
|
@@ -1193,11 +1193,11 @@ var init_manager = __esm({
|
|
|
1193
1193
|
}
|
|
1194
1194
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
1195
1195
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
1196
|
-
return new Promise((
|
|
1196
|
+
return new Promise((resolve7, reject) => {
|
|
1197
1197
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
1198
1198
|
if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
1199
1199
|
const id = this.msgId++;
|
|
1200
|
-
this.pending.set(id, { resolve:
|
|
1200
|
+
this.pending.set(id, { resolve: resolve7, reject });
|
|
1201
1201
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
1202
1202
|
setTimeout(() => {
|
|
1203
1203
|
if (this.pending.has(id)) {
|
|
@@ -1446,7 +1446,7 @@ var init_manager = __esm({
|
|
|
1446
1446
|
const browserWs = this.browserWs;
|
|
1447
1447
|
let msgId = this.browserMsgId;
|
|
1448
1448
|
const sendWs = (method, params = {}, sessionId) => {
|
|
1449
|
-
return new Promise((
|
|
1449
|
+
return new Promise((resolve7, reject) => {
|
|
1450
1450
|
const mid = msgId++;
|
|
1451
1451
|
this.browserMsgId = msgId;
|
|
1452
1452
|
const handler = (raw) => {
|
|
@@ -1455,7 +1455,7 @@ var init_manager = __esm({
|
|
|
1455
1455
|
if (msg.id === mid) {
|
|
1456
1456
|
browserWs.removeListener("message", handler);
|
|
1457
1457
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
1458
|
-
else
|
|
1458
|
+
else resolve7(msg.result);
|
|
1459
1459
|
}
|
|
1460
1460
|
} catch {
|
|
1461
1461
|
}
|
|
@@ -1637,14 +1637,14 @@ var init_manager = __esm({
|
|
|
1637
1637
|
if (!ws2 || ws2.readyState !== import_ws.default.OPEN) {
|
|
1638
1638
|
throw new Error("CDP not connected");
|
|
1639
1639
|
}
|
|
1640
|
-
return new Promise((
|
|
1640
|
+
return new Promise((resolve7, reject) => {
|
|
1641
1641
|
const id = getNextId();
|
|
1642
1642
|
pendingMap.set(id, {
|
|
1643
1643
|
resolve: (result) => {
|
|
1644
1644
|
if (result?.result?.subtype === "error") {
|
|
1645
1645
|
reject(new Error(result.result.description));
|
|
1646
1646
|
} else {
|
|
1647
|
-
|
|
1647
|
+
resolve7(result?.result?.value);
|
|
1648
1648
|
}
|
|
1649
1649
|
},
|
|
1650
1650
|
reject
|
|
@@ -1676,10 +1676,10 @@ var init_manager = __esm({
|
|
|
1676
1676
|
throw new Error("CDP not connected");
|
|
1677
1677
|
}
|
|
1678
1678
|
const sendViaSession = (method, params = {}) => {
|
|
1679
|
-
return new Promise((
|
|
1679
|
+
return new Promise((resolve7, reject) => {
|
|
1680
1680
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
1681
1681
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
1682
|
-
pendingMap.set(id, { resolve:
|
|
1682
|
+
pendingMap.set(id, { resolve: resolve7, reject });
|
|
1683
1683
|
ws2.send(JSON.stringify({ id, sessionId, method, params }));
|
|
1684
1684
|
setTimeout(() => {
|
|
1685
1685
|
if (pendingMap.has(id)) {
|
|
@@ -2379,6 +2379,8 @@ var init_chat_history = __esm({
|
|
|
2379
2379
|
lastSeenCounts = /* @__PURE__ */ new Map();
|
|
2380
2380
|
/** Last seen message hash per agent (deduplication) */
|
|
2381
2381
|
lastSeenHashes = /* @__PURE__ */ new Map();
|
|
2382
|
+
/** Last seen append-only terminal transcript per agent */
|
|
2383
|
+
lastSeenTerminal = /* @__PURE__ */ new Map();
|
|
2382
2384
|
rotated = false;
|
|
2383
2385
|
/**
|
|
2384
2386
|
* Append new messages to history
|
|
@@ -2436,10 +2438,51 @@ var init_chat_history = __esm({
|
|
|
2436
2438
|
} catch {
|
|
2437
2439
|
}
|
|
2438
2440
|
}
|
|
2441
|
+
appendTerminalHistory(agentType, terminalHistory, sessionTitle, instanceId) {
|
|
2442
|
+
const next = String(terminalHistory || "");
|
|
2443
|
+
if (!next.trim()) return;
|
|
2444
|
+
try {
|
|
2445
|
+
const dedupKey = instanceId ? `${agentType}:${instanceId}:terminal` : `${agentType}:terminal`;
|
|
2446
|
+
const prev = this.lastSeenTerminal.get(dedupKey) || "";
|
|
2447
|
+
if (prev === next) return;
|
|
2448
|
+
let delta = "";
|
|
2449
|
+
if (!prev) {
|
|
2450
|
+
delta = next;
|
|
2451
|
+
} else if (next.startsWith(prev)) {
|
|
2452
|
+
delta = next.slice(prev.length);
|
|
2453
|
+
} else if (prev.includes(next)) {
|
|
2454
|
+
this.lastSeenTerminal.set(dedupKey, next);
|
|
2455
|
+
return;
|
|
2456
|
+
} else {
|
|
2457
|
+
delta = `
|
|
2458
|
+
|
|
2459
|
+
[terminal snapshot reset ${(/* @__PURE__ */ new Date()).toISOString()} | ${sessionTitle || agentType}]
|
|
2460
|
+
${next}`;
|
|
2461
|
+
}
|
|
2462
|
+
if (!delta) {
|
|
2463
|
+
this.lastSeenTerminal.set(dedupKey, next);
|
|
2464
|
+
return;
|
|
2465
|
+
}
|
|
2466
|
+
const dir = path4.join(HISTORY_DIR, this.sanitize(agentType));
|
|
2467
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
2468
|
+
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2469
|
+
const filePrefix = instanceId ? `${this.sanitize(instanceId)}_` : "";
|
|
2470
|
+
const filePath = path4.join(dir, `${filePrefix}${date5}.terminal.log`);
|
|
2471
|
+
fs3.appendFileSync(filePath, delta, "utf-8");
|
|
2472
|
+
this.lastSeenTerminal.set(dedupKey, next);
|
|
2473
|
+
if (!this.rotated) {
|
|
2474
|
+
this.rotated = true;
|
|
2475
|
+
this.rotateOldFiles().catch(() => {
|
|
2476
|
+
});
|
|
2477
|
+
}
|
|
2478
|
+
} catch {
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2439
2481
|
/** Called when agent session is explicitly changed */
|
|
2440
2482
|
onSessionChange(agentType) {
|
|
2441
2483
|
this.lastSeenHashes.delete(agentType);
|
|
2442
2484
|
this.lastSeenCounts.delete(agentType);
|
|
2485
|
+
this.lastSeenTerminal.delete(`${agentType}:terminal`);
|
|
2443
2486
|
}
|
|
2444
2487
|
/** Delete history files older than 30 days */
|
|
2445
2488
|
async rotateOldFiles() {
|
|
@@ -2449,7 +2492,7 @@ var init_chat_history = __esm({
|
|
|
2449
2492
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
2450
2493
|
for (const dir of agentDirs) {
|
|
2451
2494
|
const dirPath = path4.join(HISTORY_DIR, dir.name);
|
|
2452
|
-
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
2495
|
+
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
2453
2496
|
for (const file2 of files) {
|
|
2454
2497
|
const filePath = path4.join(dirPath, file2);
|
|
2455
2498
|
const stat = fs3.statSync(filePath);
|
|
@@ -3196,7 +3239,13 @@ async function handleReadChat(h, args) {
|
|
|
3196
3239
|
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
3197
3240
|
const status = adapter.getStatus?.();
|
|
3198
3241
|
if (status) {
|
|
3199
|
-
return {
|
|
3242
|
+
return {
|
|
3243
|
+
success: true,
|
|
3244
|
+
messages: status.messages || [],
|
|
3245
|
+
status: status.status,
|
|
3246
|
+
activeModal: status.activeModal,
|
|
3247
|
+
terminalHistory: status.terminalHistory || ""
|
|
3248
|
+
};
|
|
3200
3249
|
}
|
|
3201
3250
|
}
|
|
3202
3251
|
return { success: false, error: `${provider.category} adapter not found` };
|
|
@@ -4966,7 +5015,7 @@ var init_handler = __esm({
|
|
|
4966
5015
|
try {
|
|
4967
5016
|
const http3 = await import("http");
|
|
4968
5017
|
const postData = JSON.stringify(body);
|
|
4969
|
-
const result = await new Promise((
|
|
5018
|
+
const result = await new Promise((resolve7, reject) => {
|
|
4970
5019
|
const req = http3.request({
|
|
4971
5020
|
hostname: "127.0.0.1",
|
|
4972
5021
|
port: 19280,
|
|
@@ -4978,9 +5027,9 @@ var init_handler = __esm({
|
|
|
4978
5027
|
res.on("data", (chunk) => data += chunk);
|
|
4979
5028
|
res.on("end", () => {
|
|
4980
5029
|
try {
|
|
4981
|
-
|
|
5030
|
+
resolve7(JSON.parse(data));
|
|
4982
5031
|
} catch {
|
|
4983
|
-
|
|
5032
|
+
resolve7({ raw: data });
|
|
4984
5033
|
}
|
|
4985
5034
|
});
|
|
4986
5035
|
});
|
|
@@ -4998,15 +5047,15 @@ var init_handler = __esm({
|
|
|
4998
5047
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
4999
5048
|
try {
|
|
5000
5049
|
const http3 = await import("http");
|
|
5001
|
-
const result = await new Promise((
|
|
5050
|
+
const result = await new Promise((resolve7, reject) => {
|
|
5002
5051
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
5003
5052
|
let data = "";
|
|
5004
5053
|
res.on("data", (chunk) => data += chunk);
|
|
5005
5054
|
res.on("end", () => {
|
|
5006
5055
|
try {
|
|
5007
|
-
|
|
5056
|
+
resolve7(JSON.parse(data));
|
|
5008
5057
|
} catch {
|
|
5009
|
-
|
|
5058
|
+
resolve7({ raw: data });
|
|
5010
5059
|
}
|
|
5011
5060
|
});
|
|
5012
5061
|
}).on("error", reject);
|
|
@@ -5020,7 +5069,7 @@ var init_handler = __esm({
|
|
|
5020
5069
|
try {
|
|
5021
5070
|
const http3 = await import("http");
|
|
5022
5071
|
const postData = JSON.stringify(args || {});
|
|
5023
|
-
const result = await new Promise((
|
|
5072
|
+
const result = await new Promise((resolve7, reject) => {
|
|
5024
5073
|
const req = http3.request({
|
|
5025
5074
|
hostname: "127.0.0.1",
|
|
5026
5075
|
port: 19280,
|
|
@@ -5032,9 +5081,9 @@ var init_handler = __esm({
|
|
|
5032
5081
|
res.on("data", (chunk) => data += chunk);
|
|
5033
5082
|
res.on("end", () => {
|
|
5034
5083
|
try {
|
|
5035
|
-
|
|
5084
|
+
resolve7(JSON.parse(data));
|
|
5036
5085
|
} catch {
|
|
5037
|
-
|
|
5086
|
+
resolve7({ raw: data });
|
|
5038
5087
|
}
|
|
5039
5088
|
});
|
|
5040
5089
|
});
|
|
@@ -5081,9 +5130,7 @@ var init_provider_loader = __esm({
|
|
|
5081
5130
|
if (options?.builtinDir) {
|
|
5082
5131
|
this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
|
|
5083
5132
|
} else {
|
|
5084
|
-
|
|
5085
|
-
const devDir = path6.resolve(__dirname, "../../providers/_builtin");
|
|
5086
|
-
this.builtinDirs = [fs5.existsSync(devDir) ? devDir : bundledDir];
|
|
5133
|
+
this.builtinDirs = [];
|
|
5087
5134
|
}
|
|
5088
5135
|
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
5089
5136
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
@@ -5605,7 +5652,7 @@ var init_provider_loader = __esm({
|
|
|
5605
5652
|
return { updated: false };
|
|
5606
5653
|
}
|
|
5607
5654
|
try {
|
|
5608
|
-
const etag = await new Promise((
|
|
5655
|
+
const etag = await new Promise((resolve7, reject) => {
|
|
5609
5656
|
const options = {
|
|
5610
5657
|
method: "HEAD",
|
|
5611
5658
|
hostname: "github.com",
|
|
@@ -5623,7 +5670,7 @@ var init_provider_loader = __esm({
|
|
|
5623
5670
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
5624
5671
|
timeout: 1e4
|
|
5625
5672
|
}, (res2) => {
|
|
5626
|
-
|
|
5673
|
+
resolve7(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
5627
5674
|
});
|
|
5628
5675
|
req2.on("error", reject);
|
|
5629
5676
|
req2.on("timeout", () => {
|
|
@@ -5632,7 +5679,7 @@ var init_provider_loader = __esm({
|
|
|
5632
5679
|
});
|
|
5633
5680
|
req2.end();
|
|
5634
5681
|
} else {
|
|
5635
|
-
|
|
5682
|
+
resolve7(res.headers.etag || res.headers["last-modified"] || "");
|
|
5636
5683
|
}
|
|
5637
5684
|
});
|
|
5638
5685
|
req.on("error", reject);
|
|
@@ -5696,7 +5743,7 @@ var init_provider_loader = __esm({
|
|
|
5696
5743
|
downloadFile(url2, destPath) {
|
|
5697
5744
|
const https = require("https");
|
|
5698
5745
|
const http3 = require("http");
|
|
5699
|
-
return new Promise((
|
|
5746
|
+
return new Promise((resolve7, reject) => {
|
|
5700
5747
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
5701
5748
|
if (redirectCount > 5) {
|
|
5702
5749
|
reject(new Error("Too many redirects"));
|
|
@@ -5716,7 +5763,7 @@ var init_provider_loader = __esm({
|
|
|
5716
5763
|
res.pipe(ws2);
|
|
5717
5764
|
ws2.on("finish", () => {
|
|
5718
5765
|
ws2.close();
|
|
5719
|
-
|
|
5766
|
+
resolve7();
|
|
5720
5767
|
});
|
|
5721
5768
|
ws2.on("error", reject);
|
|
5722
5769
|
});
|
|
@@ -6082,17 +6129,17 @@ async function findFreePort(ports) {
|
|
|
6082
6129
|
throw new Error("No free port found");
|
|
6083
6130
|
}
|
|
6084
6131
|
function checkPortFree(port) {
|
|
6085
|
-
return new Promise((
|
|
6132
|
+
return new Promise((resolve7) => {
|
|
6086
6133
|
const server = net.createServer();
|
|
6087
6134
|
server.unref();
|
|
6088
|
-
server.on("error", () =>
|
|
6135
|
+
server.on("error", () => resolve7(false));
|
|
6089
6136
|
server.listen(port, "127.0.0.1", () => {
|
|
6090
|
-
server.close(() =>
|
|
6137
|
+
server.close(() => resolve7(true));
|
|
6091
6138
|
});
|
|
6092
6139
|
});
|
|
6093
6140
|
}
|
|
6094
6141
|
async function isCdpActive(port) {
|
|
6095
|
-
return new Promise((
|
|
6142
|
+
return new Promise((resolve7) => {
|
|
6096
6143
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
6097
6144
|
timeout: 2e3
|
|
6098
6145
|
}, (res) => {
|
|
@@ -6101,16 +6148,16 @@ async function isCdpActive(port) {
|
|
|
6101
6148
|
res.on("end", () => {
|
|
6102
6149
|
try {
|
|
6103
6150
|
const info = JSON.parse(data);
|
|
6104
|
-
|
|
6151
|
+
resolve7(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
6105
6152
|
} catch {
|
|
6106
|
-
|
|
6153
|
+
resolve7(false);
|
|
6107
6154
|
}
|
|
6108
6155
|
});
|
|
6109
6156
|
});
|
|
6110
|
-
req.on("error", () =>
|
|
6157
|
+
req.on("error", () => resolve7(false));
|
|
6111
6158
|
req.on("timeout", () => {
|
|
6112
6159
|
req.destroy();
|
|
6113
|
-
|
|
6160
|
+
resolve7(false);
|
|
6114
6161
|
});
|
|
6115
6162
|
});
|
|
6116
6163
|
}
|
|
@@ -16316,6 +16363,36 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
16316
16363
|
).length;
|
|
16317
16364
|
return matched >= required2;
|
|
16318
16365
|
}
|
|
16366
|
+
function splitHistoryLines(text) {
|
|
16367
|
+
return String(text || "").split("\n").map((line) => line.replace(/\s+$/, ""));
|
|
16368
|
+
}
|
|
16369
|
+
function normalizeHistoryLine(line) {
|
|
16370
|
+
return String(line || "").replace(/\s+/g, " ").trim();
|
|
16371
|
+
}
|
|
16372
|
+
function mergeTerminalHistory(existing, snapshot) {
|
|
16373
|
+
const next = String(snapshot || "").trim();
|
|
16374
|
+
if (!next) return existing;
|
|
16375
|
+
const prev = String(existing || "").trim();
|
|
16376
|
+
if (!prev) return next;
|
|
16377
|
+
if (prev === next || prev.endsWith(next)) return prev;
|
|
16378
|
+
const prevLines = splitHistoryLines(prev);
|
|
16379
|
+
const nextLines = splitHistoryLines(next);
|
|
16380
|
+
const prevNorm = prevLines.map(normalizeHistoryLine);
|
|
16381
|
+
const nextNorm = nextLines.map(normalizeHistoryLine);
|
|
16382
|
+
const maxOverlap = Math.min(prevLines.length, nextLines.length);
|
|
16383
|
+
for (let overlap = maxOverlap; overlap >= 1; overlap -= 1) {
|
|
16384
|
+
const prevTail = prevNorm.slice(prevNorm.length - overlap);
|
|
16385
|
+
const nextHead = nextNorm.slice(0, overlap);
|
|
16386
|
+
if (prevTail.every((line, index) => line === nextHead[index])) {
|
|
16387
|
+
return [...prevLines, ...nextLines.slice(overlap)].join("\n").trim();
|
|
16388
|
+
}
|
|
16389
|
+
}
|
|
16390
|
+
const compactPrev = prevNorm.join("\n");
|
|
16391
|
+
const compactNext = nextNorm.join("\n");
|
|
16392
|
+
if (compactPrev.includes(compactNext)) return prev;
|
|
16393
|
+
return `${prev}
|
|
16394
|
+
${next}`.trim();
|
|
16395
|
+
}
|
|
16319
16396
|
function parsePatternEntry(x) {
|
|
16320
16397
|
if (x instanceof RegExp) return x;
|
|
16321
16398
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -16392,6 +16469,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
16392
16469
|
this.approvalKeys = rawKeys && typeof rawKeys === "object" ? rawKeys : {};
|
|
16393
16470
|
this.sendDelayMs = typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0;
|
|
16394
16471
|
this.sendKey = typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r";
|
|
16472
|
+
this.submitStrategy = provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo";
|
|
16395
16473
|
this.cliScripts = provider.scripts || {};
|
|
16396
16474
|
const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
|
|
16397
16475
|
if (scriptNames.length > 0) {
|
|
@@ -16406,6 +16484,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
16406
16484
|
provider;
|
|
16407
16485
|
ptyProcess = null;
|
|
16408
16486
|
messages = [];
|
|
16487
|
+
committedMessages = [];
|
|
16409
16488
|
structuredMessages = [];
|
|
16410
16489
|
currentStatus = "starting";
|
|
16411
16490
|
onStatusChange = null;
|
|
@@ -16452,8 +16531,35 @@ var init_provider_cli_adapter = __esm({
|
|
|
16452
16531
|
accumulatedRawBuffer = "";
|
|
16453
16532
|
/** Current visible terminal screen snapshot */
|
|
16454
16533
|
terminalScreen = new TerminalScreen(40, 120);
|
|
16534
|
+
/** Rolling append-only terminal transcript built from screen snapshots */
|
|
16535
|
+
terminalHistory = "";
|
|
16455
16536
|
/** Max accumulated buffer size (last 50KB) */
|
|
16456
16537
|
static MAX_ACCUMULATED_BUFFER = 5e4;
|
|
16538
|
+
currentTurnScope = null;
|
|
16539
|
+
syncMessageViews() {
|
|
16540
|
+
this.messages = [...this.committedMessages];
|
|
16541
|
+
this.structuredMessages = [...this.committedMessages];
|
|
16542
|
+
}
|
|
16543
|
+
sliceFromOffset(text, start) {
|
|
16544
|
+
if (!text) return "";
|
|
16545
|
+
if (!Number.isFinite(start) || start <= 0) return text;
|
|
16546
|
+
if (start >= text.length) return "";
|
|
16547
|
+
return text.slice(start);
|
|
16548
|
+
}
|
|
16549
|
+
buildParseInput(baseMessages, partialResponse, scope) {
|
|
16550
|
+
const buffer = scope ? this.sliceFromOffset(this.terminalHistory, scope.terminalHistoryStart) || this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
16551
|
+
const rawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
16552
|
+
const terminalHistory = scope ? this.sliceFromOffset(this.terminalHistory, scope.terminalHistoryStart) || this.terminalHistory : this.terminalHistory;
|
|
16553
|
+
return {
|
|
16554
|
+
buffer,
|
|
16555
|
+
rawBuffer,
|
|
16556
|
+
recentBuffer: buffer.slice(-1e3) || this.recentOutputBuffer,
|
|
16557
|
+
screenText: this.terminalScreen.getText(),
|
|
16558
|
+
terminalHistory,
|
|
16559
|
+
messages: [...baseMessages],
|
|
16560
|
+
partialResponse
|
|
16561
|
+
};
|
|
16562
|
+
}
|
|
16457
16563
|
setStatus(status, trigger) {
|
|
16458
16564
|
const prev = this.currentStatus;
|
|
16459
16565
|
if (prev === status) return;
|
|
@@ -16468,6 +16574,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
16468
16574
|
approvalKeys;
|
|
16469
16575
|
sendDelayMs;
|
|
16470
16576
|
sendKey;
|
|
16577
|
+
submitStrategy;
|
|
16471
16578
|
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
16472
16579
|
setCliScripts(scripts) {
|
|
16473
16580
|
this.cliScripts = scripts;
|
|
@@ -16563,6 +16670,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
16563
16670
|
this.startupParseGate = true;
|
|
16564
16671
|
this.startupBuffer = "";
|
|
16565
16672
|
this.terminalScreen.reset(40, 120);
|
|
16673
|
+
this.terminalHistory = "";
|
|
16674
|
+
this.currentTurnScope = null;
|
|
16566
16675
|
this.ready = false;
|
|
16567
16676
|
this.setStatus("idle", "pty_ready");
|
|
16568
16677
|
this.onStatusChange?.();
|
|
@@ -16574,6 +16683,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
16574
16683
|
this.ptyProcess?.write("\x1B[1;1R");
|
|
16575
16684
|
}
|
|
16576
16685
|
this.terminalScreen.write(rawData);
|
|
16686
|
+
this.terminalHistory = mergeTerminalHistory(this.terminalHistory, this.terminalScreen.getText());
|
|
16577
16687
|
const cleanData = stripAnsi(rawData);
|
|
16578
16688
|
if (this.isWaitingForResponse && cleanData) {
|
|
16579
16689
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
@@ -16718,6 +16828,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
16718
16828
|
finishResponse() {
|
|
16719
16829
|
if (this.submitPendingUntil > Date.now()) return;
|
|
16720
16830
|
if (this.responseSettleIgnoreUntil > Date.now()) return;
|
|
16831
|
+
this.commitCurrentTranscript();
|
|
16721
16832
|
if (this.responseTimeout) {
|
|
16722
16833
|
clearTimeout(this.responseTimeout);
|
|
16723
16834
|
this.responseTimeout = null;
|
|
@@ -16739,10 +16850,58 @@ var init_provider_cli_adapter = __esm({
|
|
|
16739
16850
|
this.responseSettleIgnoreUntil = 0;
|
|
16740
16851
|
this.submitRetryUsed = false;
|
|
16741
16852
|
this.submitRetryPromptSnippet = "";
|
|
16853
|
+
this.currentTurnScope = null;
|
|
16742
16854
|
this.activeModal = null;
|
|
16743
16855
|
this.setStatus("idle", "response_finished");
|
|
16744
16856
|
this.onStatusChange?.();
|
|
16745
16857
|
}
|
|
16858
|
+
commitCurrentTranscript() {
|
|
16859
|
+
const baseMessages = [...this.committedMessages];
|
|
16860
|
+
const parsed = this.parseCurrentTranscript(baseMessages, "", this.currentTurnScope);
|
|
16861
|
+
if (parsed && Array.isArray(parsed.messages) && parsed.messages.length > 0) {
|
|
16862
|
+
const parsedMessages = parsed.messages.filter((m) => m && (m.role === "user" || m.role === "assistant")).map((m) => ({
|
|
16863
|
+
role: m.role,
|
|
16864
|
+
content: typeof m.content === "string" ? m.content : String(m.content || ""),
|
|
16865
|
+
timestamp: m.timestamp
|
|
16866
|
+
}));
|
|
16867
|
+
const latestAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
|
|
16868
|
+
if (latestAssistant) {
|
|
16869
|
+
LOG.info("CLI", `[${this.cliType}] commitCurrentTranscript parsed assistant len=${latestAssistant.content.length} scopePrompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 120)}`);
|
|
16870
|
+
const nextMessages = [...baseMessages];
|
|
16871
|
+
const last2 = nextMessages[nextMessages.length - 1];
|
|
16872
|
+
if (last2?.role === "assistant") {
|
|
16873
|
+
last2.content = latestAssistant.content;
|
|
16874
|
+
last2.timestamp = latestAssistant.timestamp || last2.timestamp;
|
|
16875
|
+
} else if (last2?.role === "user") {
|
|
16876
|
+
nextMessages.push({
|
|
16877
|
+
role: "assistant",
|
|
16878
|
+
content: latestAssistant.content,
|
|
16879
|
+
timestamp: latestAssistant.timestamp || Date.now()
|
|
16880
|
+
});
|
|
16881
|
+
} else {
|
|
16882
|
+
nextMessages.push({
|
|
16883
|
+
role: "assistant",
|
|
16884
|
+
content: latestAssistant.content,
|
|
16885
|
+
timestamp: latestAssistant.timestamp || Date.now()
|
|
16886
|
+
});
|
|
16887
|
+
}
|
|
16888
|
+
this.committedMessages = nextMessages;
|
|
16889
|
+
this.syncMessageViews();
|
|
16890
|
+
return;
|
|
16891
|
+
}
|
|
16892
|
+
}
|
|
16893
|
+
const fallback = String(this.responseBuffer || "").trim();
|
|
16894
|
+
LOG.info("CLI", `[${this.cliType}] commitCurrentTranscript fallback len=${fallback.length} scopePrompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 120)}`);
|
|
16895
|
+
if (!fallback) return;
|
|
16896
|
+
const last = baseMessages[baseMessages.length - 1];
|
|
16897
|
+
if (last?.role === "assistant") {
|
|
16898
|
+
last.content = fallback;
|
|
16899
|
+
} else {
|
|
16900
|
+
baseMessages.push({ role: "assistant", content: fallback, timestamp: Date.now() });
|
|
16901
|
+
}
|
|
16902
|
+
this.committedMessages = baseMessages;
|
|
16903
|
+
this.syncMessageViews();
|
|
16904
|
+
}
|
|
16746
16905
|
// ─── Script Execution ──────────────────────────
|
|
16747
16906
|
runDetectStatus(text) {
|
|
16748
16907
|
if (!this.cliScripts?.detectStatus) return null;
|
|
@@ -16772,24 +16931,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
16772
16931
|
}
|
|
16773
16932
|
// ─── Public API (CliAdapter) ───────────────────
|
|
16774
16933
|
getStatus() {
|
|
16775
|
-
const scriptResult = this.getScriptParsedStatus();
|
|
16776
|
-
if (scriptResult) {
|
|
16777
|
-
return {
|
|
16778
|
-
status: this.currentStatus,
|
|
16779
|
-
messages: (scriptResult.messages || []).map((m) => ({
|
|
16780
|
-
role: m.role,
|
|
16781
|
-
content: m.content,
|
|
16782
|
-
timestamp: m.timestamp
|
|
16783
|
-
})),
|
|
16784
|
-
workingDir: this.workingDir,
|
|
16785
|
-
activeModal: this.activeModal
|
|
16786
|
-
};
|
|
16787
|
-
}
|
|
16788
16934
|
return {
|
|
16789
16935
|
status: this.currentStatus,
|
|
16790
|
-
messages: [...this.
|
|
16936
|
+
messages: [...this.committedMessages],
|
|
16791
16937
|
workingDir: this.workingDir,
|
|
16792
|
-
activeModal: this.activeModal
|
|
16938
|
+
activeModal: this.activeModal,
|
|
16939
|
+
terminalHistory: this.terminalHistory
|
|
16793
16940
|
};
|
|
16794
16941
|
}
|
|
16795
16942
|
/**
|
|
@@ -16797,31 +16944,32 @@ var init_provider_cli_adapter = __esm({
|
|
|
16797
16944
|
* Called by command handler / dashboard for rich content rendering.
|
|
16798
16945
|
*/
|
|
16799
16946
|
getScriptParsedStatus() {
|
|
16947
|
+
const messages = [...this.committedMessages];
|
|
16948
|
+
return {
|
|
16949
|
+
id: "cli_session",
|
|
16950
|
+
status: this.currentStatus,
|
|
16951
|
+
title: this.cliName,
|
|
16952
|
+
terminalHistory: this.terminalHistory,
|
|
16953
|
+
messages: messages.slice(-50).map((message, index) => ({
|
|
16954
|
+
id: `msg_${index}`,
|
|
16955
|
+
role: message.role,
|
|
16956
|
+
content: message.content,
|
|
16957
|
+
timestamp: message.timestamp,
|
|
16958
|
+
index,
|
|
16959
|
+
kind: "standard"
|
|
16960
|
+
})),
|
|
16961
|
+
activeModal: this.activeModal
|
|
16962
|
+
};
|
|
16963
|
+
}
|
|
16964
|
+
parseCurrentTranscript(baseMessages, partialResponse, scope) {
|
|
16800
16965
|
if (!this.cliScripts?.parseOutput) return null;
|
|
16801
16966
|
try {
|
|
16802
|
-
const input =
|
|
16803
|
-
|
|
16804
|
-
rawBuffer: this.accumulatedRawBuffer,
|
|
16805
|
-
recentBuffer: this.recentOutputBuffer,
|
|
16806
|
-
screenText: this.terminalScreen.getText(),
|
|
16807
|
-
messages: [...this.structuredMessages.length > 0 ? this.structuredMessages : this.messages],
|
|
16808
|
-
partialResponse: this.responseBuffer
|
|
16809
|
-
};
|
|
16810
|
-
const result = this.cliScripts.parseOutput(input);
|
|
16811
|
-
if (result && typeof result === "object") {
|
|
16812
|
-
if (Array.isArray(result.messages)) {
|
|
16813
|
-
this.structuredMessages = result.messages.map((m) => ({
|
|
16814
|
-
role: m.role,
|
|
16815
|
-
content: m.content,
|
|
16816
|
-
timestamp: m.timestamp
|
|
16817
|
-
}));
|
|
16818
|
-
}
|
|
16819
|
-
return result;
|
|
16820
|
-
}
|
|
16967
|
+
const input = this.buildParseInput(baseMessages, partialResponse, scope);
|
|
16968
|
+
return this.cliScripts.parseOutput(input);
|
|
16821
16969
|
} catch (e) {
|
|
16822
16970
|
LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
|
|
16971
|
+
return null;
|
|
16823
16972
|
}
|
|
16824
|
-
return null;
|
|
16825
16973
|
}
|
|
16826
16974
|
/** Whether this adapter has CLI scripts loaded */
|
|
16827
16975
|
hasCliScripts() {
|
|
@@ -16856,15 +17004,23 @@ ${data.message || ""}`.trim();
|
|
|
16856
17004
|
if (this.startupParseGate) {
|
|
16857
17005
|
const deadline = Date.now() + 1e4;
|
|
16858
17006
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
16859
|
-
await new Promise((
|
|
17007
|
+
await new Promise((resolve7) => setTimeout(resolve7, 50));
|
|
16860
17008
|
}
|
|
16861
17009
|
}
|
|
16862
17010
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
16863
17011
|
if (this.isWaitingForResponse) return;
|
|
16864
|
-
this.
|
|
16865
|
-
this.
|
|
17012
|
+
this.committedMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
17013
|
+
this.syncMessageViews();
|
|
16866
17014
|
this.isWaitingForResponse = true;
|
|
16867
17015
|
this.responseBuffer = "";
|
|
17016
|
+
this.currentTurnScope = {
|
|
17017
|
+
prompt: text,
|
|
17018
|
+
startedAt: Date.now(),
|
|
17019
|
+
bufferStart: this.accumulatedBuffer.length,
|
|
17020
|
+
rawBufferStart: this.accumulatedRawBuffer.length,
|
|
17021
|
+
terminalHistoryStart: this.terminalHistory.length
|
|
17022
|
+
};
|
|
17023
|
+
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${this.currentTurnScope.bufferStart} raw=${this.currentTurnScope.rawBufferStart} terminal=${this.currentTurnScope.terminalHistoryStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
|
|
16868
17024
|
this.submitRetryUsed = false;
|
|
16869
17025
|
this.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
|
|
16870
17026
|
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet);
|
|
@@ -16884,10 +17040,12 @@ ${data.message || ""}`.trim();
|
|
|
16884
17040
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
16885
17041
|
this.setStatus("generating", "sendMessage");
|
|
16886
17042
|
this.onStatusChange?.();
|
|
16887
|
-
|
|
16888
|
-
this.
|
|
16889
|
-
|
|
16890
|
-
|
|
17043
|
+
const startResponseTimeout = () => {
|
|
17044
|
+
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
17045
|
+
this.responseTimeout = setTimeout(() => {
|
|
17046
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
17047
|
+
}, this.timeouts.maxResponse);
|
|
17048
|
+
};
|
|
16891
17049
|
const submit = () => {
|
|
16892
17050
|
if (!this.ptyProcess) return;
|
|
16893
17051
|
this.submitPendingUntil = 0;
|
|
@@ -16910,10 +17068,30 @@ ${data.message || ""}`.trim();
|
|
|
16910
17068
|
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
|
|
16911
17069
|
};
|
|
16912
17070
|
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
|
|
16913
|
-
|
|
16914
|
-
if (this.isWaitingForResponse) this.finishResponse();
|
|
16915
|
-
}, this.timeouts.maxResponse);
|
|
17071
|
+
startResponseTimeout();
|
|
16916
17072
|
};
|
|
17073
|
+
if (this.submitStrategy === "immediate") {
|
|
17074
|
+
this.submitPendingUntil = 0;
|
|
17075
|
+
this.ptyProcess.write(text + this.sendKey);
|
|
17076
|
+
this.submitRetryTimer = setTimeout(() => {
|
|
17077
|
+
this.submitRetryTimer = null;
|
|
17078
|
+
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
17079
|
+
if (this.currentStatus !== "generating") return;
|
|
17080
|
+
if ((this.responseBuffer || "").trim()) return;
|
|
17081
|
+
const screenText = this.terminalScreen.getText();
|
|
17082
|
+
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
17083
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
17084
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
17085
|
+
this.ptyProcess.write(this.sendKey);
|
|
17086
|
+
this.submitRetryUsed = true;
|
|
17087
|
+
}, retryDelayMs);
|
|
17088
|
+
startResponseTimeout();
|
|
17089
|
+
return;
|
|
17090
|
+
}
|
|
17091
|
+
if (submitDelayMs > 0) {
|
|
17092
|
+
this.submitPendingUntil = Date.now() + submitDelayMs;
|
|
17093
|
+
}
|
|
17094
|
+
this.ptyProcess.write(text);
|
|
16917
17095
|
const submitStartedAt = Date.now();
|
|
16918
17096
|
let lastNormalizedScreen = "";
|
|
16919
17097
|
let lastScreenChangeAt = submitStartedAt;
|
|
@@ -16980,10 +17158,12 @@ ${data.message || ""}`.trim();
|
|
|
16980
17158
|
}
|
|
16981
17159
|
}
|
|
16982
17160
|
clearHistory() {
|
|
16983
|
-
this.
|
|
16984
|
-
this.
|
|
17161
|
+
this.committedMessages = [];
|
|
17162
|
+
this.syncMessageViews();
|
|
16985
17163
|
this.accumulatedBuffer = "";
|
|
16986
17164
|
this.accumulatedRawBuffer = "";
|
|
17165
|
+
this.terminalHistory = "";
|
|
17166
|
+
this.currentTurnScope = null;
|
|
16987
17167
|
this.submitRetryUsed = false;
|
|
16988
17168
|
this.submitRetryPromptSnippet = "";
|
|
16989
17169
|
this.terminalScreen.reset();
|
|
@@ -17037,9 +17217,12 @@ ${data.message || ""}`.trim();
|
|
|
17037
17217
|
spawnAt: this.spawnAt,
|
|
17038
17218
|
workingDir: this.workingDir,
|
|
17039
17219
|
messages: this.messages.slice(-20),
|
|
17220
|
+
committedMessages: this.committedMessages.slice(-20),
|
|
17040
17221
|
structuredMessages: this.structuredMessages.slice(-20),
|
|
17041
|
-
messageCount: this.
|
|
17222
|
+
messageCount: this.committedMessages.length,
|
|
17042
17223
|
screenText: this.terminalScreen.getText().slice(-4e3),
|
|
17224
|
+
terminalHistory: this.terminalHistory.slice(-8e3),
|
|
17225
|
+
currentTurnScope: this.currentTurnScope,
|
|
17043
17226
|
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
17044
17227
|
recentOutputBuffer: this.recentOutputBuffer.slice(-500),
|
|
17045
17228
|
settledBuffer: this.settledBuffer.slice(-500),
|
|
@@ -17052,6 +17235,7 @@ ${data.message || ""}`.trim();
|
|
|
17052
17235
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
17053
17236
|
sendDelayMs: this.sendDelayMs,
|
|
17054
17237
|
sendKey: this.sendKey,
|
|
17238
|
+
submitStrategy: this.submitStrategy,
|
|
17055
17239
|
submitPendingUntil: this.submitPendingUntil,
|
|
17056
17240
|
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
17057
17241
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
@@ -17124,31 +17308,12 @@ var init_cli_provider_instance = __esm({
|
|
|
17124
17308
|
async onTick() {
|
|
17125
17309
|
}
|
|
17126
17310
|
getState() {
|
|
17127
|
-
const
|
|
17128
|
-
const parsedStatus = this.adapter.getScriptParsedStatus();
|
|
17129
|
-
const adapterStatus = parsedStatus ? {
|
|
17130
|
-
...rawStatus,
|
|
17131
|
-
messages: parsedStatus.messages || rawStatus.messages,
|
|
17132
|
-
activeModal: parsedStatus.activeModal || rawStatus.activeModal
|
|
17133
|
-
} : rawStatus;
|
|
17311
|
+
const adapterStatus = this.adapter.getStatus();
|
|
17134
17312
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
17135
17313
|
const recentMessages = adapterStatus.messages.slice(-50).map((m) => {
|
|
17136
17314
|
const content = typeof m.content === "string" && m.content.length > 8e3 ? m.content.slice(0, 8e3) + "\n... (truncated)" : m.content;
|
|
17137
17315
|
return { ...m, content };
|
|
17138
17316
|
});
|
|
17139
|
-
const partial2 = this.adapter.getPartialResponse();
|
|
17140
|
-
const shouldAppendRawPartial = !parsedStatus;
|
|
17141
|
-
if (shouldAppendRawPartial && adapterStatus.status === "generating" && partial2) {
|
|
17142
|
-
const cleaned = partial2.trim();
|
|
17143
|
-
if (cleaned && cleaned !== "(generating...)") {
|
|
17144
|
-
recentMessages.push({
|
|
17145
|
-
role: "assistant",
|
|
17146
|
-
content: (cleaned.length > 8e3 ? cleaned.slice(0, 8e3) + "..." : cleaned) + "...",
|
|
17147
|
-
timestamp: Date.now(),
|
|
17148
|
-
meta: { streaming: true }
|
|
17149
|
-
});
|
|
17150
|
-
}
|
|
17151
|
-
}
|
|
17152
17317
|
if (recentMessages.length > 0) {
|
|
17153
17318
|
const dirName2 = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
17154
17319
|
this.historyWriter.appendNewMessages(
|
|
@@ -17158,6 +17323,14 @@ var init_cli_provider_instance = __esm({
|
|
|
17158
17323
|
this.instanceId
|
|
17159
17324
|
);
|
|
17160
17325
|
}
|
|
17326
|
+
if (adapterStatus.terminalHistory?.trim()) {
|
|
17327
|
+
this.historyWriter.appendTerminalHistory(
|
|
17328
|
+
this.type,
|
|
17329
|
+
adapterStatus.terminalHistory,
|
|
17330
|
+
`${this.provider.name} \xB7 ${dirName}`,
|
|
17331
|
+
this.instanceId
|
|
17332
|
+
);
|
|
17333
|
+
}
|
|
17161
17334
|
return {
|
|
17162
17335
|
type: this.type,
|
|
17163
17336
|
name: this.provider.name,
|
|
@@ -17170,6 +17343,7 @@ var init_cli_provider_instance = __esm({
|
|
|
17170
17343
|
status: adapterStatus.status,
|
|
17171
17344
|
messages: recentMessages,
|
|
17172
17345
|
activeModal: adapterStatus.activeModal,
|
|
17346
|
+
terminalHistory: adapterStatus.terminalHistory,
|
|
17173
17347
|
inputContent: ""
|
|
17174
17348
|
},
|
|
17175
17349
|
workspace: this.workingDir,
|
|
@@ -33373,8 +33547,8 @@ var init_acp = __esm({
|
|
|
33373
33547
|
this.#requestHandler = requestHandler;
|
|
33374
33548
|
this.#notificationHandler = notificationHandler;
|
|
33375
33549
|
this.#stream = stream;
|
|
33376
|
-
this.#closedPromise = new Promise((
|
|
33377
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
33550
|
+
this.#closedPromise = new Promise((resolve7) => {
|
|
33551
|
+
this.#abortController.signal.addEventListener("abort", () => resolve7());
|
|
33378
33552
|
});
|
|
33379
33553
|
this.#receive();
|
|
33380
33554
|
}
|
|
@@ -33523,8 +33697,8 @@ var init_acp = __esm({
|
|
|
33523
33697
|
}
|
|
33524
33698
|
async sendRequest(method, params) {
|
|
33525
33699
|
const id = this.#nextRequestId++;
|
|
33526
|
-
const responsePromise = new Promise((
|
|
33527
|
-
this.#pendingResponses.set(id, { resolve:
|
|
33700
|
+
const responsePromise = new Promise((resolve7, reject) => {
|
|
33701
|
+
this.#pendingResponses.set(id, { resolve: resolve7, reject });
|
|
33528
33702
|
});
|
|
33529
33703
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
33530
33704
|
return responsePromise;
|
|
@@ -34056,13 +34230,13 @@ var init_acp_provider_instance = __esm({
|
|
|
34056
34230
|
}
|
|
34057
34231
|
this.currentStatus = "waiting_approval";
|
|
34058
34232
|
this.detectStatusTransition();
|
|
34059
|
-
const approved = await new Promise((
|
|
34060
|
-
this.permissionResolvers.push(
|
|
34233
|
+
const approved = await new Promise((resolve7) => {
|
|
34234
|
+
this.permissionResolvers.push(resolve7);
|
|
34061
34235
|
setTimeout(() => {
|
|
34062
|
-
const idx = this.permissionResolvers.indexOf(
|
|
34236
|
+
const idx = this.permissionResolvers.indexOf(resolve7);
|
|
34063
34237
|
if (idx >= 0) {
|
|
34064
34238
|
this.permissionResolvers.splice(idx, 1);
|
|
34065
|
-
|
|
34239
|
+
resolve7(false);
|
|
34066
34240
|
}
|
|
34067
34241
|
}, 3e5);
|
|
34068
34242
|
});
|
|
@@ -35652,7 +35826,8 @@ async function detectAllVersions(loader, archive) {
|
|
|
35652
35826
|
binary: null,
|
|
35653
35827
|
detectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
35654
35828
|
};
|
|
35655
|
-
const
|
|
35829
|
+
const verCmdConfig = provider.versionCommand;
|
|
35830
|
+
const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[currentOs] : verCmdConfig;
|
|
35656
35831
|
if (provider.category === "ide") {
|
|
35657
35832
|
const osPaths = provider.paths?.[currentOs] || [];
|
|
35658
35833
|
const appPath = checkPathExists2(osPaths);
|
|
@@ -36231,15 +36406,15 @@ var init_dev_server = __esm({
|
|
|
36231
36406
|
this.json(res, 500, { error: e.message });
|
|
36232
36407
|
}
|
|
36233
36408
|
});
|
|
36234
|
-
return new Promise((
|
|
36409
|
+
return new Promise((resolve7, reject) => {
|
|
36235
36410
|
this.server.listen(port, "127.0.0.1", () => {
|
|
36236
36411
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
36237
|
-
|
|
36412
|
+
resolve7();
|
|
36238
36413
|
});
|
|
36239
36414
|
this.server.on("error", (e) => {
|
|
36240
36415
|
if (e.code === "EADDRINUSE") {
|
|
36241
36416
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
36242
|
-
|
|
36417
|
+
resolve7();
|
|
36243
36418
|
} else {
|
|
36244
36419
|
reject(e);
|
|
36245
36420
|
}
|
|
@@ -36322,20 +36497,20 @@ var init_dev_server = __esm({
|
|
|
36322
36497
|
child.stderr?.on("data", (d) => {
|
|
36323
36498
|
stderr += d.toString().slice(0, 2e3);
|
|
36324
36499
|
});
|
|
36325
|
-
await new Promise((
|
|
36500
|
+
await new Promise((resolve7) => {
|
|
36326
36501
|
const timer = setTimeout(() => {
|
|
36327
36502
|
child.kill();
|
|
36328
|
-
|
|
36503
|
+
resolve7();
|
|
36329
36504
|
}, 3e3);
|
|
36330
36505
|
child.on("exit", () => {
|
|
36331
36506
|
clearTimeout(timer);
|
|
36332
|
-
|
|
36507
|
+
resolve7();
|
|
36333
36508
|
});
|
|
36334
36509
|
child.stdout?.once("data", () => {
|
|
36335
36510
|
setTimeout(() => {
|
|
36336
36511
|
child.kill();
|
|
36337
36512
|
clearTimeout(timer);
|
|
36338
|
-
|
|
36513
|
+
resolve7();
|
|
36339
36514
|
}, 500);
|
|
36340
36515
|
});
|
|
36341
36516
|
});
|
|
@@ -37079,14 +37254,14 @@ var init_dev_server = __esm({
|
|
|
37079
37254
|
child.stderr?.on("data", (d) => {
|
|
37080
37255
|
stderr += d.toString();
|
|
37081
37256
|
});
|
|
37082
|
-
await new Promise((
|
|
37257
|
+
await new Promise((resolve7) => {
|
|
37083
37258
|
const timer = setTimeout(() => {
|
|
37084
37259
|
child.kill();
|
|
37085
|
-
|
|
37260
|
+
resolve7();
|
|
37086
37261
|
}, timeout);
|
|
37087
37262
|
child.on("exit", () => {
|
|
37088
37263
|
clearTimeout(timer);
|
|
37089
|
-
|
|
37264
|
+
resolve7();
|
|
37090
37265
|
});
|
|
37091
37266
|
});
|
|
37092
37267
|
const elapsed = Date.now() - start;
|
|
@@ -37137,11 +37312,7 @@ var init_dev_server = __esm({
|
|
|
37137
37312
|
return;
|
|
37138
37313
|
}
|
|
37139
37314
|
let targetDir;
|
|
37140
|
-
|
|
37141
|
-
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
37142
|
-
} else {
|
|
37143
|
-
targetDir = this.providerLoader.getBuiltinProviderDir(category, type);
|
|
37144
|
-
}
|
|
37315
|
+
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
37145
37316
|
const jsonPath = path12.join(targetDir, "provider.json");
|
|
37146
37317
|
if (fs10.existsSync(jsonPath)) {
|
|
37147
37318
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
@@ -37939,8 +38110,7 @@ var init_dev_server = __esm({
|
|
|
37939
38110
|
}
|
|
37940
38111
|
loadAutoImplReferenceScripts(category, referenceType) {
|
|
37941
38112
|
if (!referenceType) return {};
|
|
37942
|
-
const
|
|
37943
|
-
const refDir = path12.join(builtinDir, category, referenceType);
|
|
38113
|
+
const refDir = this.providerLoader.getUpstreamProviderDir(category, referenceType);
|
|
37944
38114
|
if (!fs10.existsSync(refDir)) return {};
|
|
37945
38115
|
const referenceScripts = {};
|
|
37946
38116
|
const scriptsDir = path12.join(refDir, "scripts");
|
|
@@ -38179,7 +38349,7 @@ var init_dev_server = __esm({
|
|
|
38179
38349
|
}
|
|
38180
38350
|
if (model) args.push("--model", model);
|
|
38181
38351
|
const escapedArgs = args.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
38182
|
-
const metaPrompt = `Read the file at ${promptFile} and follow ALL instructions
|
|
38352
|
+
const metaPrompt = `Read the file at ${promptFile} and follow ALL instructions strictly. DO NOT spend time exploring the filesystem or other providers. You have full authority to implement ALL required script files and independently test them against 127.0.0.1:19280 via CDP CURL. Upon complete validation of ALL assigned files, print exactly "_PIPELINE_COMPLETE_SIGNAL_" to gracefully close the pipeline. DO NOT WAIT FOR APPROVAL, execute completely autonomously.`;
|
|
38183
38353
|
shellCmd = `${command} ${escapedArgs} "${metaPrompt}"`;
|
|
38184
38354
|
} else {
|
|
38185
38355
|
const escapedArgs = baseArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
@@ -38442,6 +38612,8 @@ var init_dev_server = __esm({
|
|
|
38442
38612
|
lines.push("5. Do NOT modify `scripts.js` router \u2014 only edit individual `*.js` files");
|
|
38443
38613
|
lines.push("6. All scripts run in the browser (CDP evaluate) \u2014 use DOM APIs only");
|
|
38444
38614
|
lines.push('7. **Cross-Platform Compatibility**: If you use ARIA labels that contain keyboard shortcuts (e.g., `Cascade (\u2318L)`), you MUST use substring matches (`aria-label*="Cascade"`) or handle both macOS (`\u2318`, `Cmd`) and Windows (`Ctrl`) so the script does not break on other operating systems.');
|
|
38615
|
+
lines.push("8. **CRITICAL: DO NOT explore the filesystem or read other providers.** The reference implementation pattern is already provided below. Do not run `find`, `rg`, or `cat` on upstream providers. Doing so wastes context tokens and will crash the agent session. Focus entirely on modifying the target files.");
|
|
38616
|
+
lines.push("9. Do NOT delete any files. Implement the logic by replacing the empty stubs.");
|
|
38445
38617
|
lines.push("");
|
|
38446
38618
|
lines.push("## Required Return Format");
|
|
38447
38619
|
lines.push("| Function | Return JSON |");
|
|
@@ -38791,14 +38963,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
38791
38963
|
res.end(JSON.stringify(data, null, 2));
|
|
38792
38964
|
}
|
|
38793
38965
|
async readBody(req) {
|
|
38794
|
-
return new Promise((
|
|
38966
|
+
return new Promise((resolve7) => {
|
|
38795
38967
|
let body = "";
|
|
38796
38968
|
req.on("data", (chunk) => body += chunk);
|
|
38797
38969
|
req.on("end", () => {
|
|
38798
38970
|
try {
|
|
38799
|
-
|
|
38971
|
+
resolve7(JSON.parse(body));
|
|
38800
38972
|
} catch {
|
|
38801
|
-
|
|
38973
|
+
resolve7({});
|
|
38802
38974
|
}
|
|
38803
38975
|
});
|
|
38804
38976
|
});
|
|
@@ -39724,13 +39896,13 @@ ${e?.stack || ""}`);
|
|
|
39724
39896
|
} catch {
|
|
39725
39897
|
}
|
|
39726
39898
|
const http3 = esmRequire("https");
|
|
39727
|
-
const data = await new Promise((
|
|
39899
|
+
const data = await new Promise((resolve7, reject) => {
|
|
39728
39900
|
const req = http3.get(`${serverUrl}/api/v1/turn/credentials`, {
|
|
39729
39901
|
headers: { "Authorization": `Bearer ${token}` }
|
|
39730
39902
|
}, (res) => {
|
|
39731
39903
|
let d = "";
|
|
39732
39904
|
res.on("data", (c) => d += c);
|
|
39733
|
-
res.on("end", () =>
|
|
39905
|
+
res.on("end", () => resolve7(d));
|
|
39734
39906
|
});
|
|
39735
39907
|
req.on("error", reject);
|
|
39736
39908
|
req.setTimeout(5e3, () => {
|
|
@@ -40586,7 +40758,7 @@ var init_adhdev_daemon = __esm({
|
|
|
40586
40758
|
fs12 = __toESM(require("fs"));
|
|
40587
40759
|
path14 = __toESM(require("path"));
|
|
40588
40760
|
import_chalk2 = __toESM(require("chalk"));
|
|
40589
|
-
pkgVersion = "0.6.
|
|
40761
|
+
pkgVersion = "0.6.59";
|
|
40590
40762
|
if (pkgVersion === "unknown") {
|
|
40591
40763
|
try {
|
|
40592
40764
|
const possiblePaths = [
|