adhdev 0.6.53 → 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 +817 -300
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +749 -277
- 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" };
|
|
@@ -6015,8 +6036,9 @@ var init_provider_loader = __esm({
|
|
|
6015
6036
|
}
|
|
6016
6037
|
}
|
|
6017
6038
|
compareVersions(a, b) {
|
|
6018
|
-
const
|
|
6019
|
-
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);
|
|
6020
6042
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
6021
6043
|
const va = pa[i] || 0;
|
|
6022
6044
|
const vb = pb[i] || 0;
|
|
@@ -7040,6 +7062,246 @@ var init_reporter = __esm({
|
|
|
7040
7062
|
}
|
|
7041
7063
|
});
|
|
7042
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
|
+
|
|
7043
7305
|
// ../daemon-core/src/cli-adapters/provider-cli-adapter.ts
|
|
7044
7306
|
var provider_cli_adapter_exports = {};
|
|
7045
7307
|
__export(provider_cli_adapter_exports, {
|
|
@@ -7112,28 +7374,19 @@ function parsePatternEntry(x) {
|
|
|
7112
7374
|
}
|
|
7113
7375
|
return null;
|
|
7114
7376
|
}
|
|
7115
|
-
function coercePatternArray(raw
|
|
7116
|
-
if (!Array.isArray(raw)) return [
|
|
7117
|
-
|
|
7118
|
-
return parsed.length > 0 ? parsed : [...fallbacks];
|
|
7119
|
-
}
|
|
7120
|
-
function defaultCleanOutput(raw, _lastUserInput) {
|
|
7121
|
-
return stripAnsi(raw).trim();
|
|
7377
|
+
function coercePatternArray(raw) {
|
|
7378
|
+
if (!Array.isArray(raw)) return [];
|
|
7379
|
+
return raw.map(parsePatternEntry).filter((r) => r != null);
|
|
7122
7380
|
}
|
|
7123
7381
|
function normalizeCliProviderForRuntime(raw) {
|
|
7124
7382
|
const patterns = raw?.patterns || {};
|
|
7125
7383
|
return {
|
|
7126
|
-
...raw,
|
|
7127
7384
|
patterns: {
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
approval: coercePatternArray(patterns.approval, FALLBACK_APPROVAL),
|
|
7131
|
-
ready: coercePatternArray(patterns.ready, [])
|
|
7132
|
-
},
|
|
7133
|
-
cleanOutput: typeof raw?.cleanOutput === "function" ? raw.cleanOutput : defaultCleanOutput
|
|
7385
|
+
approval: coercePatternArray(patterns.approval)
|
|
7386
|
+
}
|
|
7134
7387
|
};
|
|
7135
7388
|
}
|
|
7136
|
-
var os11, path9, import_child_process5, pty,
|
|
7389
|
+
var os11, path9, import_child_process5, pty, ProviderCliAdapter;
|
|
7137
7390
|
var init_provider_cli_adapter = __esm({
|
|
7138
7391
|
"../daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
|
|
7139
7392
|
"use strict";
|
|
@@ -7141,6 +7394,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7141
7394
|
path9 = __toESM(require("path"));
|
|
7142
7395
|
import_child_process5 = require("child_process");
|
|
7143
7396
|
init_logger();
|
|
7397
|
+
init_terminal_screen();
|
|
7144
7398
|
try {
|
|
7145
7399
|
pty = require("node-pty");
|
|
7146
7400
|
if (os11.platform() !== "win32") {
|
|
@@ -7162,40 +7416,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7162
7416
|
} catch {
|
|
7163
7417
|
LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
|
|
7164
7418
|
}
|
|
7165
|
-
|
|
7166
|
-
/Type your message/i,
|
|
7167
|
-
/for\s*shortcuts/i,
|
|
7168
|
-
// Claude Code prompt
|
|
7169
|
-
/\?\s*for\s*help/i,
|
|
7170
|
-
// Claude Code help prompt
|
|
7171
|
-
/Press enter/i,
|
|
7172
|
-
/^[>›❯]\s*$/i,
|
|
7173
|
-
// Prompt char as the complete evaluated string
|
|
7174
|
-
/[>›❯]\s*$/
|
|
7175
|
-
// Prompt char at the very end of evaluated string
|
|
7176
|
-
];
|
|
7177
|
-
FALLBACK_GENERATING = [
|
|
7178
|
-
/[\u2800-\u28ff]/,
|
|
7179
|
-
// Braille spinner blocks (universal TUI)
|
|
7180
|
-
/esc to (cancel|interrupt|stop)/i,
|
|
7181
|
-
// Common TUI generation status line
|
|
7182
|
-
/generating\.\.\./i,
|
|
7183
|
-
/Claude is (?:thinking|processing|working)/i
|
|
7184
|
-
// Specific Claude Code status
|
|
7185
|
-
];
|
|
7186
|
-
FALLBACK_APPROVAL = [
|
|
7187
|
-
/Allow\s*once/i,
|
|
7188
|
-
// ANSI strip may remove spaces
|
|
7189
|
-
/Always\s*allow/i,
|
|
7190
|
-
/\(y\/n\)/i,
|
|
7191
|
-
/\[Y\/n\]/i,
|
|
7192
|
-
/Yes,?\s*don'?t\s*ask/i
|
|
7193
|
-
// "Yes, don't ask again" (Claude Code)
|
|
7194
|
-
];
|
|
7195
|
-
ProviderCliAdapter = class {
|
|
7419
|
+
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
7196
7420
|
constructor(provider, workingDir, extraArgs = []) {
|
|
7197
7421
|
this.extraArgs = extraArgs;
|
|
7198
|
-
this.provider =
|
|
7422
|
+
this.provider = provider;
|
|
7199
7423
|
this.cliType = provider.type;
|
|
7200
7424
|
this.cliName = provider.name;
|
|
7201
7425
|
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os11.homedir()) : workingDir;
|
|
@@ -7212,6 +7436,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
7212
7436
|
};
|
|
7213
7437
|
const rawKeys = provider.approvalKeys;
|
|
7214
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
|
+
}
|
|
7215
7446
|
}
|
|
7216
7447
|
cliType;
|
|
7217
7448
|
cliName;
|
|
@@ -7219,6 +7450,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7219
7450
|
provider;
|
|
7220
7451
|
ptyProcess = null;
|
|
7221
7452
|
messages = [];
|
|
7453
|
+
structuredMessages = [];
|
|
7222
7454
|
currentStatus = "starting";
|
|
7223
7455
|
onStatusChange = null;
|
|
7224
7456
|
responseBuffer = "";
|
|
@@ -7229,7 +7461,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
7229
7461
|
idleTimeout = null;
|
|
7230
7462
|
ready = false;
|
|
7231
7463
|
startupBuffer = "";
|
|
7232
|
-
/** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
|
|
7233
7464
|
startupParseGate = false;
|
|
7234
7465
|
spawnAt = 0;
|
|
7235
7466
|
// PTY I/O
|
|
@@ -7247,11 +7478,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7247
7478
|
// Output settle debounce — fires after PTY output goes quiet
|
|
7248
7479
|
settleTimer = null;
|
|
7249
7480
|
settledBuffer = "";
|
|
7250
|
-
// snapshot of recentOutputBuffer at settle time
|
|
7251
7481
|
// Resize redraw suppression
|
|
7252
7482
|
resizeSuppressUntil = 0;
|
|
7253
7483
|
// Debug: status transition history
|
|
7254
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;
|
|
7255
7495
|
setStatus(status, trigger) {
|
|
7256
7496
|
const prev = this.currentStatus;
|
|
7257
7497
|
if (prev === status) return;
|
|
@@ -7260,10 +7500,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
7260
7500
|
if (this.statusHistory.length > 50) this.statusHistory.shift();
|
|
7261
7501
|
LOG.info("CLI", `[${this.cliType}] status: ${prev} \u2192 ${status}${trigger ? ` (${trigger})` : ""}`);
|
|
7262
7502
|
}
|
|
7263
|
-
// Resolved timeouts
|
|
7503
|
+
// Resolved timeouts
|
|
7264
7504
|
timeouts;
|
|
7265
|
-
// Provider approval key mapping
|
|
7505
|
+
// Provider approval key mapping
|
|
7266
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
|
+
}
|
|
7267
7513
|
// ─── Lifecycle ─────────────────────────────────
|
|
7268
7514
|
setServerConn(serverConn) {
|
|
7269
7515
|
this.serverConn = serverConn;
|
|
@@ -7352,15 +7598,19 @@ var init_provider_cli_adapter = __esm({
|
|
|
7352
7598
|
this.spawnAt = Date.now();
|
|
7353
7599
|
this.startupParseGate = true;
|
|
7354
7600
|
this.startupBuffer = "";
|
|
7601
|
+
this.terminalScreen.reset(40, 120);
|
|
7355
7602
|
this.ready = true;
|
|
7356
7603
|
this.setStatus("idle", "pty_ready");
|
|
7357
7604
|
this.onStatusChange?.();
|
|
7358
7605
|
}
|
|
7359
|
-
// ─── Output
|
|
7606
|
+
// ─── Output Handling ────────────────────────────
|
|
7360
7607
|
handleOutput(rawData) {
|
|
7361
7608
|
if (Date.now() < this.resizeSuppressUntil) return;
|
|
7609
|
+
this.terminalScreen.write(rawData);
|
|
7362
7610
|
const cleanData = stripAnsi(rawData);
|
|
7363
|
-
|
|
7611
|
+
if (this.isWaitingForResponse && cleanData) {
|
|
7612
|
+
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
7613
|
+
}
|
|
7364
7614
|
if (cleanData.trim()) {
|
|
7365
7615
|
if (this.serverConn) {
|
|
7366
7616
|
this.serverConn.sendMessage("log", { message: cleanData.trim(), level: "info" });
|
|
@@ -7369,9 +7619,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7369
7619
|
}
|
|
7370
7620
|
}
|
|
7371
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);
|
|
7372
7624
|
if (this.startupParseGate) {
|
|
7373
7625
|
this.startupBuffer += cleanData;
|
|
7374
|
-
LOG.info("CLI", `[${this.cliType}] startup chunk (${cleanData.length} chars): ${cleanData.slice(0, 200).replace(/\n/g, "\\n")}`);
|
|
7375
7626
|
const dialogPatterns = [
|
|
7376
7627
|
/Do you want to connect/i,
|
|
7377
7628
|
/Do you trust the files/i,
|
|
@@ -7386,60 +7637,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
7386
7637
|
}
|
|
7387
7638
|
const elapsed = Date.now() - this.spawnAt;
|
|
7388
7639
|
const bufCap = this.startupBuffer.length > 12e3;
|
|
7389
|
-
const
|
|
7390
|
-
|
|
7640
|
+
const scriptStatus = this.runDetectStatus(this.startupBuffer);
|
|
7641
|
+
const isReady = scriptStatus === "idle" || elapsed > 8e3 || bufCap;
|
|
7642
|
+
if (isReady) {
|
|
7391
7643
|
this.startupParseGate = false;
|
|
7392
|
-
|
|
7393
|
-
LOG.info("CLI", `[${this.cliType}] \u2713 Startup gate end (prompt matched)`);
|
|
7394
|
-
} else {
|
|
7395
|
-
LOG.info("CLI", `[${this.cliType}] startup gate end (${elapsed}ms, cap=${bufCap}, prompt=${promptMatched})`);
|
|
7396
|
-
}
|
|
7644
|
+
LOG.info("CLI", `[${this.cliType}] Startup gate end (${elapsed}ms, scriptStatus=${scriptStatus})`);
|
|
7397
7645
|
} else {
|
|
7398
7646
|
return;
|
|
7399
7647
|
}
|
|
7400
7648
|
}
|
|
7401
|
-
if (cleanData.trim().length > 5) {
|
|
7402
|
-
LOG.debug("CLI", `[${this.cliType}] output chunk (${cleanData.length}): ${cleanData.slice(0, 300).replace(/\n/g, "\\n")}`);
|
|
7403
|
-
}
|
|
7404
|
-
if (!this.isWaitingForResponse) {
|
|
7405
|
-
if (patterns.generating.some((p) => p.test(cleanData))) {
|
|
7406
|
-
if (this.settleTimer) {
|
|
7407
|
-
clearTimeout(this.settleTimer);
|
|
7408
|
-
this.settleTimer = null;
|
|
7409
|
-
}
|
|
7410
|
-
this.isWaitingForResponse = true;
|
|
7411
|
-
this.responseBuffer = "";
|
|
7412
|
-
this.setStatus("generating", "autonomous_gen");
|
|
7413
|
-
this.onStatusChange?.();
|
|
7414
|
-
}
|
|
7415
|
-
}
|
|
7416
|
-
if (this.isWaitingForResponse) {
|
|
7417
|
-
this.responseBuffer += cleanData;
|
|
7418
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
7419
|
-
if (patterns.generating.some((p) => p.test(cleanData))) {
|
|
7420
|
-
this.setStatus("generating", "still_generating");
|
|
7421
|
-
this.idleTimeout = setTimeout(() => {
|
|
7422
|
-
if (this.isWaitingForResponse) this.finishResponse();
|
|
7423
|
-
}, this.timeouts.generatingIdle);
|
|
7424
|
-
this.onStatusChange?.();
|
|
7425
|
-
if (this.settleTimer) {
|
|
7426
|
-
clearTimeout(this.settleTimer);
|
|
7427
|
-
this.settleTimer = null;
|
|
7428
|
-
}
|
|
7429
|
-
return;
|
|
7430
|
-
}
|
|
7431
|
-
}
|
|
7432
|
-
if (this.currentStatus === "waiting_approval") {
|
|
7433
|
-
this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
|
|
7434
|
-
this.scheduleSettle();
|
|
7435
|
-
return;
|
|
7436
|
-
}
|
|
7437
7649
|
this.scheduleSettle();
|
|
7438
7650
|
}
|
|
7439
|
-
/**
|
|
7440
|
-
* Fired after output goes quiet for outputSettle ms.
|
|
7441
|
-
* Evaluates the stabilised buffer for approval, prompt (idle), or timeout.
|
|
7442
|
-
*/
|
|
7443
7651
|
scheduleSettle() {
|
|
7444
7652
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
7445
7653
|
this.settleTimer = setTimeout(() => {
|
|
@@ -7449,59 +7657,25 @@ var init_provider_cli_adapter = __esm({
|
|
|
7449
7657
|
}, this.timeouts.outputSettle);
|
|
7450
7658
|
}
|
|
7451
7659
|
evaluateSettled() {
|
|
7452
|
-
const
|
|
7453
|
-
const
|
|
7454
|
-
if (
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
if (genResume) {
|
|
7458
|
-
if (this.approvalExitTimeout) {
|
|
7459
|
-
clearTimeout(this.approvalExitTimeout);
|
|
7460
|
-
this.approvalExitTimeout = null;
|
|
7461
|
-
}
|
|
7462
|
-
this.setStatus("generating", "approval_gen_resume");
|
|
7463
|
-
this.activeModal = null;
|
|
7464
|
-
this.recentOutputBuffer = "";
|
|
7465
|
-
this.approvalTransitionBuffer = "";
|
|
7466
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
7467
|
-
this.onStatusChange?.();
|
|
7468
|
-
} else if (promptResume) {
|
|
7469
|
-
if (this.approvalExitTimeout) {
|
|
7470
|
-
clearTimeout(this.approvalExitTimeout);
|
|
7471
|
-
this.approvalExitTimeout = null;
|
|
7472
|
-
}
|
|
7473
|
-
this.activeModal = null;
|
|
7474
|
-
this.recentOutputBuffer = "";
|
|
7475
|
-
this.approvalTransitionBuffer = "";
|
|
7476
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
7477
|
-
this.finishResponse();
|
|
7478
|
-
}
|
|
7479
|
-
return;
|
|
7480
|
-
}
|
|
7481
|
-
const hasApproval = patterns.approval.some((p) => p.test(buf));
|
|
7482
|
-
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") {
|
|
7483
7665
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
7484
7666
|
if (!inCooldown) {
|
|
7485
|
-
const ctxLines = buf.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
7486
7667
|
this.isWaitingForResponse = true;
|
|
7487
|
-
this.setStatus("waiting_approval", "
|
|
7488
|
-
|
|
7489
|
-
this.
|
|
7490
|
-
this.activeModal = {
|
|
7491
|
-
message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
|
|
7492
|
-
buttons: this.cliType === "claude-cli" ? ["Yes (y)", "Always allow (a)", "Deny (Esc)"] : ["Allow once", "Always allow", "Deny"]
|
|
7493
|
-
};
|
|
7668
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
7669
|
+
const modal = this.runParseApproval(tail);
|
|
7670
|
+
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
7494
7671
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
7495
7672
|
if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
|
|
7496
7673
|
this.approvalExitTimeout = setTimeout(() => {
|
|
7497
7674
|
if (this.currentStatus === "waiting_approval") {
|
|
7498
|
-
LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-
|
|
7675
|
+
LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-clearing`);
|
|
7499
7676
|
this.activeModal = null;
|
|
7500
7677
|
this.lastApprovalResolvedAt = Date.now();
|
|
7501
|
-
this.
|
|
7502
|
-
this.approvalTransitionBuffer = "";
|
|
7503
|
-
this.approvalExitTimeout = null;
|
|
7504
|
-
this.setStatus(this.isWaitingForResponse ? "generating" : "idle", "approval_cleared");
|
|
7678
|
+
this.setStatus("idle", "approval_timeout");
|
|
7505
7679
|
this.onStatusChange?.();
|
|
7506
7680
|
}
|
|
7507
7681
|
}, 6e4);
|
|
@@ -7509,19 +7683,42 @@ var init_provider_cli_adapter = __esm({
|
|
|
7509
7683
|
return;
|
|
7510
7684
|
}
|
|
7511
7685
|
}
|
|
7512
|
-
if (
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
this.
|
|
7519
|
-
|
|
7520
|
-
this.finishResponse();
|
|
7521
|
-
}
|
|
7522
|
-
}, 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();
|
|
7523
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);
|
|
7524
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
|
+
}
|
|
7525
7722
|
}
|
|
7526
7723
|
}
|
|
7527
7724
|
finishResponse() {
|
|
@@ -7537,25 +7734,50 @@ var init_provider_cli_adapter = __esm({
|
|
|
7537
7734
|
clearTimeout(this.approvalExitTimeout);
|
|
7538
7735
|
this.approvalExitTimeout = null;
|
|
7539
7736
|
}
|
|
7540
|
-
const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
|
|
7541
|
-
let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
|
|
7542
|
-
if (lastUserText && response) {
|
|
7543
|
-
const userTrimmed = lastUserText.trim();
|
|
7544
|
-
response = response.split("\n").filter((l) => l.trim() !== userTrimmed).join("\n").trim();
|
|
7545
|
-
}
|
|
7546
|
-
if (response) {
|
|
7547
|
-
this.messages.push({ role: "assistant", content: response, timestamp: Date.now() });
|
|
7548
|
-
if (this.messages.length > 200) this.messages = this.messages.slice(-200);
|
|
7549
|
-
LOG.info("CLI", `[${this.cliType}] Response (${response.length} chars)`);
|
|
7550
|
-
}
|
|
7551
7737
|
this.responseBuffer = "";
|
|
7552
7738
|
this.isWaitingForResponse = false;
|
|
7553
7739
|
this.activeModal = null;
|
|
7554
7740
|
this.setStatus("idle", "response_finished");
|
|
7555
7741
|
this.onStatusChange?.();
|
|
7556
7742
|
}
|
|
7557
|
-
// ───
|
|
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) ───────────────────
|
|
7558
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
|
+
}
|
|
7559
7781
|
return {
|
|
7560
7782
|
status: this.currentStatus,
|
|
7561
7783
|
messages: [...this.messages],
|
|
@@ -7563,11 +7785,71 @@ var init_provider_cli_adapter = __esm({
|
|
|
7563
7785
|
activeModal: this.activeModal
|
|
7564
7786
|
};
|
|
7565
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
|
+
}
|
|
7566
7847
|
async sendMessage(text) {
|
|
7567
7848
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
7568
7849
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
7569
7850
|
if (this.isWaitingForResponse) return;
|
|
7570
7851
|
this.messages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
7852
|
+
this.structuredMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
7571
7853
|
this.isWaitingForResponse = true;
|
|
7572
7854
|
this.responseBuffer = "";
|
|
7573
7855
|
this.setStatus("generating", "sendMessage");
|
|
@@ -7579,8 +7861,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7579
7861
|
}
|
|
7580
7862
|
getPartialResponse() {
|
|
7581
7863
|
if (!this.isWaitingForResponse) return "";
|
|
7582
|
-
|
|
7583
|
-
return partial2 || (this.isWaitingForResponse ? "(generating...)" : "");
|
|
7864
|
+
return this.responseBuffer;
|
|
7584
7865
|
}
|
|
7585
7866
|
cancel() {
|
|
7586
7867
|
this.shutdown();
|
|
@@ -7612,6 +7893,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7612
7893
|
}
|
|
7613
7894
|
clearHistory() {
|
|
7614
7895
|
this.messages = [];
|
|
7896
|
+
this.structuredMessages = [];
|
|
7897
|
+
this.accumulatedBuffer = "";
|
|
7898
|
+
this.accumulatedRawBuffer = "";
|
|
7899
|
+
this.terminalScreen.reset();
|
|
7615
7900
|
this.onStatusChange?.();
|
|
7616
7901
|
}
|
|
7617
7902
|
isProcessing() {
|
|
@@ -7623,11 +7908,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
7623
7908
|
writeRaw(data) {
|
|
7624
7909
|
this.ptyProcess?.write(data);
|
|
7625
7910
|
}
|
|
7626
|
-
/**
|
|
7627
|
-
* Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
|
|
7628
|
-
* Index 0 = first option (already selected by default — just Enter).
|
|
7629
|
-
* Index N = press Arrow Down N times, then Enter.
|
|
7630
|
-
*/
|
|
7631
7911
|
resolveModal(buttonIndex) {
|
|
7632
7912
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
|
|
7633
7913
|
if (buttonIndex in this.approvalKeys) {
|
|
@@ -7642,25 +7922,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
7642
7922
|
if (this.ptyProcess) {
|
|
7643
7923
|
try {
|
|
7644
7924
|
this.ptyProcess.resize(cols, rows);
|
|
7925
|
+
this.terminalScreen.resize(rows, cols);
|
|
7645
7926
|
this.resizeSuppressUntil = Date.now() + 300;
|
|
7646
7927
|
} catch {
|
|
7647
7928
|
}
|
|
7648
7929
|
}
|
|
7649
7930
|
}
|
|
7650
|
-
/**
|
|
7651
|
-
* Full debug state — exposes all internal buffers, status, and patterns for debugging.
|
|
7652
|
-
* Used by DevServer /api/cli/debug endpoint.
|
|
7653
|
-
*/
|
|
7654
7931
|
getDebugState() {
|
|
7655
|
-
const sb = this.startupBuffer;
|
|
7656
|
-
const testOnStartup = (p) => {
|
|
7657
|
-
const flags = p.flags.includes("g") ? p.flags.replace(/g/g, "") : p.flags;
|
|
7658
|
-
return new RegExp(p.source, flags).test(sb);
|
|
7659
|
-
};
|
|
7660
|
-
const promptDiagnostics = this.provider.patterns.prompt.map((p) => ({
|
|
7661
|
-
pattern: p.toString(),
|
|
7662
|
-
matchedAgainstStartupBuffer: testOnStartup(p)
|
|
7663
|
-
}));
|
|
7664
7932
|
return {
|
|
7665
7933
|
type: this.cliType,
|
|
7666
7934
|
name: this.cliName,
|
|
@@ -7670,32 +7938,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7670
7938
|
spawnAt: this.spawnAt,
|
|
7671
7939
|
workingDir: this.workingDir,
|
|
7672
7940
|
messages: this.messages.slice(-20),
|
|
7941
|
+
structuredMessages: this.structuredMessages.slice(-20),
|
|
7673
7942
|
messageCount: this.messages.length,
|
|
7674
|
-
|
|
7675
|
-
startupBuffer: sb.slice(-4e3),
|
|
7676
|
-
startupBufferLength: sb.length,
|
|
7677
|
-
promptDiagnostics,
|
|
7943
|
+
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
7678
7944
|
recentOutputBuffer: this.recentOutputBuffer.slice(-500),
|
|
7679
7945
|
settledBuffer: this.settledBuffer.slice(-500),
|
|
7680
|
-
|
|
7681
|
-
approvalTransitionBuffer: this.approvalTransitionBuffer.slice(-500),
|
|
7682
|
-
// State
|
|
7946
|
+
accumulatedBufferLength: this.accumulatedBuffer.length,
|
|
7683
7947
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
7684
7948
|
activeModal: this.activeModal,
|
|
7685
7949
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
7686
7950
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
prompt: this.provider.patterns.prompt.map((p) => p.toString()),
|
|
7690
|
-
generating: this.provider.patterns.generating.map((p) => p.toString()),
|
|
7691
|
-
approval: this.provider.patterns.approval.map((p) => p.toString()),
|
|
7692
|
-
ready: this.provider.patterns.ready.map((p) => p.toString())
|
|
7693
|
-
},
|
|
7694
|
-
// Status history
|
|
7951
|
+
hasCliScripts: this.hasCliScripts(),
|
|
7952
|
+
scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
|
|
7695
7953
|
statusHistory: this.statusHistory.slice(-30),
|
|
7696
|
-
// Timeouts config
|
|
7697
7954
|
timeouts: this.timeouts,
|
|
7698
|
-
// PTY alive
|
|
7699
7955
|
ptyAlive: !!this.ptyProcess
|
|
7700
7956
|
};
|
|
7701
7957
|
}
|
|
@@ -7761,21 +8017,27 @@ var init_cli_provider_instance = __esm({
|
|
|
7761
8017
|
async onTick() {
|
|
7762
8018
|
}
|
|
7763
8019
|
getState() {
|
|
7764
|
-
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;
|
|
7765
8027
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
7766
|
-
const recentMessages = adapterStatus.messages.slice(-50).map((m) =>
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
}));
|
|
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
|
+
});
|
|
7771
8032
|
const partial2 = this.adapter.getPartialResponse();
|
|
7772
8033
|
if (adapterStatus.status === "generating" && partial2) {
|
|
7773
8034
|
const cleaned = partial2.trim();
|
|
7774
8035
|
if (cleaned && cleaned !== "(generating...)") {
|
|
7775
8036
|
recentMessages.push({
|
|
7776
8037
|
role: "assistant",
|
|
7777
|
-
content: (cleaned.length >
|
|
7778
|
-
timestamp: Date.now()
|
|
8038
|
+
content: (cleaned.length > 8e3 ? cleaned.slice(0, 8e3) + "..." : cleaned) + "...",
|
|
8039
|
+
timestamp: Date.now(),
|
|
8040
|
+
meta: { streaming: true }
|
|
7779
8041
|
});
|
|
7780
8042
|
}
|
|
7781
8043
|
}
|
|
@@ -7814,6 +8076,8 @@ var init_cli_provider_instance = __esm({
|
|
|
7814
8076
|
this.adapter.sendMessage(data.text);
|
|
7815
8077
|
} else if (event === "server_connected" && data?.serverConn) {
|
|
7816
8078
|
this.adapter.setServerConn(data.serverConn);
|
|
8079
|
+
} else if (event === "resolve_action" && data) {
|
|
8080
|
+
this.adapter.resolveAction(data);
|
|
7817
8081
|
}
|
|
7818
8082
|
}
|
|
7819
8083
|
dispose() {
|
|
@@ -25200,7 +25464,8 @@ var init_cli_manager = __esm({
|
|
|
25200
25464
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
25201
25465
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
25202
25466
|
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
25203
|
-
|
|
25467
|
+
const resolvedProvider = this.providerLoader.resolve(normalizedType) || provider;
|
|
25468
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs);
|
|
25204
25469
|
}
|
|
25205
25470
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
25206
25471
|
}
|
|
@@ -25285,7 +25550,8 @@ ${installInfo}`
|
|
|
25285
25550
|
}
|
|
25286
25551
|
const instanceManager = this.deps.getInstanceManager();
|
|
25287
25552
|
if (provider && instanceManager) {
|
|
25288
|
-
const
|
|
25553
|
+
const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
|
|
25554
|
+
const cliInstance = new CliProviderInstance(resolvedProvider, resolvedDir, cliArgs, key);
|
|
25289
25555
|
try {
|
|
25290
25556
|
await instanceManager.addInstance(key, cliInstance, {
|
|
25291
25557
|
serverConn: this.deps.getServerConn(),
|
|
@@ -28549,6 +28815,46 @@ var init_dev_server = __esm({
|
|
|
28549
28815
|
}
|
|
28550
28816
|
}
|
|
28551
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
|
+
}
|
|
28552
28858
|
async handleAutoImplement(type, req, res) {
|
|
28553
28859
|
const body = await this.readBody(req);
|
|
28554
28860
|
const { agent = "claude-cli", functions, reference = "antigravity", model, comment } = body;
|
|
@@ -28571,36 +28877,26 @@ var init_dev_server = __esm({
|
|
|
28571
28877
|
return;
|
|
28572
28878
|
}
|
|
28573
28879
|
try {
|
|
28574
|
-
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
|
+
});
|
|
28575
28889
|
const domContext = null;
|
|
28576
|
-
this.sendAutoImplSSE({
|
|
28577
|
-
|
|
28578
|
-
|
|
28579
|
-
|
|
28580
|
-
|
|
28581
|
-
|
|
28582
|
-
if (fs9.existsSync(scriptsDir)) {
|
|
28583
|
-
const versions = fs9.readdirSync(scriptsDir).filter((d) => {
|
|
28584
|
-
try {
|
|
28585
|
-
return fs9.statSync(path12.join(scriptsDir, d)).isDirectory();
|
|
28586
|
-
} catch {
|
|
28587
|
-
return false;
|
|
28588
|
-
}
|
|
28589
|
-
}).sort().reverse();
|
|
28590
|
-
if (versions.length > 0) {
|
|
28591
|
-
const latestDir = path12.join(scriptsDir, versions[0]);
|
|
28592
|
-
for (const file2 of fs9.readdirSync(latestDir)) {
|
|
28593
|
-
if (file2.endsWith(".js")) {
|
|
28594
|
-
try {
|
|
28595
|
-
referenceScripts[file2] = fs9.readFileSync(path12.join(latestDir, file2), "utf-8");
|
|
28596
|
-
} catch {
|
|
28597
|
-
}
|
|
28598
|
-
}
|
|
28599
|
-
}
|
|
28600
|
-
}
|
|
28890
|
+
this.sendAutoImplSSE({
|
|
28891
|
+
event: "progress",
|
|
28892
|
+
data: {
|
|
28893
|
+
function: "_init",
|
|
28894
|
+
status: "loading_reference",
|
|
28895
|
+
message: `Loading reference script (${resolvedReference || "none"})...`
|
|
28601
28896
|
}
|
|
28602
|
-
}
|
|
28603
|
-
const
|
|
28897
|
+
});
|
|
28898
|
+
const referenceScripts = this.loadAutoImplReferenceScripts(provider.category, resolvedReference);
|
|
28899
|
+
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
28604
28900
|
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
28605
28901
|
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
28606
28902
|
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
@@ -28618,7 +28914,7 @@ var init_dev_server = __esm({
|
|
|
28618
28914
|
}
|
|
28619
28915
|
const agentCategory = agentProvider?.category;
|
|
28620
28916
|
if (agentCategory === "acp") {
|
|
28621
|
-
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(" ")}` } });
|
|
28622
28918
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
28623
28919
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
28624
28920
|
const { Readable: Readable2, Writable: Writable2 } = await import("stream");
|
|
@@ -28705,7 +29001,7 @@ var init_dev_server = __esm({
|
|
|
28705
29001
|
this.autoImplProcess = null;
|
|
28706
29002
|
this.autoImplStatus.running = false;
|
|
28707
29003
|
const success2 = code === 0;
|
|
28708
|
-
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})` } });
|
|
28709
29005
|
try {
|
|
28710
29006
|
this.providerLoader.reload();
|
|
28711
29007
|
} catch {
|
|
@@ -28720,16 +29016,16 @@ var init_dev_server = __esm({
|
|
|
28720
29016
|
try {
|
|
28721
29017
|
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "initializing", message: "ACP initialize..." } });
|
|
28722
29018
|
await connection.initialize({ protocolVersion: PROTOCOL_VERSION2, clientCapabilities: {} });
|
|
28723
|
-
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..." } });
|
|
28724
29020
|
const session = await connection.newSession({ cwd: providerDir, mcpServers: [] });
|
|
28725
29021
|
const sessionId = session?.sessionId;
|
|
28726
29022
|
if (!sessionId) throw new Error("No sessionId returned from session/new");
|
|
28727
|
-
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)...` } });
|
|
28728
29024
|
await connection.prompt({
|
|
28729
29025
|
sessionId,
|
|
28730
29026
|
prompt: [{ type: "text", text: prompt }]
|
|
28731
29027
|
});
|
|
28732
|
-
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" } });
|
|
28733
29029
|
} catch (e) {
|
|
28734
29030
|
this.sendAutoImplSSE({ event: "output", data: { chunk: `[ACP Error] ${e.message}
|
|
28735
29031
|
`, stream: "stderr" } });
|
|
@@ -28781,7 +29077,7 @@ var init_dev_server = __esm({
|
|
|
28781
29077
|
const escapedArgs = baseArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
28782
29078
|
shellCmd = `cat '${promptFile}' | ${command} ${escapedArgs}`;
|
|
28783
29079
|
}
|
|
28784
|
-
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)` } });
|
|
28785
29081
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
28786
29082
|
const spawnedAt = Date.now();
|
|
28787
29083
|
let child;
|
|
@@ -28877,7 +29173,7 @@ var init_dev_server = __esm({
|
|
|
28877
29173
|
const success2 = code === 0;
|
|
28878
29174
|
this.sendAutoImplSSE({
|
|
28879
29175
|
event: "complete",
|
|
28880
|
-
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})` }
|
|
28881
29177
|
});
|
|
28882
29178
|
try {
|
|
28883
29179
|
this.providerLoader.reload();
|
|
@@ -28912,7 +29208,7 @@ var init_dev_server = __esm({
|
|
|
28912
29208
|
success: success2,
|
|
28913
29209
|
exitCode: code,
|
|
28914
29210
|
functions,
|
|
28915
|
-
message: success2 ? "\u2705 Auto-implement
|
|
29211
|
+
message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`
|
|
28916
29212
|
}
|
|
28917
29213
|
});
|
|
28918
29214
|
try {
|
|
@@ -28940,7 +29236,10 @@ var init_dev_server = __esm({
|
|
|
28940
29236
|
this.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
28941
29237
|
}
|
|
28942
29238
|
}
|
|
28943
|
-
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
|
+
}
|
|
28944
29243
|
const lines = [];
|
|
28945
29244
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
28946
29245
|
lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
|
|
@@ -29003,7 +29302,7 @@ var init_dev_server = __esm({
|
|
|
29003
29302
|
setMode: "set_mode.js"
|
|
29004
29303
|
};
|
|
29005
29304
|
if (Object.keys(referenceScripts).length > 0) {
|
|
29006
|
-
lines.push(
|
|
29305
|
+
lines.push(`## Reference Implementation (from ${referenceType || "antigravity"} provider)`);
|
|
29007
29306
|
lines.push("These are WORKING scripts from another IDE. Adapt the PATTERNS (not selectors) for the target IDE.");
|
|
29008
29307
|
lines.push("");
|
|
29009
29308
|
for (const fn of functions) {
|
|
@@ -29152,6 +29451,150 @@ var init_dev_server = __esm({
|
|
|
29152
29451
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
29153
29452
|
return lines.join("\n");
|
|
29154
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
|
+
}
|
|
29155
29598
|
handleAutoImplSSE(type, req, res) {
|
|
29156
29599
|
res.writeHead(200, {
|
|
29157
29600
|
"Content-Type": "text/event-stream",
|
|
@@ -29179,7 +29622,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
29179
29622
|
setTimeout(() => {
|
|
29180
29623
|
if (this.autoImplProcess) this.autoImplProcess.kill("SIGKILL");
|
|
29181
29624
|
}, 3e3);
|
|
29182
|
-
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" } });
|
|
29183
29626
|
this.autoImplProcess = null;
|
|
29184
29627
|
this.autoImplStatus.running = false;
|
|
29185
29628
|
this.json(res, 200, { cancelled: true });
|
|
@@ -30748,11 +31191,12 @@ ${e?.stack || ""}`);
|
|
|
30748
31191
|
});
|
|
30749
31192
|
|
|
30750
31193
|
// src/screenshot-controller.ts
|
|
30751
|
-
var ScreenshotController;
|
|
31194
|
+
var import_sharp, ScreenshotController;
|
|
30752
31195
|
var init_screenshot_controller = __esm({
|
|
30753
31196
|
"src/screenshot-controller.ts"() {
|
|
30754
31197
|
"use strict";
|
|
30755
31198
|
init_src();
|
|
31199
|
+
import_sharp = __toESM(require("sharp"));
|
|
30756
31200
|
ScreenshotController = class _ScreenshotController {
|
|
30757
31201
|
deps;
|
|
30758
31202
|
timer = null;
|
|
@@ -30779,12 +31223,16 @@ var init_screenshot_controller = __esm({
|
|
|
30779
31223
|
this.profileDirect = {
|
|
30780
31224
|
minInterval: Math.max(300, planMinIntervalMs),
|
|
30781
31225
|
maxInterval: Math.max(2e3, planMinIntervalMs),
|
|
30782
|
-
quality: 25
|
|
31226
|
+
quality: 25,
|
|
31227
|
+
maxLongEdge: 1728,
|
|
31228
|
+
firstFrameLongEdge: 1920
|
|
30783
31229
|
};
|
|
30784
31230
|
this.profileRelay = {
|
|
30785
31231
|
minInterval: Math.max(700, planMinIntervalMs),
|
|
30786
31232
|
maxInterval: Math.max(3e3, planMinIntervalMs),
|
|
30787
|
-
quality: 12
|
|
31233
|
+
quality: 12,
|
|
31234
|
+
maxLongEdge: 1152,
|
|
31235
|
+
firstFrameLongEdge: 1280
|
|
30788
31236
|
};
|
|
30789
31237
|
this.currentInterval = this.profileDirect.maxInterval;
|
|
30790
31238
|
this.dailyBudgetMinutes = planLimits?.dailyScreenshotMinutes ?? -1;
|
|
@@ -30857,6 +31305,7 @@ var init_screenshot_controller = __esm({
|
|
|
30857
31305
|
const sizeMatch = buf.length === this.lastSize;
|
|
30858
31306
|
const hashMatch = hash2 === this.lastHash;
|
|
30859
31307
|
const anyNeedsFirstFrame = this.deps.hasAnyNeedingFirstFrame();
|
|
31308
|
+
const resizeTarget = anyNeedsFirstFrame ? profile.firstFrameLongEdge : profile.maxLongEdge;
|
|
30860
31309
|
if (sizeMatch && hashMatch && !anyNeedsFirstFrame) {
|
|
30861
31310
|
this.staticFrameCount++;
|
|
30862
31311
|
if (this.staticFrameCount >= this.STATIC_THRESHOLD) {
|
|
@@ -30866,13 +31315,14 @@ var init_screenshot_controller = __esm({
|
|
|
30866
31315
|
LOG.debug("Screenshot", `skip (unchanged, static=${this.staticFrameCount}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"})`);
|
|
30867
31316
|
}
|
|
30868
31317
|
} else {
|
|
31318
|
+
const normalizedBuf = await this.normalizeBuffer(buf, resizeTarget, profile.quality);
|
|
30869
31319
|
this.lastSize = buf.length;
|
|
30870
31320
|
this.lastHash = hash2;
|
|
30871
31321
|
this.staticFrameCount = 0;
|
|
30872
31322
|
this.currentInterval = profile.minInterval;
|
|
30873
|
-
const sent = this.deps.sendScreenshotBuffer(
|
|
31323
|
+
const sent = this.deps.sendScreenshotBuffer(normalizedBuf);
|
|
30874
31324
|
if (this.debugCount <= 3 || anyNeedsFirstFrame) {
|
|
30875
|
-
LOG.debug("Screenshot", `sent: ${
|
|
31325
|
+
LOG.debug("Screenshot", `sent: ${normalizedBuf.length} bytes, delivered=${sent}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
30876
31326
|
}
|
|
30877
31327
|
}
|
|
30878
31328
|
} else {
|
|
@@ -30920,6 +31370,28 @@ var init_screenshot_controller = __esm({
|
|
|
30920
31370
|
}
|
|
30921
31371
|
return h;
|
|
30922
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
|
+
}
|
|
30923
31395
|
};
|
|
30924
31396
|
}
|
|
30925
31397
|
});
|
|
@@ -30982,7 +31454,7 @@ var init_adhdev_daemon = __esm({
|
|
|
30982
31454
|
fs11 = __toESM(require("fs"));
|
|
30983
31455
|
path14 = __toESM(require("path"));
|
|
30984
31456
|
import_chalk2 = __toESM(require("chalk"));
|
|
30985
|
-
pkgVersion = "0.6.
|
|
31457
|
+
pkgVersion = "0.6.55";
|
|
30986
31458
|
if (pkgVersion === "unknown") {
|
|
30987
31459
|
try {
|
|
30988
31460
|
const possiblePaths = [
|