adhdev 0.6.52 → 0.6.55
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 +828 -315
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +752 -281
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -3173,6 +3173,9 @@ var init_builders = __esm({
|
|
|
3173
3173
|
});
|
|
3174
3174
|
|
|
3175
3175
|
// ../daemon-core/src/commands/chat-commands.ts
|
|
3176
|
+
function getTargetedCliAdapter(h, args, providerType) {
|
|
3177
|
+
return h.getCliAdapter(args?._targetInstance || h.currentIdeType || providerType);
|
|
3178
|
+
}
|
|
3176
3179
|
async function handleChatHistory(h, args) {
|
|
3177
3180
|
const { agentType, offset, limit, instanceId } = args;
|
|
3178
3181
|
try {
|
|
@@ -3185,10 +3188,10 @@ async function handleChatHistory(h, args) {
|
|
|
3185
3188
|
}
|
|
3186
3189
|
}
|
|
3187
3190
|
async function handleReadChat(h, args) {
|
|
3188
|
-
const provider = h.getProvider();
|
|
3191
|
+
const provider = h.getProvider(args?.agentType);
|
|
3189
3192
|
const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
|
|
3190
3193
|
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
3191
|
-
const adapter = h
|
|
3194
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3192
3195
|
if (adapter) {
|
|
3193
3196
|
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
3194
3197
|
const status = adapter.getStatus?.();
|
|
@@ -3304,7 +3307,7 @@ async function handleSendChat(h, args) {
|
|
|
3304
3307
|
const text = args?.text || args?.message;
|
|
3305
3308
|
if (!text) return { success: false, error: "text required" };
|
|
3306
3309
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
3307
|
-
const provider = h.getProvider();
|
|
3310
|
+
const provider = h.getProvider(args?.agentType);
|
|
3308
3311
|
const _logSendSuccess = (method, targetAgent) => {
|
|
3309
3312
|
h.historyWriter.appendNewMessages(
|
|
3310
3313
|
targetAgent || provider?.type || h.currentIdeType || "unknown_agent",
|
|
@@ -3316,7 +3319,7 @@ async function handleSendChat(h, args) {
|
|
|
3316
3319
|
return { success: true, sent: true, method, targetAgent };
|
|
3317
3320
|
};
|
|
3318
3321
|
if (provider?.category === "cli" || provider?.category === "acp") {
|
|
3319
|
-
const adapter = h
|
|
3322
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3320
3323
|
if (adapter) {
|
|
3321
3324
|
_log(`${provider.category} adapter: ${adapter.cliType}`);
|
|
3322
3325
|
try {
|
|
@@ -3469,7 +3472,7 @@ async function handleSendChat(h, args) {
|
|
|
3469
3472
|
return { success: false, error: "No provider method could send the message" };
|
|
3470
3473
|
}
|
|
3471
3474
|
async function handleListChats(h, args) {
|
|
3472
|
-
const provider = h.getProvider();
|
|
3475
|
+
const provider = h.getProvider(args?.agentType);
|
|
3473
3476
|
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
3474
3477
|
try {
|
|
3475
3478
|
const chats = await h.agentStream.listAgentChats(h.getCdp(), provider.type);
|
|
@@ -3521,7 +3524,16 @@ async function handleListChats(h, args) {
|
|
|
3521
3524
|
return { success: false, error: "listSessions script not available for this provider" };
|
|
3522
3525
|
}
|
|
3523
3526
|
async function handleNewChat(h, args) {
|
|
3524
|
-
const provider = h.getProvider();
|
|
3527
|
+
const provider = h.getProvider(args?.agentType);
|
|
3528
|
+
if (provider?.category === "cli") {
|
|
3529
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3530
|
+
if (!adapter) return { success: false, error: "CLI adapter not running" };
|
|
3531
|
+
if (typeof adapter.clearHistory === "function") {
|
|
3532
|
+
adapter.clearHistory();
|
|
3533
|
+
return { success: true, cleared: true };
|
|
3534
|
+
}
|
|
3535
|
+
return { success: false, error: "new_chat not supported by this CLI provider" };
|
|
3536
|
+
}
|
|
3525
3537
|
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
3526
3538
|
const ok = await h.agentStream.newAgentSession(h.getCdp(), provider.type, h.currentIdeType);
|
|
3527
3539
|
return { success: ok };
|
|
@@ -3546,7 +3558,7 @@ async function handleNewChat(h, args) {
|
|
|
3546
3558
|
return { success: false, error: "newSession script not available for this provider" };
|
|
3547
3559
|
}
|
|
3548
3560
|
async function handleSwitchChat(h, args) {
|
|
3549
|
-
const provider = h.getProvider();
|
|
3561
|
+
const provider = h.getProvider(args?.agentType);
|
|
3550
3562
|
const ideType = h.currentIdeType;
|
|
3551
3563
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
3552
3564
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
@@ -3640,10 +3652,10 @@ async function handleSwitchChat(h, args) {
|
|
|
3640
3652
|
}
|
|
3641
3653
|
}
|
|
3642
3654
|
async function handleSetMode(h, args) {
|
|
3643
|
-
const provider = h.getProvider();
|
|
3655
|
+
const provider = h.getProvider(args?.agentType);
|
|
3644
3656
|
const mode = args?.mode || "agent";
|
|
3645
3657
|
if (provider?.category === "acp") {
|
|
3646
|
-
const adapter = h
|
|
3658
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3647
3659
|
if (adapter) {
|
|
3648
3660
|
const acpInstance = adapter._acpInstance;
|
|
3649
3661
|
if (acpInstance && typeof acpInstance.onEvent === "function") {
|
|
@@ -3695,11 +3707,11 @@ async function handleSetMode(h, args) {
|
|
|
3695
3707
|
return { success: false, error: `setMode '${mode}' not supported by this provider` };
|
|
3696
3708
|
}
|
|
3697
3709
|
async function handleChangeModel(h, args) {
|
|
3698
|
-
const provider = h.getProvider();
|
|
3710
|
+
const provider = h.getProvider(args?.agentType);
|
|
3699
3711
|
const model = args?.model;
|
|
3700
3712
|
LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} ideType=${h.currentIdeType} providerType=${h.currentProviderType}`);
|
|
3701
3713
|
if (provider?.category === "acp") {
|
|
3702
|
-
const adapter = h
|
|
3714
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3703
3715
|
LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
|
|
3704
3716
|
if (adapter) {
|
|
3705
3717
|
const acpInstance = adapter._acpInstance;
|
|
@@ -3756,11 +3768,11 @@ async function handleSetThoughtLevel(h, args) {
|
|
|
3756
3768
|
const configId = args?.configId;
|
|
3757
3769
|
const value = args?.value;
|
|
3758
3770
|
if (!configId || !value) return { success: false, error: "configId and value required" };
|
|
3759
|
-
const provider = h.getProvider();
|
|
3771
|
+
const provider = h.getProvider(args?.agentType);
|
|
3760
3772
|
if (!provider || provider.category !== "acp") {
|
|
3761
3773
|
return { success: false, error: "set_thought_level only for ACP providers" };
|
|
3762
3774
|
}
|
|
3763
|
-
const adapter = h
|
|
3775
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3764
3776
|
const acpInstance = adapter?._acpInstance;
|
|
3765
3777
|
if (!acpInstance) return { success: false, error: "ACP instance not found" };
|
|
3766
3778
|
try {
|
|
@@ -3772,13 +3784,22 @@ async function handleSetThoughtLevel(h, args) {
|
|
|
3772
3784
|
}
|
|
3773
3785
|
}
|
|
3774
3786
|
async function handleResolveAction(h, args) {
|
|
3775
|
-
const provider = h.getProvider();
|
|
3787
|
+
const provider = h.getProvider(args?.agentType);
|
|
3776
3788
|
const action = args?.action || "approve";
|
|
3777
3789
|
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
3778
3790
|
LOG.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
|
|
3779
3791
|
if (provider?.category === "cli") {
|
|
3780
|
-
const adapter = h
|
|
3792
|
+
const adapter = getTargetedCliAdapter(h, args, provider.type);
|
|
3781
3793
|
if (!adapter) return { success: false, error: "CLI adapter not running" };
|
|
3794
|
+
if (args?.data && typeof adapter.resolveAction === "function") {
|
|
3795
|
+
try {
|
|
3796
|
+
await adapter.resolveAction(args.data);
|
|
3797
|
+
LOG.info("Command", `[resolveAction] CLI PTY \u2192 resolveAction triggered with data payload`);
|
|
3798
|
+
return { success: true, method: "cli-resolve-action" };
|
|
3799
|
+
} catch (e) {
|
|
3800
|
+
return { success: false, error: `CLI resolveAction failed: ${e.message}` };
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3782
3803
|
const status = adapter.getStatus?.();
|
|
3783
3804
|
if (status?.status !== "waiting_approval") {
|
|
3784
3805
|
return { success: false, error: "Not in approval state" };
|
|
@@ -5830,7 +5851,7 @@ var init_provider_loader = __esm({
|
|
|
5830
5851
|
// ─── Private ───────────────────────────────────
|
|
5831
5852
|
/**
|
|
5832
5853
|
* Find the on-disk directory for a provider by type.
|
|
5833
|
-
*
|
|
5854
|
+
* Canonical shape: root/category/type.
|
|
5834
5855
|
*/
|
|
5835
5856
|
findProviderDirInternal(type) {
|
|
5836
5857
|
const provider = this.providers.get(type);
|
|
@@ -5839,9 +5860,8 @@ var init_provider_loader = __esm({
|
|
|
5839
5860
|
const searchRoots = this.getProviderRoots();
|
|
5840
5861
|
for (const root of searchRoots) {
|
|
5841
5862
|
if (!fs5.existsSync(root)) continue;
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
}
|
|
5863
|
+
const candidate = this.getProviderDir(root, cat, type);
|
|
5864
|
+
if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
|
|
5845
5865
|
const catDir = path6.join(root, cat);
|
|
5846
5866
|
if (fs5.existsSync(catDir)) {
|
|
5847
5867
|
try {
|
|
@@ -6016,8 +6036,9 @@ var init_provider_loader = __esm({
|
|
|
6016
6036
|
}
|
|
6017
6037
|
}
|
|
6018
6038
|
compareVersions(a, b) {
|
|
6019
|
-
const
|
|
6020
|
-
const
|
|
6039
|
+
const normalize2 = (v) => v.split(/[-_+]/)[0].split(".").map((x) => parseInt(x, 10) || 0);
|
|
6040
|
+
const pa = normalize2(a);
|
|
6041
|
+
const pb = normalize2(b);
|
|
6021
6042
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
6022
6043
|
const va = pa[i] || 0;
|
|
6023
6044
|
const vb = pb[i] || 0;
|
|
@@ -7041,6 +7062,246 @@ var init_reporter = __esm({
|
|
|
7041
7062
|
}
|
|
7042
7063
|
});
|
|
7043
7064
|
|
|
7065
|
+
// ../daemon-core/src/cli-adapters/terminal-screen.ts
|
|
7066
|
+
function clamp(value, min, max) {
|
|
7067
|
+
return Math.max(min, Math.min(max, value));
|
|
7068
|
+
}
|
|
7069
|
+
var TerminalScreen;
|
|
7070
|
+
var init_terminal_screen = __esm({
|
|
7071
|
+
"../daemon-core/src/cli-adapters/terminal-screen.ts"() {
|
|
7072
|
+
"use strict";
|
|
7073
|
+
TerminalScreen = class {
|
|
7074
|
+
rows;
|
|
7075
|
+
cols;
|
|
7076
|
+
cursorRow = 0;
|
|
7077
|
+
cursorCol = 0;
|
|
7078
|
+
savedRow = 0;
|
|
7079
|
+
savedCol = 0;
|
|
7080
|
+
lines;
|
|
7081
|
+
constructor(rows = 40, cols = 120) {
|
|
7082
|
+
this.rows = rows;
|
|
7083
|
+
this.cols = cols;
|
|
7084
|
+
this.lines = this.makeLines(rows, cols);
|
|
7085
|
+
}
|
|
7086
|
+
reset(rows = this.rows, cols = this.cols) {
|
|
7087
|
+
this.rows = rows;
|
|
7088
|
+
this.cols = cols;
|
|
7089
|
+
this.cursorRow = 0;
|
|
7090
|
+
this.cursorCol = 0;
|
|
7091
|
+
this.savedRow = 0;
|
|
7092
|
+
this.savedCol = 0;
|
|
7093
|
+
this.lines = this.makeLines(rows, cols);
|
|
7094
|
+
}
|
|
7095
|
+
resize(rows, cols) {
|
|
7096
|
+
const nextRows = Math.max(1, rows | 0);
|
|
7097
|
+
const nextCols = Math.max(1, cols | 0);
|
|
7098
|
+
const next = this.makeLines(nextRows, nextCols);
|
|
7099
|
+
const copyRows = Math.min(this.rows, nextRows);
|
|
7100
|
+
const copyCols = Math.min(this.cols, nextCols);
|
|
7101
|
+
for (let r = 0; r < copyRows; r++) {
|
|
7102
|
+
for (let c = 0; c < copyCols; c++) {
|
|
7103
|
+
next[r][c] = this.lines[r][c];
|
|
7104
|
+
}
|
|
7105
|
+
}
|
|
7106
|
+
this.rows = nextRows;
|
|
7107
|
+
this.cols = nextCols;
|
|
7108
|
+
this.lines = next;
|
|
7109
|
+
this.cursorRow = clamp(this.cursorRow, 0, this.rows - 1);
|
|
7110
|
+
this.cursorCol = clamp(this.cursorCol, 0, this.cols - 1);
|
|
7111
|
+
this.savedRow = clamp(this.savedRow, 0, this.rows - 1);
|
|
7112
|
+
this.savedCol = clamp(this.savedCol, 0, this.cols - 1);
|
|
7113
|
+
}
|
|
7114
|
+
write(data) {
|
|
7115
|
+
let i = 0;
|
|
7116
|
+
while (i < data.length) {
|
|
7117
|
+
const ch = data[i];
|
|
7118
|
+
if (ch === "\x1B") {
|
|
7119
|
+
const consumed = this.consumeEscape(data, i);
|
|
7120
|
+
i = consumed > i ? consumed : i + 1;
|
|
7121
|
+
continue;
|
|
7122
|
+
}
|
|
7123
|
+
if (ch === "\r") {
|
|
7124
|
+
this.cursorCol = 0;
|
|
7125
|
+
i++;
|
|
7126
|
+
continue;
|
|
7127
|
+
}
|
|
7128
|
+
if (ch === "\n") {
|
|
7129
|
+
this.newLine();
|
|
7130
|
+
i++;
|
|
7131
|
+
continue;
|
|
7132
|
+
}
|
|
7133
|
+
if (ch === "\b") {
|
|
7134
|
+
this.cursorCol = Math.max(0, this.cursorCol - 1);
|
|
7135
|
+
i++;
|
|
7136
|
+
continue;
|
|
7137
|
+
}
|
|
7138
|
+
if (ch === " ") {
|
|
7139
|
+
const nextStop = Math.min(this.cols - 1, this.cursorCol + (8 - (this.cursorCol % 8 || 8)));
|
|
7140
|
+
while (this.cursorCol < nextStop) this.putChar(" ");
|
|
7141
|
+
i++;
|
|
7142
|
+
continue;
|
|
7143
|
+
}
|
|
7144
|
+
if (ch >= " " && ch !== "\x7F") {
|
|
7145
|
+
this.putChar(ch);
|
|
7146
|
+
}
|
|
7147
|
+
i++;
|
|
7148
|
+
}
|
|
7149
|
+
}
|
|
7150
|
+
getText() {
|
|
7151
|
+
const raw = this.lines.map((line) => line.join("").replace(/\s+$/, ""));
|
|
7152
|
+
let start = 0;
|
|
7153
|
+
let end = raw.length;
|
|
7154
|
+
while (start < end && raw[start] === "") start++;
|
|
7155
|
+
while (end > start && raw[end - 1] === "") end--;
|
|
7156
|
+
return raw.slice(start, end).join("\n");
|
|
7157
|
+
}
|
|
7158
|
+
consumeEscape(data, start) {
|
|
7159
|
+
const next = data[start + 1];
|
|
7160
|
+
if (!next) return start + 1;
|
|
7161
|
+
if (next === "[") {
|
|
7162
|
+
let end = start + 2;
|
|
7163
|
+
while (end < data.length && !/[@-~]/.test(data[end])) end++;
|
|
7164
|
+
if (end >= data.length) return data.length;
|
|
7165
|
+
this.applyCsi(data.slice(start + 2, end), data[end]);
|
|
7166
|
+
return end + 1;
|
|
7167
|
+
}
|
|
7168
|
+
if (next === "]") {
|
|
7169
|
+
let end = start + 2;
|
|
7170
|
+
while (end < data.length) {
|
|
7171
|
+
if (data[end] === "\x07") return end + 1;
|
|
7172
|
+
if (data[end] === "\x1B" && data[end + 1] === "\\") return end + 2;
|
|
7173
|
+
end++;
|
|
7174
|
+
}
|
|
7175
|
+
return data.length;
|
|
7176
|
+
}
|
|
7177
|
+
if (next === "7") {
|
|
7178
|
+
this.savedRow = this.cursorRow;
|
|
7179
|
+
this.savedCol = this.cursorCol;
|
|
7180
|
+
return start + 2;
|
|
7181
|
+
}
|
|
7182
|
+
if (next === "8") {
|
|
7183
|
+
this.cursorRow = this.savedRow;
|
|
7184
|
+
this.cursorCol = this.savedCol;
|
|
7185
|
+
return start + 2;
|
|
7186
|
+
}
|
|
7187
|
+
return start + 2;
|
|
7188
|
+
}
|
|
7189
|
+
applyCsi(paramText, finalChar) {
|
|
7190
|
+
const privateMode = paramText.startsWith("?");
|
|
7191
|
+
const normalized = privateMode ? paramText.slice(1) : paramText;
|
|
7192
|
+
const params = normalized.length > 0 ? normalized.split(";").map((p) => parseInt(p || "0", 10) || 0) : [0];
|
|
7193
|
+
switch (finalChar) {
|
|
7194
|
+
case "A":
|
|
7195
|
+
this.cursorRow = clamp(this.cursorRow - (params[0] || 1), 0, this.rows - 1);
|
|
7196
|
+
return;
|
|
7197
|
+
case "B":
|
|
7198
|
+
this.cursorRow = clamp(this.cursorRow + (params[0] || 1), 0, this.rows - 1);
|
|
7199
|
+
return;
|
|
7200
|
+
case "C":
|
|
7201
|
+
this.cursorCol = clamp(this.cursorCol + (params[0] || 1), 0, this.cols - 1);
|
|
7202
|
+
return;
|
|
7203
|
+
case "D":
|
|
7204
|
+
this.cursorCol = clamp(this.cursorCol - (params[0] || 1), 0, this.cols - 1);
|
|
7205
|
+
return;
|
|
7206
|
+
case "E":
|
|
7207
|
+
this.cursorRow = clamp(this.cursorRow + (params[0] || 1), 0, this.rows - 1);
|
|
7208
|
+
this.cursorCol = 0;
|
|
7209
|
+
return;
|
|
7210
|
+
case "F":
|
|
7211
|
+
this.cursorRow = clamp(this.cursorRow - (params[0] || 1), 0, this.rows - 1);
|
|
7212
|
+
this.cursorCol = 0;
|
|
7213
|
+
return;
|
|
7214
|
+
case "G":
|
|
7215
|
+
this.cursorCol = clamp((params[0] || 1) - 1, 0, this.cols - 1);
|
|
7216
|
+
return;
|
|
7217
|
+
case "H":
|
|
7218
|
+
case "f": {
|
|
7219
|
+
const row = (params[0] || 1) - 1;
|
|
7220
|
+
const col = (params[1] || 1) - 1;
|
|
7221
|
+
this.cursorRow = clamp(row, 0, this.rows - 1);
|
|
7222
|
+
this.cursorCol = clamp(col, 0, this.cols - 1);
|
|
7223
|
+
return;
|
|
7224
|
+
}
|
|
7225
|
+
case "J": {
|
|
7226
|
+
const mode = params[0] || 0;
|
|
7227
|
+
if (mode === 2 || mode === 3) {
|
|
7228
|
+
this.reset(this.rows, this.cols);
|
|
7229
|
+
} else if (mode === 0) {
|
|
7230
|
+
this.clearToEndOfScreen();
|
|
7231
|
+
} else if (mode === 1) {
|
|
7232
|
+
this.clearToStartOfScreen();
|
|
7233
|
+
}
|
|
7234
|
+
return;
|
|
7235
|
+
}
|
|
7236
|
+
case "K": {
|
|
7237
|
+
const mode = params[0] || 0;
|
|
7238
|
+
if (mode === 2) this.clearLine(this.cursorRow, 0, this.cols - 1);
|
|
7239
|
+
else if (mode === 1) this.clearLine(this.cursorRow, 0, this.cursorCol);
|
|
7240
|
+
else this.clearLine(this.cursorRow, this.cursorCol, this.cols - 1);
|
|
7241
|
+
return;
|
|
7242
|
+
}
|
|
7243
|
+
case "m":
|
|
7244
|
+
return;
|
|
7245
|
+
case "s":
|
|
7246
|
+
this.savedRow = this.cursorRow;
|
|
7247
|
+
this.savedCol = this.cursorCol;
|
|
7248
|
+
return;
|
|
7249
|
+
case "u":
|
|
7250
|
+
this.cursorRow = this.savedRow;
|
|
7251
|
+
this.cursorCol = this.savedCol;
|
|
7252
|
+
return;
|
|
7253
|
+
case "h":
|
|
7254
|
+
case "l":
|
|
7255
|
+
if (privateMode && (normalized === "1049" || normalized === "47")) {
|
|
7256
|
+
this.reset(this.rows, this.cols);
|
|
7257
|
+
}
|
|
7258
|
+
return;
|
|
7259
|
+
default:
|
|
7260
|
+
return;
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
putChar(ch) {
|
|
7264
|
+
if (this.cursorRow < 0 || this.cursorRow >= this.rows) return;
|
|
7265
|
+
if (this.cursorCol < 0) this.cursorCol = 0;
|
|
7266
|
+
if (this.cursorCol >= this.cols) this.newLine();
|
|
7267
|
+
this.lines[this.cursorRow][this.cursorCol] = ch;
|
|
7268
|
+
this.cursorCol++;
|
|
7269
|
+
if (this.cursorCol >= this.cols) this.newLine();
|
|
7270
|
+
}
|
|
7271
|
+
newLine() {
|
|
7272
|
+
this.cursorCol = 0;
|
|
7273
|
+
if (this.cursorRow >= this.rows - 1) {
|
|
7274
|
+
this.lines.shift();
|
|
7275
|
+
this.lines.push(Array.from({ length: this.cols }, () => " "));
|
|
7276
|
+
} else {
|
|
7277
|
+
this.cursorRow++;
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
clearLine(row, start, end) {
|
|
7281
|
+
if (row < 0 || row >= this.rows) return;
|
|
7282
|
+
for (let c = clamp(start, 0, this.cols - 1); c <= clamp(end, 0, this.cols - 1); c++) {
|
|
7283
|
+
this.lines[row][c] = " ";
|
|
7284
|
+
}
|
|
7285
|
+
}
|
|
7286
|
+
clearToEndOfScreen() {
|
|
7287
|
+
this.clearLine(this.cursorRow, this.cursorCol, this.cols - 1);
|
|
7288
|
+
for (let r = this.cursorRow + 1; r < this.rows; r++) {
|
|
7289
|
+
this.clearLine(r, 0, this.cols - 1);
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
clearToStartOfScreen() {
|
|
7293
|
+
for (let r = 0; r < this.cursorRow; r++) {
|
|
7294
|
+
this.clearLine(r, 0, this.cols - 1);
|
|
7295
|
+
}
|
|
7296
|
+
this.clearLine(this.cursorRow, 0, this.cursorCol);
|
|
7297
|
+
}
|
|
7298
|
+
makeLines(rows, cols) {
|
|
7299
|
+
return Array.from({ length: rows }, () => Array.from({ length: cols }, () => " "));
|
|
7300
|
+
}
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
});
|
|
7304
|
+
|
|
7044
7305
|
// ../daemon-core/src/cli-adapters/provider-cli-adapter.ts
|
|
7045
7306
|
var provider_cli_adapter_exports = {};
|
|
7046
7307
|
__export(provider_cli_adapter_exports, {
|
|
@@ -7113,28 +7374,19 @@ function parsePatternEntry(x) {
|
|
|
7113
7374
|
}
|
|
7114
7375
|
return null;
|
|
7115
7376
|
}
|
|
7116
|
-
function coercePatternArray(raw
|
|
7117
|
-
if (!Array.isArray(raw)) return [
|
|
7118
|
-
|
|
7119
|
-
return parsed.length > 0 ? parsed : [...fallbacks];
|
|
7120
|
-
}
|
|
7121
|
-
function defaultCleanOutput(raw, _lastUserInput) {
|
|
7122
|
-
return stripAnsi(raw).trim();
|
|
7377
|
+
function coercePatternArray(raw) {
|
|
7378
|
+
if (!Array.isArray(raw)) return [];
|
|
7379
|
+
return raw.map(parsePatternEntry).filter((r) => r != null);
|
|
7123
7380
|
}
|
|
7124
7381
|
function normalizeCliProviderForRuntime(raw) {
|
|
7125
7382
|
const patterns = raw?.patterns || {};
|
|
7126
7383
|
return {
|
|
7127
|
-
...raw,
|
|
7128
7384
|
patterns: {
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
|
|
7132
|
-
ready: coercePatternArray(patterns.ready, [])
|
|
7133
|
-
},
|
|
7134
|
-
cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
|
|
7385
|
+
approval: coercePatternArray(patterns.approval)
|
|
7386
|
+
}
|
|
7135
7387
|
};
|
|
7136
7388
|
}
|
|
7137
|
-
var os11, path9, import_child_process5, pty,
|
|
7389
|
+
var os11, path9, import_child_process5, pty, ProviderCliAdapter;
|
|
7138
7390
|
var init_provider_cli_adapter = __esm({
|
|
7139
7391
|
"../daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
|
|
7140
7392
|
"use strict";
|
|
@@ -7142,6 +7394,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7142
7394
|
path9 = __toESM(require("path"));
|
|
7143
7395
|
import_child_process5 = require("child_process");
|
|
7144
7396
|
init_logger();
|
|
7397
|
+
init_terminal_screen();
|
|
7145
7398
|
try {
|
|
7146
7399
|
pty = require("node-pty");
|
|
7147
7400
|
if (os11.platform() !== "win32") {
|
|
@@ -7163,40 +7416,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7163
7416
|
} catch {
|
|
7164
7417
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
|
|
7165
7418
|
}
|
|
7166
|
-
|
|
7167
|
-
/Type your message/i,
|
|
7168
|
-
/for\s*shortcuts/i,
|
|
7169
|
-
// Claude Code prompt
|
|
7170
|
-
/\?\s*for\s*help/i,
|
|
7171
|
-
// Claude Code help prompt
|
|
7172
|
-
/Press enter/i,
|
|
7173
|
-
/^[>›❯]\s*$/i,
|
|
7174
|
-
// Prompt char as the complete evaluated string
|
|
7175
|
-
/[>›❯]\s*$/
|
|
7176
|
-
// Prompt char at the very end of evaluated string
|
|
7177
|
-
];
|
|
7178
|
-
FALLBACK_GENERATING = [
|
|
7179
|
-
/[\u2800-\u28ff]/,
|
|
7180
|
-
// Braille spinner blocks (universal TUI)
|
|
7181
|
-
/esc to (cancel|interrupt|stop)/i,
|
|
7182
|
-
// Common TUI generation status line
|
|
7183
|
-
/generating\.\.\./i,
|
|
7184
|
-
/Claude is (?:thinking|processing|working)/i
|
|
7185
|
-
// Specific Claude Code status
|
|
7186
|
-
];
|
|
7187
|
-
FALLBACK_APPROVAL = [
|
|
7188
|
-
/Allow\s*once/i,
|
|
7189
|
-
// ANSI strip may remove spaces
|
|
7190
|
-
/Always\s*allow/i,
|
|
7191
|
-
/\(y\/n\)/i,
|
|
7192
|
-
/\[Y\/n\]/i,
|
|
7193
|
-
/Yes,?\s*don'?t\s*ask/i
|
|
7194
|
-
// "Yes, don't ask again" (Claude Code)
|
|
7195
|
-
];
|
|
7196
|
-
ProviderCliAdapter = class {
|
|
7419
|
+
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
7197
7420
|
constructor(provider, workingDir, extraArgs = []) {
|
|
7198
7421
|
this.extraArgs = extraArgs;
|
|
7199
|
-
this.provider =
|
|
7422
|
+
this.provider = provider;
|
|
7200
7423
|
this.cliType = provider.type;
|
|
7201
7424
|
this.cliName = provider.name;
|
|
7202
7425
|
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
|
|
@@ -7213,6 +7436,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
7213
7436
|
};
|
|
7214
7437
|
const rawKeys = provider.approvalKeys;
|
|
7215
7438
|
this.approvalKeys = rawKeys && typeof rawKeys === "object" ? rawKeys : {};
|
|
7439
|
+
this.cliScripts = provider.scripts || {};
|
|
7440
|
+
const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
|
|
7441
|
+
if (scriptNames.length > 0) {
|
|
7442
|
+
LOG.info("CLI", `[${this.cliType}] CLI scripts: [${scriptNames.join(", ")}]`);
|
|
7443
|
+
} else {
|
|
7444
|
+
LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
|
|
7445
|
+
}
|
|
7216
7446
|
}
|
|
7217
7447
|
cliType;
|
|
7218
7448
|
cliName;
|
|
@@ -7220,6 +7450,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7220
7450
|
provider;
|
|
7221
7451
|
ptyProcess = null;
|
|
7222
7452
|
messages = [];
|
|
7453
|
+
structuredMessages = [];
|
|
7223
7454
|
currentStatus = "starting";
|
|
7224
7455
|
onStatusChange = null;
|
|
7225
7456
|
responseBuffer = "";
|
|
@@ -7230,7 +7461,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
7230
7461
|
idleTimeout = null;
|
|
7231
7462
|
ready = false;
|
|
7232
7463
|
startupBuffer = "";
|
|
7233
|
-
/** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
|
|
7234
7464
|
startupParseGate = false;
|
|
7235
7465
|
spawnAt = 0;
|
|
7236
7466
|
// PTY I/O
|
|
@@ -7248,11 +7478,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7248
7478
|
// Output settle debounce — fires after PTY output goes quiet
|
|
7249
7479
|
settleTimer = null;
|
|
7250
7480
|
settledBuffer = "";
|
|
7251
|
-
// snapshot of recentOutputBuffer at settle time
|
|
7252
7481
|
// Resize redraw suppression
|
|
7253
7482
|
resizeSuppressUntil = 0;
|
|
7254
7483
|
// Debug: status transition history
|
|
7255
7484
|
statusHistory = [];
|
|
7485
|
+
// ─── CLI Scripts (script-based parsing) ───
|
|
7486
|
+
cliScripts;
|
|
7487
|
+
/** Full accumulated ANSI-stripped PTY output */
|
|
7488
|
+
accumulatedBuffer = "";
|
|
7489
|
+
/** Full accumulated raw PTY output (with ANSI) */
|
|
7490
|
+
accumulatedRawBuffer = "";
|
|
7491
|
+
/** Current visible terminal screen snapshot */
|
|
7492
|
+
terminalScreen = new TerminalScreen(40, 120);
|
|
7493
|
+
/** Max accumulated buffer size (last 50KB) */
|
|
7494
|
+
static MAX_ACCUMULATED_BUFFER = 5e4;
|
|
7256
7495
|
setStatus(status, trigger) {
|
|
7257
7496
|
const prev = this.currentStatus;
|
|
7258
7497
|
if (prev === status) return;
|
|
@@ -7261,10 +7500,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
7261
7500
|
if (this.statusHistory.length > 50) this.statusHistory.shift();
|
|
7262
7501
|
LOG.info("CLI", `[${this.cliType}] status: ${prev} \u2192 ${status}${trigger ? ` (${trigger})` : ""}`);
|
|
7263
7502
|
}
|
|
7264
|
-
// Resolved timeouts
|
|
7503
|
+
// Resolved timeouts
|
|
7265
7504
|
timeouts;
|
|
7266
|
-
// Provider approval key mapping
|
|
7505
|
+
// Provider approval key mapping
|
|
7267
7506
|
approvalKeys;
|
|
7507
|
+
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
7508
|
+
setCliScripts(scripts) {
|
|
7509
|
+
this.cliScripts = scripts;
|
|
7510
|
+
const scriptNames = Object.keys(scripts).filter((k) => typeof scripts[k] === "function");
|
|
7511
|
+
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
7512
|
+
}
|
|
7268
7513
|
// ─── Lifecycle ─────────────────────────────────
|
|
7269
7514
|
setServerConn(serverConn) {
|
|
7270
7515
|
this.serverConn = serverConn;
|
|
@@ -7353,15 +7598,19 @@ var init_provider_cli_adapter = __esm({
|
|
|
7353
7598
|
this.spawnAt = Date.now();
|
|
7354
7599
|
this.startupParseGate = true;
|
|
7355
7600
|
this.startupBuffer = "";
|
|
7601
|
+
this.terminalScreen.reset(40, 120);
|
|
7356
7602
|
this.ready = true;
|
|
7357
7603
|
this.setStatus("idle", "pty_ready");
|
|
7358
7604
|
this.onStatusChange?.();
|
|
7359
7605
|
}
|
|
7360
|
-
// ─── Output
|
|
7606
|
+
// ─── Output Handling ────────────────────────────
|
|
7361
7607
|
handleOutput(rawData) {
|
|
7362
7608
|
if (Date.now() < this.resizeSuppressUntil) return;
|
|
7609
|
+
this.terminalScreen.write(rawData);
|
|
7363
7610
|
const cleanData = stripAnsi(rawData);
|
|
7364
|
-
|
|
7611
|
+
if (this.isWaitingForResponse && cleanData) {
|
|
7612
|
+
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
7613
|
+
}
|
|
7365
7614
|
if (cleanData.trim()) {
|
|
7366
7615
|
if (this.serverConn) {
|
|
7367
7616
|
this.serverConn.sendMessage("log", { message: cleanData.trim(), level: "info" });
|
|
@@ -7370,9 +7619,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7370
7619
|
}
|
|
7371
7620
|
}
|
|
7372
7621
|
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
7622
|
+
this.accumulatedBuffer = (this.accumulatedBuffer + cleanData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
7623
|
+
this.accumulatedRawBuffer = (this.accumulatedRawBuffer + rawData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
7373
7624
|
if (this.startupParseGate) {
|
|
7374
7625
|
this.startupBuffer += cleanData;
|
|
7375
|
-
LOG.info("CLI", `[${this.cliType}] startup chunk (${cleanData.length} chars): ${cleanData.slice(0, 200).replace(/\n/g, "\\n")}`);
|
|
7376
7626
|
const dialogPatterns = [
|
|
7377
7627
|
/Do you want to connect/i,
|
|
7378
7628
|
/Do you trust the files/i,
|
|
@@ -7387,60 +7637,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
7387
7637
|
}
|
|
7388
7638
|
const elapsed = Date.now() - this.spawnAt;
|
|
7389
7639
|
const bufCap = this.startupBuffer.length > 12e3;
|
|
7390
|
-
const
|
|
7391
|
-
|
|
7640
|
+
const scriptStatus = this.runDetectStatus(this.startupBuffer);
|
|
7641
|
+
const isReady = scriptStatus === "idle" || elapsed > 8e3 || bufCap;
|
|
7642
|
+
if (isReady) {
|
|
7392
7643
|
this.startupParseGate = false;
|
|
7393
|
-
|
|
7394
|
-
LOG.info("CLI", `[${this.cliType}] \u2713 Startup gate end (prompt matched)`);
|
|
7395
|
-
} else {
|
|
7396
|
-
LOG.info("CLI", `[${this.cliType}] startup gate end (${elapsed}ms, cap=${bufCap}, prompt=${promptMatched})`);
|
|
7397
|
-
}
|
|
7644
|
+
LOG.info("CLI", `[${this.cliType}] Startup gate end (${elapsed}ms, scriptStatus=${scriptStatus})`);
|
|
7398
7645
|
} else {
|
|
7399
7646
|
return;
|
|
7400
7647
|
}
|
|
7401
7648
|
}
|
|
7402
|
-
if (cleanData.trim().length > 5) {
|
|
7403
|
-
LOG.debug("CLI", `[${this.cliType}] output chunk (${cleanData.length}): ${cleanData.slice(0, 300).replace(/\n/g, "\\n")}`);
|
|
7404
|
-
}
|
|
7405
|
-
if (!this.isWaitingForResponse) {
|
|
7406
|
-
if (patterns.generating.some((p) => p.test(cleanData))) {
|
|
7407
|
-
if (this.settleTimer) {
|
|
7408
|
-
clearTimeout(this.settleTimer);
|
|
7409
|
-
this.settleTimer = null;
|
|
7410
|
-
}
|
|
7411
|
-
this.isWaitingForResponse = true;
|
|
7412
|
-
this.responseBuffer = "";
|
|
7413
|
-
this.setStatus("generating", "autonomous_gen");
|
|
7414
|
-
this.onStatusChange?.();
|
|
7415
|
-
}
|
|
7416
|
-
}
|
|
7417
|
-
if (this.isWaitingForResponse) {
|
|
7418
|
-
this.responseBuffer += cleanData;
|
|
7419
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
7420
|
-
if (patterns.generating.some((p) => p.test(cleanData))) {
|
|
7421
|
-
this.setStatus("generating", "still_generating");
|
|
7422
|
-
this.idleTimeout = setTimeout(() => {
|
|
7423
|
-
if (this.isWaitingForResponse) this.finishResponse();
|
|
7424
|
-
}, this.timeouts.generatingIdle);
|
|
7425
|
-
this.onStatusChange?.();
|
|
7426
|
-
if (this.settleTimer) {
|
|
7427
|
-
clearTimeout(this.settleTimer);
|
|
7428
|
-
this.settleTimer = null;
|
|
7429
|
-
}
|
|
7430
|
-
return;
|
|
7431
|
-
}
|
|
7432
|
-
}
|
|
7433
|
-
if (this.currentStatus === "waiting_approval") {
|
|
7434
|
-
this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
|
|
7435
|
-
this.scheduleSettle();
|
|
7436
|
-
return;
|
|
7437
|
-
}
|
|
7438
7649
|
this.scheduleSettle();
|
|
7439
7650
|
}
|
|
7440
|
-
/**
|
|
7441
|
-
* Fired after output goes quiet for outputSettle ms.
|
|
7442
|
-
* Evaluates the stabilised buffer for approval, prompt (idle), or timeout.
|
|
7443
|
-
*/
|
|
7444
7651
|
scheduleSettle() {
|
|
7445
7652
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
7446
7653
|
this.settleTimer = setTimeout(() => {
|
|
@@ -7450,59 +7657,25 @@ var init_provider_cli_adapter = __esm({
|
|
|
7450
7657
|
}, this.timeouts.outputSettle);
|
|
7451
7658
|
}
|
|
7452
7659
|
evaluateSettled() {
|
|
7453
|
-
const
|
|
7454
|
-
const
|
|
7455
|
-
if (
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
if (genResume) {
|
|
7459
|
-
if (this.approvalExitTimeout) {
|
|
7460
|
-
clearTimeout(this.approvalExitTimeout);
|
|
7461
|
-
this.approvalExitTimeout = null;
|
|
7462
|
-
}
|
|
7463
|
-
this.setStatus("generating", "approval_gen_resume");
|
|
7464
|
-
this.activeModal = null;
|
|
7465
|
-
this.recentOutputBuffer = "";
|
|
7466
|
-
this.approvalTransitionBuffer = "";
|
|
7467
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
7468
|
-
this.onStatusChange?.();
|
|
7469
|
-
} else if (promptResume) {
|
|
7470
|
-
if (this.approvalExitTimeout) {
|
|
7471
|
-
clearTimeout(this.approvalExitTimeout);
|
|
7472
|
-
this.approvalExitTimeout = null;
|
|
7473
|
-
}
|
|
7474
|
-
this.activeModal = null;
|
|
7475
|
-
this.recentOutputBuffer = "";
|
|
7476
|
-
this.approvalTransitionBuffer = "";
|
|
7477
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
7478
|
-
this.finishResponse();
|
|
7479
|
-
}
|
|
7480
|
-
return;
|
|
7481
|
-
}
|
|
7482
|
-
const hasApproval = patterns.approval.some((p) => p.test(buf));
|
|
7483
|
-
if (hasApproval) {
|
|
7660
|
+
const tail = this.settledBuffer;
|
|
7661
|
+
const scriptStatus = this.runDetectStatus(tail);
|
|
7662
|
+
if (!scriptStatus) return;
|
|
7663
|
+
const prevStatus = this.currentStatus;
|
|
7664
|
+
if (scriptStatus === "waiting_approval") {
|
|
7484
7665
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
7485
7666
|
if (!inCooldown) {
|
|
7486
|
-
const ctxLines = buf.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
7487
7667
|
this.isWaitingForResponse = true;
|
|
7488
|
-
this.setStatus("waiting_approval", "
|
|
7489
|
-
|
|
7490
|
-
this.
|
|
7491
|
-
this.activeModal = {
|
|
7492
|
-
message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
|
|
7493
|
-
buttons: this.cliType === "claude-cli" ? ["Yes (y)", "Always allow (a)", "Deny (Esc)"] : ["Allow once", "Always allow", "Deny"]
|
|
7494
|
-
};
|
|
7668
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
7669
|
+
const modal = this.runParseApproval(tail);
|
|
7670
|
+
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
7495
7671
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
7496
7672
|
if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
|
|
7497
7673
|
this.approvalExitTimeout = setTimeout(() => {
|
|
7498
7674
|
if (this.currentStatus === "waiting_approval") {
|
|
7499
|
-
LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-
|
|
7675
|
+
LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-clearing`);
|
|
7500
7676
|
this.activeModal = null;
|
|
7501
7677
|
this.lastApprovalResolvedAt = Date.now();
|
|
7502
|
-
this.
|
|
7503
|
-
this.approvalTransitionBuffer = "";
|
|
7504
|
-
this.approvalExitTimeout = null;
|
|
7505
|
-
this.setStatus(this.isWaitingForResponse ? "generating" : "idle", "approval_cleared");
|
|
7678
|
+
this.setStatus("idle", "approval_timeout");
|
|
7506
7679
|
this.onStatusChange?.();
|
|
7507
7680
|
}
|
|
7508
7681
|
}, 6e4);
|
|
@@ -7510,19 +7683,42 @@ var init_provider_cli_adapter = __esm({
|
|
|
7510
7683
|
return;
|
|
7511
7684
|
}
|
|
7512
7685
|
}
|
|
7513
|
-
if (
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
this.
|
|
7520
|
-
|
|
7521
|
-
this.finishResponse();
|
|
7522
|
-
}
|
|
7523
|
-
}, this.timeouts.idleFinish);
|
|
7686
|
+
if (scriptStatus === "generating") {
|
|
7687
|
+
if (prevStatus === "waiting_approval") {
|
|
7688
|
+
if (this.approvalExitTimeout) {
|
|
7689
|
+
clearTimeout(this.approvalExitTimeout);
|
|
7690
|
+
this.approvalExitTimeout = null;
|
|
7691
|
+
}
|
|
7692
|
+
this.activeModal = null;
|
|
7693
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
7524
7694
|
}
|
|
7695
|
+
if (!this.isWaitingForResponse) {
|
|
7696
|
+
this.isWaitingForResponse = true;
|
|
7697
|
+
this.responseBuffer = "";
|
|
7698
|
+
}
|
|
7699
|
+
this.setStatus("generating", "script_detect");
|
|
7700
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
7701
|
+
this.idleTimeout = setTimeout(() => {
|
|
7702
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
7703
|
+
}, this.timeouts.generatingIdle);
|
|
7525
7704
|
this.onStatusChange?.();
|
|
7705
|
+
return;
|
|
7706
|
+
}
|
|
7707
|
+
if (scriptStatus === "idle") {
|
|
7708
|
+
if (prevStatus === "waiting_approval") {
|
|
7709
|
+
if (this.approvalExitTimeout) {
|
|
7710
|
+
clearTimeout(this.approvalExitTimeout);
|
|
7711
|
+
this.approvalExitTimeout = null;
|
|
7712
|
+
}
|
|
7713
|
+
this.activeModal = null;
|
|
7714
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
7715
|
+
}
|
|
7716
|
+
if (this.isWaitingForResponse) {
|
|
7717
|
+
this.finishResponse();
|
|
7718
|
+
} else if (prevStatus !== "idle") {
|
|
7719
|
+
this.setStatus("idle", "script_detect");
|
|
7720
|
+
this.onStatusChange?.();
|
|
7721
|
+
}
|
|
7526
7722
|
}
|
|
7527
7723
|
}
|
|
7528
7724
|
finishResponse() {
|
|
@@ -7538,25 +7734,50 @@ var init_provider_cli_adapter = __esm({
|
|
|
7538
7734
|
clearTimeout(this.approvalExitTimeout);
|
|
7539
7735
|
this.approvalExitTimeout = null;
|
|
7540
7736
|
}
|
|
7541
|
-
const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
|
|
7542
|
-
let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
|
|
7543
|
-
if (lastUserText && response) {
|
|
7544
|
-
const userTrimmed = lastUserText.trim();
|
|
7545
|
-
response = response.split("\n").filter((l) => l.trim() !== userTrimmed).join("\n").trim();
|
|
7546
|
-
}
|
|
7547
|
-
if (response) {
|
|
7548
|
-
this.messages.push({ role: "assistant", content: response, timestamp: Date.now() });
|
|
7549
|
-
if (this.messages.length > 200) this.messages = this.messages.slice(-200);
|
|
7550
|
-
LOG.info("CLI", `[${this.cliType}] Response (${response.length} chars)`);
|
|
7551
|
-
}
|
|
7552
7737
|
this.responseBuffer = "";
|
|
7553
7738
|
this.isWaitingForResponse = false;
|
|
7554
7739
|
this.activeModal = null;
|
|
7555
7740
|
this.setStatus("idle", "response_finished");
|
|
7556
7741
|
this.onStatusChange?.();
|
|
7557
7742
|
}
|
|
7558
|
-
// ───
|
|
7743
|
+
// ─── Script Execution ──────────────────────────
|
|
7744
|
+
runDetectStatus(text) {
|
|
7745
|
+
if (!this.cliScripts?.detectStatus) return null;
|
|
7746
|
+
try {
|
|
7747
|
+
return this.cliScripts.detectStatus({ tail: text.slice(-500) });
|
|
7748
|
+
} catch (e) {
|
|
7749
|
+
LOG.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
7750
|
+
return null;
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7753
|
+
runParseApproval(tail) {
|
|
7754
|
+
if (!this.cliScripts?.parseApproval) return null;
|
|
7755
|
+
try {
|
|
7756
|
+
return this.cliScripts.parseApproval({
|
|
7757
|
+
buffer: this.terminalScreen.getText() || this.accumulatedBuffer,
|
|
7758
|
+
rawBuffer: this.accumulatedRawBuffer,
|
|
7759
|
+
tail
|
|
7760
|
+
});
|
|
7761
|
+
} catch (e) {
|
|
7762
|
+
LOG.warn("CLI", `[${this.cliType}] parseApproval error: ${e.message}`);
|
|
7763
|
+
return null;
|
|
7764
|
+
}
|
|
7765
|
+
}
|
|
7766
|
+
// ─── Public API (CliAdapter) ───────────────────
|
|
7559
7767
|
getStatus() {
|
|
7768
|
+
const scriptResult = this.getScriptParsedStatus();
|
|
7769
|
+
if (scriptResult) {
|
|
7770
|
+
return {
|
|
7771
|
+
status: this.currentStatus,
|
|
7772
|
+
messages: (scriptResult.messages || []).map((m) => ({
|
|
7773
|
+
role: m.role,
|
|
7774
|
+
content: m.content,
|
|
7775
|
+
timestamp: m.timestamp
|
|
7776
|
+
})),
|
|
7777
|
+
workingDir: this.workingDir,
|
|
7778
|
+
activeModal: this.activeModal
|
|
7779
|
+
};
|
|
7780
|
+
}
|
|
7560
7781
|
return {
|
|
7561
7782
|
status: this.currentStatus,
|
|
7562
7783
|
messages: [...this.messages],
|
|
@@ -7564,11 +7785,71 @@ var init_provider_cli_adapter = __esm({
|
|
|
7564
7785
|
activeModal: this.activeModal
|
|
7565
7786
|
};
|
|
7566
7787
|
}
|
|
7788
|
+
/**
|
|
7789
|
+
* Script-based full parse — returns ReadChatResult.
|
|
7790
|
+
* Called by command handler / dashboard for rich content rendering.
|
|
7791
|
+
*/
|
|
7792
|
+
getScriptParsedStatus() {
|
|
7793
|
+
if (!this.cliScripts?.parseOutput) return null;
|
|
7794
|
+
try {
|
|
7795
|
+
const input = {
|
|
7796
|
+
buffer: this.accumulatedBuffer,
|
|
7797
|
+
rawBuffer: this.accumulatedRawBuffer,
|
|
7798
|
+
recentBuffer: this.recentOutputBuffer,
|
|
7799
|
+
screenText: this.terminalScreen.getText(),
|
|
7800
|
+
messages: [...this.structuredMessages.length > 0 ? this.structuredMessages : this.messages],
|
|
7801
|
+
partialResponse: this.responseBuffer
|
|
7802
|
+
};
|
|
7803
|
+
const result = this.cliScripts.parseOutput(input);
|
|
7804
|
+
if (result && typeof result === "object") {
|
|
7805
|
+
if (Array.isArray(result.messages)) {
|
|
7806
|
+
this.structuredMessages = result.messages.map((m) => ({
|
|
7807
|
+
role: m.role,
|
|
7808
|
+
content: m.content,
|
|
7809
|
+
timestamp: m.timestamp
|
|
7810
|
+
}));
|
|
7811
|
+
}
|
|
7812
|
+
return result;
|
|
7813
|
+
}
|
|
7814
|
+
} catch (e) {
|
|
7815
|
+
LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
|
|
7816
|
+
}
|
|
7817
|
+
return null;
|
|
7818
|
+
}
|
|
7819
|
+
/** Whether this adapter has CLI scripts loaded */
|
|
7820
|
+
hasCliScripts() {
|
|
7821
|
+
return typeof this.cliScripts?.detectStatus === "function";
|
|
7822
|
+
}
|
|
7823
|
+
/**
|
|
7824
|
+
* Resolves an action (like 'fix' lint error) from the dashboard.
|
|
7825
|
+
* Uses resolveAction script if available, otherwise falls back to standard text.
|
|
7826
|
+
*/
|
|
7827
|
+
async resolveAction(data) {
|
|
7828
|
+
let promptText = "";
|
|
7829
|
+
if (this.cliScripts && typeof this.cliScripts.resolveAction === "function") {
|
|
7830
|
+
try {
|
|
7831
|
+
promptText = this.cliScripts.resolveAction(data);
|
|
7832
|
+
} catch (e) {
|
|
7833
|
+
LOG.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
|
|
7834
|
+
}
|
|
7835
|
+
}
|
|
7836
|
+
if (!promptText && data) {
|
|
7837
|
+
promptText = `Please fix the following issue:
|
|
7838
|
+
${data.title || ""}
|
|
7839
|
+
${data.explanation || ""}
|
|
7840
|
+
|
|
7841
|
+
${data.message || ""}`.trim();
|
|
7842
|
+
}
|
|
7843
|
+
if (promptText) {
|
|
7844
|
+
await this.sendMessage(promptText);
|
|
7845
|
+
}
|
|
7846
|
+
}
|
|
7567
7847
|
async sendMessage(text) {
|
|
7568
7848
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
7569
7849
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
7570
7850
|
if (this.isWaitingForResponse) return;
|
|
7571
7851
|
this.messages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
7852
|
+
this.structuredMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
7572
7853
|
this.isWaitingForResponse = true;
|
|
7573
7854
|
this.responseBuffer = "";
|
|
7574
7855
|
this.setStatus("generating", "sendMessage");
|
|
@@ -7580,8 +7861,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7580
7861
|
}
|
|
7581
7862
|
getPartialResponse() {
|
|
7582
7863
|
if (!this.isWaitingForResponse) return "";
|
|
7583
|
-
|
|
7584
|
-
return partial2 || (this.isWaitingForResponse ? "(generating...)" : "");
|
|
7864
|
+
return this.responseBuffer;
|
|
7585
7865
|
}
|
|
7586
7866
|
cancel() {
|
|
7587
7867
|
this.shutdown();
|
|
@@ -7613,6 +7893,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7613
7893
|
}
|
|
7614
7894
|
clearHistory() {
|
|
7615
7895
|
this.messages = [];
|
|
7896
|
+
this.structuredMessages = [];
|
|
7897
|
+
this.accumulatedBuffer = "";
|
|
7898
|
+
this.accumulatedRawBuffer = "";
|
|
7899
|
+
this.terminalScreen.reset();
|
|
7616
7900
|
this.onStatusChange?.();
|
|
7617
7901
|
}
|
|
7618
7902
|
isProcessing() {
|
|
@@ -7624,11 +7908,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
7624
7908
|
writeRaw(data) {
|
|
7625
7909
|
this.ptyProcess?.write(data);
|
|
7626
7910
|
}
|
|
7627
|
-
/**
|
|
7628
|
-
* Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
|
|
7629
|
-
* Index 0 = first option (already selected by default — just Enter).
|
|
7630
|
-
* Index N = press Arrow Down N times, then Enter.
|
|
7631
|
-
*/
|
|
7632
7911
|
resolveModal(buttonIndex) {
|
|
7633
7912
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
|
|
7634
7913
|
if (buttonIndex in this.approvalKeys) {
|
|
@@ -7643,25 +7922,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
7643
7922
|
if (this.ptyProcess) {
|
|
7644
7923
|
try {
|
|
7645
7924
|
this.ptyProcess.resize(cols, rows);
|
|
7925
|
+
this.terminalScreen.resize(rows, cols);
|
|
7646
7926
|
this.resizeSuppressUntil = Date.now() + 300;
|
|
7647
7927
|
} catch {
|
|
7648
7928
|
}
|
|
7649
7929
|
}
|
|
7650
7930
|
}
|
|
7651
|
-
/**
|
|
7652
|
-
* Full debug state — exposes all internal buffers, status, and patterns for debugging.
|
|
7653
|
-
* Used by DevServer /api/cli/debug endpoint.
|
|
7654
|
-
*/
|
|
7655
7931
|
getDebugState() {
|
|
7656
|
-
const sb = this.startupBuffer;
|
|
7657
|
-
const testOnStartup = (p) => {
|
|
7658
|
-
const flags = p.flags.includes("g") ? p.flags.replace(/g/g, "") : p.flags;
|
|
7659
|
-
return new RegExp(p.source, flags).test(sb);
|
|
7660
|
-
};
|
|
7661
|
-
const promptDiagnostics = this.provider.patterns.prompt.map((p) => ({
|
|
7662
|
-
pattern: p.toString(),
|
|
7663
|
-
matchedAgainstStartupBuffer: testOnStartup(p)
|
|
7664
|
-
}));
|
|
7665
7932
|
return {
|
|
7666
7933
|
type: this.cliType,
|
|
7667
7934
|
name: this.cliName,
|
|
@@ -7671,32 +7938,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7671
7938
|
spawnAt: this.spawnAt,
|
|
7672
7939
|
workingDir: this.workingDir,
|
|
7673
7940
|
messages: this.messages.slice(-20),
|
|
7941
|
+
structuredMessages: this.structuredMessages.slice(-20),
|
|
7674
7942
|
messageCount: this.messages.length,
|
|
7675
|
-
|
|
7676
|
-
startupBuffer: sb.slice(-4e3),
|
|
7677
|
-
startupBufferLength: sb.length,
|
|
7678
|
-
promptDiagnostics,
|
|
7943
|
+
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
7679
7944
|
recentOutputBuffer: this.recentOutputBuffer.slice(-500),
|
|
7680
7945
|
settledBuffer: this.settledBuffer.slice(-500),
|
|
7681
|
-
|
|
7682
|
-
approvalTransitionBuffer: this.approvalTransitionBuffer.slice(-500),
|
|
7683
|
-
// State
|
|
7946
|
+
accumulatedBufferLength: this.accumulatedBuffer.length,
|
|
7684
7947
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
7685
7948
|
activeModal: this.activeModal,
|
|
7686
7949
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
7687
7950
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
prompt: this.provider.patterns.prompt.map((p) => p.toString()),
|
|
7691
|
-
generating: this.provider.patterns.generating.map((p) => p.toString()),
|
|
7692
|
-
approval: this.provider.patterns.approval.map((p) => p.toString()),
|
|
7693
|
-
ready: this.provider.patterns.ready.map((p) => p.toString())
|
|
7694
|
-
},
|
|
7695
|
-
// Status history
|
|
7951
|
+
hasCliScripts: this.hasCliScripts(),
|
|
7952
|
+
scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
|
|
7696
7953
|
statusHistory: this.statusHistory.slice(-30),
|
|
7697
|
-
// Timeouts config
|
|
7698
7954
|
timeouts: this.timeouts,
|
|
7699
|
-
// PTY alive
|
|
7700
7955
|
ptyAlive: !!this.ptyProcess
|
|
7701
7956
|
};
|
|
7702
7957
|
}
|
|
@@ -7762,21 +8017,27 @@ var init_cli_provider_instance = __esm({
|
|
|
7762
8017
|
async onTick() {
|
|
7763
8018
|
}
|
|
7764
8019
|
getState() {
|
|
7765
|
-
const
|
|
8020
|
+
const rawStatus = this.adapter.getStatus();
|
|
8021
|
+
const parsedStatus = this.adapter.getScriptParsedStatus();
|
|
8022
|
+
const adapterStatus = parsedStatus ? {
|
|
8023
|
+
...rawStatus,
|
|
8024
|
+
messages: parsedStatus.messages || rawStatus.messages,
|
|
8025
|
+
activeModal: parsedStatus.activeModal || rawStatus.activeModal
|
|
8026
|
+
} : rawStatus;
|
|
7766
8027
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
7767
|
-
const recentMessages = adapterStatus.messages.slice(-50).map((m) =>
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
}));
|
|
8028
|
+
const recentMessages = adapterStatus.messages.slice(-50).map((m) => {
|
|
8029
|
+
const content = typeof m.content === "string" && m.content.length > 8e3 ? m.content.slice(0, 8e3) + "\n... (truncated)" : m.content;
|
|
8030
|
+
return { ...m, content };
|
|
8031
|
+
});
|
|
7772
8032
|
const partial2 = this.adapter.getPartialResponse();
|
|
7773
8033
|
if (adapterStatus.status === "generating" && partial2) {
|
|
7774
8034
|
const cleaned = partial2.trim();
|
|
7775
8035
|
if (cleaned && cleaned !== "(generating...)") {
|
|
7776
8036
|
recentMessages.push({
|
|
7777
8037
|
role: "assistant",
|
|
7778
|
-
content: (cleaned.length >
|
|
7779
|
-
timestamp: Date.now()
|
|
8038
|
+
content: (cleaned.length > 8e3 ? cleaned.slice(0, 8e3) + "..." : cleaned) + "...",
|
|
8039
|
+
timestamp: Date.now(),
|
|
8040
|
+
meta: { streaming: true }
|
|
7780
8041
|
});
|
|
7781
8042
|
}
|
|
7782
8043
|
}
|
|
@@ -7815,6 +8076,8 @@ var init_cli_provider_instance = __esm({
|
|
|
7815
8076
|
this.adapter.sendMessage(data.text);
|
|
7816
8077
|
} else if (event === "server_connected" && data?.serverConn) {
|
|
7817
8078
|
this.adapter.setServerConn(data.serverConn);
|
|
8079
|
+
} else if (event === "resolve_action" && data) {
|
|
8080
|
+
this.adapter.resolveAction(data);
|
|
7818
8081
|
}
|
|
7819
8082
|
}
|
|
7820
8083
|
dispose() {
|
|
@@ -25201,7 +25464,8 @@ var init_cli_manager = __esm({
|
|
|
25201
25464
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
25202
25465
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
25203
25466
|
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
25204
|
-
|
|
25467
|
+
const resolvedProvider = this.providerLoader.resolve(normalizedType) || provider;
|
|
25468
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs);
|
|
25205
25469
|
}
|
|
25206
25470
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
25207
25471
|
}
|
|
@@ -25286,7 +25550,8 @@ ${installInfo}`
|
|
|
25286
25550
|
}
|
|
25287
25551
|
const instanceManager = this.deps.getInstanceManager();
|
|
25288
25552
|
if (provider && instanceManager) {
|
|
25289
|
-
const
|
|
25553
|
+
const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
|
|
25554
|
+
const cliInstance = new CliProviderInstance(resolvedProvider, resolvedDir, cliArgs, key);
|
|
25290
25555
|
try {
|
|
25291
25556
|
await instanceManager.addInstance(key, cliInstance, {
|
|
25292
25557
|
serverConn: this.deps.getServerConn(),
|
|
@@ -28550,6 +28815,46 @@ var init_dev_server = __esm({
|
|
|
28550
28815
|
}
|
|
28551
28816
|
}
|
|
28552
28817
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
28818
|
+
getDefaultAutoImplReference(category, type) {
|
|
28819
|
+
if (category === "cli") {
|
|
28820
|
+
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
28821
|
+
}
|
|
28822
|
+
return "antigravity";
|
|
28823
|
+
}
|
|
28824
|
+
resolveAutoImplReference(category, requestedReference, targetType) {
|
|
28825
|
+
const desired = requestedReference || this.getDefaultAutoImplReference(category, targetType);
|
|
28826
|
+
const ref = this.providerLoader.resolve(desired) || this.providerLoader.getMeta(desired);
|
|
28827
|
+
if (ref?.category === category) return desired;
|
|
28828
|
+
const all = this.providerLoader.getAll();
|
|
28829
|
+
const fallback = all.find((p) => p.category === category && p.type !== targetType);
|
|
28830
|
+
return fallback?.type || null;
|
|
28831
|
+
}
|
|
28832
|
+
loadAutoImplReferenceScripts(category, referenceType) {
|
|
28833
|
+
if (!referenceType) return {};
|
|
28834
|
+
const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
|
|
28835
|
+
const refDir = path12.join(builtinDir, category, referenceType);
|
|
28836
|
+
if (!fs9.existsSync(refDir)) return {};
|
|
28837
|
+
const referenceScripts = {};
|
|
28838
|
+
const scriptsDir = path12.join(refDir, "scripts");
|
|
28839
|
+
if (!fs9.existsSync(scriptsDir)) return referenceScripts;
|
|
28840
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
28841
|
+
try {
|
|
28842
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
28843
|
+
} catch {
|
|
28844
|
+
return false;
|
|
28845
|
+
}
|
|
28846
|
+
}).sort().reverse();
|
|
28847
|
+
if (versions.length === 0) return referenceScripts;
|
|
28848
|
+
const latestDir = path12.join(scriptsDir, versions[0]);
|
|
28849
|
+
for (const file2 of fs9.readdirSync(latestDir)) {
|
|
28850
|
+
if (!file2.endsWith(".js")) continue;
|
|
28851
|
+
try {
|
|
28852
|
+
referenceScripts[file2] = fs9.readFileSync(path12.join(latestDir, file2), "utf-8");
|
|
28853
|
+
} catch {
|
|
28854
|
+
}
|
|
28855
|
+
}
|
|
28856
|
+
return referenceScripts;
|
|
28857
|
+
}
|
|
28553
28858
|
async handleAutoImplement(type, req, res) {
|
|
28554
28859
|
const body = await this.readBody(req);
|
|
28555
28860
|
const { agent = "claude-cli", functions, reference = "antigravity", model, comment } = body;
|
|
@@ -28572,36 +28877,26 @@ var init_dev_server = __esm({
|
|
|
28572
28877
|
return;
|
|
28573
28878
|
}
|
|
28574
28879
|
try {
|
|
28575
|
-
this.
|
|
28880
|
+
const resolvedReference = this.resolveAutoImplReference(provider.category, reference, type);
|
|
28881
|
+
this.sendAutoImplSSE({
|
|
28882
|
+
event: "progress",
|
|
28883
|
+
data: {
|
|
28884
|
+
function: "_init",
|
|
28885
|
+
status: "analyzing",
|
|
28886
|
+
message: provider.category === "cli" ? "Initializing agent (granting CLI PTY debug access)..." : "Initializing agent (granting DOM access)..."
|
|
28887
|
+
}
|
|
28888
|
+
});
|
|
28576
28889
|
const domContext = null;
|
|
28577
|
-
this.sendAutoImplSSE({
|
|
28578
|
-
|
|
28579
|
-
|
|
28580
|
-
|
|
28581
|
-
|
|
28582
|
-
|
|
28583
|
-
if (fs9.existsSync(scriptsDir)) {
|
|
28584
|
-
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
28585
|
-
try {
|
|
28586
|
-
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
28587
|
-
} catch {
|
|
28588
|
-
return false;
|
|
28589
|
-
}
|
|
28590
|
-
}).sort().reverse();
|
|
28591
|
-
if (versions.length > 0) {
|
|
28592
|
-
const latestDir = path12.join(scriptsDir, versions[0]);
|
|
28593
|
-
for (const file2 of fs9.readdirSync(latestDir)) {
|
|
28594
|
-
if (file2.endsWith(".js")) {
|
|
28595
|
-
try {
|
|
28596
|
-
referenceScripts[file2] = fs9.readFileSync(path12.join(latestDir, file2), "utf-8");
|
|
28597
|
-
} catch {
|
|
28598
|
-
}
|
|
28599
|
-
}
|
|
28600
|
-
}
|
|
28601
|
-
}
|
|
28890
|
+
this.sendAutoImplSSE({
|
|
28891
|
+
event: "progress",
|
|
28892
|
+
data: {
|
|
28893
|
+
function: "_init",
|
|
28894
|
+
status: "loading_reference",
|
|
28895
|
+
message: `Loading reference script (${resolvedReference || "none"})...`
|
|
28602
28896
|
}
|
|
28603
|
-
}
|
|
28604
|
-
const
|
|
28897
|
+
});
|
|
28898
|
+
const referenceScripts = this.loadAutoImplReferenceScripts(provider.category, resolvedReference);
|
|
28899
|
+
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
28605
28900
|
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
28606
28901
|
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
28607
28902
|
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
@@ -28619,7 +28914,7 @@ var init_dev_server = __esm({
|
|
|
28619
28914
|
}
|
|
28620
28915
|
const agentCategory = agentProvider?.category;
|
|
28621
28916
|
if (agentCategory === "acp") {
|
|
28622
|
-
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `ACP
|
|
28917
|
+
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn3.command} ${(spawn3.args || []).join(" ")}` } });
|
|
28623
28918
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
28624
28919
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
28625
28920
|
const { Readable: Readable2, Writable: Writable2 } = await import("stream");
|
|
@@ -28706,7 +29001,7 @@ var init_dev_server = __esm({
|
|
|
28706
29001
|
this.autoImplProcess = null;
|
|
28707
29002
|
this.autoImplStatus.running = false;
|
|
28708
29003
|
const success2 = code === 0;
|
|
28709
|
-
this.sendAutoImplSSE({ event: "complete", data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 ACP Auto-implement
|
|
29004
|
+
this.sendAutoImplSSE({ event: "complete", data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 ACP Auto-implement complete" : `\u274C ACP agent exited (code: ${code})` } });
|
|
28710
29005
|
try {
|
|
28711
29006
|
this.providerLoader.reload();
|
|
28712
29007
|
} catch {
|
|
@@ -28721,16 +29016,16 @@ var init_dev_server = __esm({
|
|
|
28721
29016
|
try {
|
|
28722
29017
|
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "initializing", message: "ACP initialize..." } });
|
|
28723
29018
|
await connection.initialize({ protocolVersion: PROTOCOL_VERSION2, clientCapabilities: {} });
|
|
28724
|
-
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "session", message: "ACP session
|
|
29019
|
+
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "session", message: "Creating ACP session..." } });
|
|
28725
29020
|
const session = await connection.newSession({ cwd: providerDir, mcpServers: [] });
|
|
28726
29021
|
const sessionId = session?.sessionId;
|
|
28727
29022
|
if (!sessionId) throw new Error("No sessionId returned from session/new");
|
|
28728
|
-
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "prompting", message:
|
|
29023
|
+
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "prompting", message: `Sending prompt (${prompt.length} chars)...` } });
|
|
28729
29024
|
await connection.prompt({
|
|
28730
29025
|
sessionId,
|
|
28731
29026
|
prompt: [{ type: "text", text: prompt }]
|
|
28732
29027
|
});
|
|
28733
|
-
this.sendAutoImplSSE({ event: "progress", data: { function: "_done", status: "complete", message: "\u2705 ACP
|
|
29028
|
+
this.sendAutoImplSSE({ event: "progress", data: { function: "_done", status: "complete", message: "\u2705 ACP prompt processing complete" } });
|
|
28734
29029
|
} catch (e) {
|
|
28735
29030
|
this.sendAutoImplSSE({ event: "output", data: { chunk: `[ACP Error] ${e.message}
|
|
28736
29031
|
`, stream: "stderr" } });
|
|
@@ -28782,7 +29077,7 @@ var init_dev_server = __esm({
|
|
|
28782
29077
|
const escapedArgs = baseArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
28783
29078
|
shellCmd = `cat '${promptFile}' | ${command} ${escapedArgs}`;
|
|
28784
29079
|
}
|
|
28785
|
-
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message:
|
|
29080
|
+
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
28786
29081
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
28787
29082
|
const spawnedAt = Date.now();
|
|
28788
29083
|
let child;
|
|
@@ -28878,7 +29173,7 @@ var init_dev_server = __esm({
|
|
|
28878
29173
|
const success2 = code === 0;
|
|
28879
29174
|
this.sendAutoImplSSE({
|
|
28880
29175
|
event: "complete",
|
|
28881
|
-
data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 Auto-implement
|
|
29176
|
+
data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})` }
|
|
28882
29177
|
});
|
|
28883
29178
|
try {
|
|
28884
29179
|
this.providerLoader.reload();
|
|
@@ -28913,7 +29208,7 @@ var init_dev_server = __esm({
|
|
|
28913
29208
|
success: success2,
|
|
28914
29209
|
exitCode: code,
|
|
28915
29210
|
functions,
|
|
28916
|
-
message: success2 ? "\u2705 Auto-implement
|
|
29211
|
+
message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`
|
|
28917
29212
|
}
|
|
28918
29213
|
});
|
|
28919
29214
|
try {
|
|
@@ -28941,7 +29236,10 @@ var init_dev_server = __esm({
|
|
|
28941
29236
|
this.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
28942
29237
|
}
|
|
28943
29238
|
}
|
|
28944
|
-
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment) {
|
|
29239
|
+
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
|
|
29240
|
+
if (provider.category === "cli") {
|
|
29241
|
+
return this.buildCliAutoImplPrompt(type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
|
|
29242
|
+
}
|
|
28945
29243
|
const lines = [];
|
|
28946
29244
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
28947
29245
|
lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
|
|
@@ -29004,7 +29302,7 @@ var init_dev_server = __esm({
|
|
|
29004
29302
|
setMode: "set_mode.js"
|
|
29005
29303
|
};
|
|
29006
29304
|
if (Object.keys(referenceScripts).length > 0) {
|
|
29007
|
-
lines.push(
|
|
29305
|
+
lines.push(`## Reference Implementation (from ${referenceType || "antigravity"} provider)`);
|
|
29008
29306
|
lines.push("These are WORKING scripts from another IDE. Adapt the PATTERNS (not selectors) for the target IDE.");
|
|
29009
29307
|
lines.push("");
|
|
29010
29308
|
for (const fn of functions) {
|
|
@@ -29153,6 +29451,150 @@ var init_dev_server = __esm({
|
|
|
29153
29451
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
29154
29452
|
return lines.join("\n");
|
|
29155
29453
|
}
|
|
29454
|
+
buildCliAutoImplPrompt(type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
|
|
29455
|
+
const lines = [];
|
|
29456
|
+
lines.push("You are implementing PTY parsing scripts for a CLI provider.");
|
|
29457
|
+
lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
|
|
29458
|
+
lines.push("");
|
|
29459
|
+
lines.push(`# Target: ${provider.name || type} (${type})`);
|
|
29460
|
+
lines.push(`Provider directory: \`${providerDir}\``);
|
|
29461
|
+
lines.push("Provider category: `cli`");
|
|
29462
|
+
lines.push("");
|
|
29463
|
+
lines.push("## Current Target Files");
|
|
29464
|
+
lines.push("These are the files you need to edit. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
29465
|
+
lines.push("");
|
|
29466
|
+
const scriptsDir = path12.join(providerDir, "scripts");
|
|
29467
|
+
if (fs9.existsSync(scriptsDir)) {
|
|
29468
|
+
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
29469
|
+
try {
|
|
29470
|
+
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
29471
|
+
} catch {
|
|
29472
|
+
return false;
|
|
29473
|
+
}
|
|
29474
|
+
}).sort().reverse();
|
|
29475
|
+
if (versions.length > 0) {
|
|
29476
|
+
const vDir = path12.join(scriptsDir, versions[0]);
|
|
29477
|
+
lines.push(`Scripts version directory: \`${vDir}\``);
|
|
29478
|
+
lines.push("");
|
|
29479
|
+
for (const file2 of fs9.readdirSync(vDir)) {
|
|
29480
|
+
if (!file2.endsWith(".js")) continue;
|
|
29481
|
+
try {
|
|
29482
|
+
const content = fs9.readFileSync(path12.join(vDir, file2), "utf-8");
|
|
29483
|
+
lines.push(`### \`${file2}\``);
|
|
29484
|
+
lines.push("```javascript");
|
|
29485
|
+
lines.push(content);
|
|
29486
|
+
lines.push("```");
|
|
29487
|
+
lines.push("");
|
|
29488
|
+
} catch {
|
|
29489
|
+
}
|
|
29490
|
+
}
|
|
29491
|
+
}
|
|
29492
|
+
}
|
|
29493
|
+
const funcToFile = {
|
|
29494
|
+
parseOutput: "parse_output.js",
|
|
29495
|
+
detectStatus: "detect_status.js",
|
|
29496
|
+
parseApproval: "parse_approval.js"
|
|
29497
|
+
};
|
|
29498
|
+
if (Object.keys(referenceScripts).length > 0) {
|
|
29499
|
+
lines.push(`## Reference Implementation (from ${referenceType || "another CLI"} provider)`);
|
|
29500
|
+
lines.push("These are working CLI PTY parser scripts. Reuse the parsing shape and runtime contract, but adapt to the target CLI screen.");
|
|
29501
|
+
lines.push("");
|
|
29502
|
+
for (const fn of functions) {
|
|
29503
|
+
const fileName = funcToFile[fn];
|
|
29504
|
+
if (fileName && referenceScripts[fileName]) {
|
|
29505
|
+
lines.push(`### ${fn} \u2192 \`${fileName}\``);
|
|
29506
|
+
lines.push("```javascript");
|
|
29507
|
+
lines.push(referenceScripts[fileName]);
|
|
29508
|
+
lines.push("```");
|
|
29509
|
+
lines.push("");
|
|
29510
|
+
}
|
|
29511
|
+
}
|
|
29512
|
+
if (referenceScripts["scripts.js"]) {
|
|
29513
|
+
lines.push("### Router \u2192 `scripts.js`");
|
|
29514
|
+
lines.push("```javascript");
|
|
29515
|
+
lines.push(referenceScripts["scripts.js"]);
|
|
29516
|
+
lines.push("```");
|
|
29517
|
+
lines.push("");
|
|
29518
|
+
}
|
|
29519
|
+
}
|
|
29520
|
+
lines.push("## Runtime Contract");
|
|
29521
|
+
lines.push("The daemon runtime is already implemented in `packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts`.");
|
|
29522
|
+
lines.push("Your scripts receive PTY-derived input and must return plain JS objects.");
|
|
29523
|
+
lines.push("");
|
|
29524
|
+
lines.push("| Function | Input | Return |");
|
|
29525
|
+
lines.push("|---|---|---|");
|
|
29526
|
+
lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
|
|
29527
|
+
lines.push("| `detectStatus` | `{ tail }` | `idle`, `generating`, `waiting_approval`, or `error` |");
|
|
29528
|
+
lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
|
|
29529
|
+
lines.push("");
|
|
29530
|
+
lines.push("## Rules");
|
|
29531
|
+
lines.push("1. These scripts run in Node.js CommonJS, not in the browser. Do NOT use DOM APIs.");
|
|
29532
|
+
lines.push("2. Prefer `screenText` for current visible UI state. That is the PTY equivalent of parsing the current IDE DOM.");
|
|
29533
|
+
lines.push("3. Use `messages` as prior transcript state so redraws do not duplicate old turns on every parse.");
|
|
29534
|
+
lines.push("4. Use `partialResponse` for the actively streaming assistant text when status is `generating`.");
|
|
29535
|
+
lines.push("5. `detectStatus` must stay lightweight and tail-based. Do not scan the entire history there.");
|
|
29536
|
+
lines.push("6. `parseApproval` should understand the live approval area and return clean button labels.");
|
|
29537
|
+
lines.push("7. Use `rawBuffer` only when ANSI/control-sequence artifacts matter. Do not depend on raw escape noise unless necessary.");
|
|
29538
|
+
lines.push("8. Keep exports compatible with the existing `scripts.js` router (`module.exports = function ...`).");
|
|
29539
|
+
lines.push("9. Do not rewrite unrelated provider config. Only touch the scripts needed for this task unless a tiny supporting change is required.");
|
|
29540
|
+
lines.push("");
|
|
29541
|
+
lines.push("## Task");
|
|
29542
|
+
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
29543
|
+
lines.push("");
|
|
29544
|
+
lines.push("## Verification API");
|
|
29545
|
+
lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
|
|
29546
|
+
lines.push("");
|
|
29547
|
+
lines.push("### 1. Launch the target CLI");
|
|
29548
|
+
lines.push("```bash");
|
|
29549
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
|
|
29550
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
29551
|
+
lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
|
|
29552
|
+
lines.push("```");
|
|
29553
|
+
lines.push("");
|
|
29554
|
+
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
29555
|
+
lines.push("```bash");
|
|
29556
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
29557
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
29558
|
+
lines.push("```");
|
|
29559
|
+
lines.push("");
|
|
29560
|
+
lines.push("### 3. Send a rich test prompt");
|
|
29561
|
+
lines.push("```bash");
|
|
29562
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
29563
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
29564
|
+
lines.push(` -d '{"type":"${type}","text":"Write a short python snippet, include a markdown table, and briefly explain what you did."}'`);
|
|
29565
|
+
lines.push("```");
|
|
29566
|
+
lines.push("");
|
|
29567
|
+
lines.push("### 4. If approval appears, resolve it");
|
|
29568
|
+
lines.push("```bash");
|
|
29569
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
29570
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
29571
|
+
lines.push(` -d '{"type":"${type}","buttonIndex":0}'`);
|
|
29572
|
+
lines.push("```");
|
|
29573
|
+
lines.push("");
|
|
29574
|
+
lines.push("### 5. Stop the CLI when finished");
|
|
29575
|
+
lines.push("```bash");
|
|
29576
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/stop \\`);
|
|
29577
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
29578
|
+
lines.push(` -d '{"type":"${type}"}'`);
|
|
29579
|
+
lines.push("```");
|
|
29580
|
+
lines.push("");
|
|
29581
|
+
lines.push("## Required Validation");
|
|
29582
|
+
lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
|
|
29583
|
+
lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
|
|
29584
|
+
lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
|
|
29585
|
+
lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
|
|
29586
|
+
lines.push("5. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
29587
|
+
lines.push("");
|
|
29588
|
+
if (userComment) {
|
|
29589
|
+
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
29590
|
+
lines.push("The user has provided the following additional instructions. Follow them strictly:");
|
|
29591
|
+
lines.push("");
|
|
29592
|
+
lines.push(userComment);
|
|
29593
|
+
lines.push("");
|
|
29594
|
+
}
|
|
29595
|
+
lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
|
|
29596
|
+
return lines.join("\n");
|
|
29597
|
+
}
|
|
29156
29598
|
handleAutoImplSSE(type, req, res) {
|
|
29157
29599
|
res.writeHead(200, {
|
|
29158
29600
|
"Content-Type": "text/event-stream",
|
|
@@ -29180,7 +29622,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
29180
29622
|
setTimeout(() => {
|
|
29181
29623
|
if (this.autoImplProcess) this.autoImplProcess.kill("SIGKILL");
|
|
29182
29624
|
}, 3e3);
|
|
29183
|
-
this.sendAutoImplSSE({ event: "complete", data: { success: false, exitCode: -1, message: "\u26D4
|
|
29625
|
+
this.sendAutoImplSSE({ event: "complete", data: { success: false, exitCode: -1, message: "\u26D4 Aborted by user" } });
|
|
29184
29626
|
this.autoImplProcess = null;
|
|
29185
29627
|
this.autoImplStatus.running = false;
|
|
29186
29628
|
this.json(res, 200, { cancelled: true });
|
|
@@ -30749,11 +31191,12 @@ ${e?.stack || ""}`);
|
|
|
30749
31191
|
});
|
|
30750
31192
|
|
|
30751
31193
|
// src/screenshot-controller.ts
|
|
30752
|
-
var ScreenshotController;
|
|
31194
|
+
var import_sharp, ScreenshotController;
|
|
30753
31195
|
var init_screenshot_controller = __esm({
|
|
30754
31196
|
"src/screenshot-controller.ts"() {
|
|
30755
31197
|
"use strict";
|
|
30756
31198
|
init_src();
|
|
31199
|
+
import_sharp = __toESM(require("sharp"));
|
|
30757
31200
|
ScreenshotController = class _ScreenshotController {
|
|
30758
31201
|
deps;
|
|
30759
31202
|
timer = null;
|
|
@@ -30780,12 +31223,16 @@ var init_screenshot_controller = __esm({
|
|
|
30780
31223
|
this.profileDirect = {
|
|
30781
31224
|
minInterval: Math.max(300, planMinIntervalMs),
|
|
30782
31225
|
maxInterval: Math.max(2e3, planMinIntervalMs),
|
|
30783
|
-
quality: 25
|
|
31226
|
+
quality: 25,
|
|
31227
|
+
maxLongEdge: 1728,
|
|
31228
|
+
firstFrameLongEdge: 1920
|
|
30784
31229
|
};
|
|
30785
31230
|
this.profileRelay = {
|
|
30786
31231
|
minInterval: Math.max(700, planMinIntervalMs),
|
|
30787
31232
|
maxInterval: Math.max(3e3, planMinIntervalMs),
|
|
30788
|
-
quality: 12
|
|
31233
|
+
quality: 12,
|
|
31234
|
+
maxLongEdge: 1152,
|
|
31235
|
+
firstFrameLongEdge: 1280
|
|
30789
31236
|
};
|
|
30790
31237
|
this.currentInterval = this.profileDirect.maxInterval;
|
|
30791
31238
|
this.dailyBudgetMinutes = planLimits?.dailyScreenshotMinutes ?? -1;
|
|
@@ -30858,6 +31305,7 @@ var init_screenshot_controller = __esm({
|
|
|
30858
31305
|
const sizeMatch = buf.length === this.lastSize;
|
|
30859
31306
|
const hashMatch = hash2 === this.lastHash;
|
|
30860
31307
|
const anyNeedsFirstFrame = this.deps.hasAnyNeedingFirstFrame();
|
|
31308
|
+
const resizeTarget = anyNeedsFirstFrame ? profile.firstFrameLongEdge : profile.maxLongEdge;
|
|
30861
31309
|
if (sizeMatch && hashMatch && !anyNeedsFirstFrame) {
|
|
30862
31310
|
this.staticFrameCount++;
|
|
30863
31311
|
if (this.staticFrameCount >= this.STATIC_THRESHOLD) {
|
|
@@ -30867,13 +31315,14 @@ var init_screenshot_controller = __esm({
|
|
|
30867
31315
|
LOG.debug("Screenshot", `skip (unchanged, static=${this.staticFrameCount}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"})`);
|
|
30868
31316
|
}
|
|
30869
31317
|
} else {
|
|
31318
|
+
const normalizedBuf = await this.normalizeBuffer(buf, resizeTarget, profile.quality);
|
|
30870
31319
|
this.lastSize = buf.length;
|
|
30871
31320
|
this.lastHash = hash2;
|
|
30872
31321
|
this.staticFrameCount = 0;
|
|
30873
31322
|
this.currentInterval = profile.minInterval;
|
|
30874
|
-
const sent = this.deps.sendScreenshotBuffer(
|
|
31323
|
+
const sent = this.deps.sendScreenshotBuffer(normalizedBuf);
|
|
30875
31324
|
if (this.debugCount <= 3 || anyNeedsFirstFrame) {
|
|
30876
|
-
LOG.debug("Screenshot", `sent: ${
|
|
31325
|
+
LOG.debug("Screenshot", `sent: ${normalizedBuf.length} bytes, delivered=${sent}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
30877
31326
|
}
|
|
30878
31327
|
}
|
|
30879
31328
|
} else {
|
|
@@ -30921,6 +31370,28 @@ var init_screenshot_controller = __esm({
|
|
|
30921
31370
|
}
|
|
30922
31371
|
return h;
|
|
30923
31372
|
}
|
|
31373
|
+
/** Normalize screenshot resolution before transport so UX feels consistent across machines/DPI. */
|
|
31374
|
+
async normalizeBuffer(buf, maxLongEdge, quality) {
|
|
31375
|
+
try {
|
|
31376
|
+
const image = (0, import_sharp.default)(buf, { failOn: "none" });
|
|
31377
|
+
const meta3 = await image.metadata();
|
|
31378
|
+
const width = meta3.width || 0;
|
|
31379
|
+
const height = meta3.height || 0;
|
|
31380
|
+
if (!width || !height) return buf;
|
|
31381
|
+
const longEdge = Math.max(width, height);
|
|
31382
|
+
if (longEdge <= maxLongEdge) return buf;
|
|
31383
|
+
return await image.resize({
|
|
31384
|
+
width: width >= height ? maxLongEdge : void 0,
|
|
31385
|
+
height: height > width ? maxLongEdge : void 0,
|
|
31386
|
+
fit: "inside",
|
|
31387
|
+
withoutEnlargement: true,
|
|
31388
|
+
kernel: import_sharp.default.kernel.lanczos3
|
|
31389
|
+
}).webp({ quality, effort: 4 }).toBuffer();
|
|
31390
|
+
} catch (e) {
|
|
31391
|
+
LOG.debug("Screenshot", `normalize skipped: ${e?.message || e}`);
|
|
31392
|
+
return buf;
|
|
31393
|
+
}
|
|
31394
|
+
}
|
|
30924
31395
|
};
|
|
30925
31396
|
}
|
|
30926
31397
|
});
|
|
@@ -30983,7 +31454,7 @@ var init_adhdev_daemon = __esm({
|
|
|
30983
31454
|
fs11 = __toESM(require("fs"));
|
|
30984
31455
|
path14 = __toESM(require("path"));
|
|
30985
31456
|
import_chalk2 = __toESM(require("chalk"));
|
|
30986
|
-
pkgVersion = "0.6.
|
|
31457
|
+
pkgVersion = "0.6.55";
|
|
30987
31458
|
if (pkgVersion === "unknown") {
|
|
30988
31459
|
try {
|
|
30989
31460
|
const possiblePaths = [
|