adhdev 0.8.15 → 0.8.16
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 +331 -56
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +254 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -6721,6 +6721,40 @@ function normalizeScreenSnapshot(text) {
|
|
|
6721
6721
|
function normalizeComparableMessageContent(text) {
|
|
6722
6722
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
6723
6723
|
}
|
|
6724
|
+
function trimPromptEchoPrefix(text, promptText) {
|
|
6725
|
+
const prompt = normalizeComparableMessageContent(String(promptText || ""));
|
|
6726
|
+
if (!prompt) return String(text || "");
|
|
6727
|
+
const lines = String(text || "").split(/\r\n|\n|\r/g);
|
|
6728
|
+
let dropCount = 0;
|
|
6729
|
+
for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
|
|
6730
|
+
const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
|
|
6731
|
+
if (!fragment) {
|
|
6732
|
+
if (dropCount === index) dropCount = index + 1;
|
|
6733
|
+
continue;
|
|
6734
|
+
}
|
|
6735
|
+
const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
|
|
6736
|
+
const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
|
|
6737
|
+
if (canBePromptEcho && prompt.includes(fragment)) {
|
|
6738
|
+
dropCount = index + 1;
|
|
6739
|
+
continue;
|
|
6740
|
+
}
|
|
6741
|
+
break;
|
|
6742
|
+
}
|
|
6743
|
+
return lines.slice(dropCount).join("\n").trim();
|
|
6744
|
+
}
|
|
6745
|
+
function getLastUserPromptText(messages) {
|
|
6746
|
+
const items = Array.isArray(messages) ? messages : [];
|
|
6747
|
+
for (let index = items.length - 1; index >= 0; index -= 1) {
|
|
6748
|
+
const message = items[index];
|
|
6749
|
+
if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
|
|
6750
|
+
return message.content;
|
|
6751
|
+
}
|
|
6752
|
+
}
|
|
6753
|
+
return "";
|
|
6754
|
+
}
|
|
6755
|
+
function looksLikeConfirmOnlyLabel(label) {
|
|
6756
|
+
return /^(?:continue|confirm|ok|yes|trust|proceed|enter)$/i.test(String(label || "").trim());
|
|
6757
|
+
}
|
|
6724
6758
|
function parsePatternEntry(x) {
|
|
6725
6759
|
if (x instanceof RegExp) return x;
|
|
6726
6760
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -6857,6 +6891,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
6857
6891
|
submitRetryUsed = false;
|
|
6858
6892
|
submitRetryPromptSnippet = "";
|
|
6859
6893
|
idleFinishCandidate = null;
|
|
6894
|
+
finishRetryTimer = null;
|
|
6895
|
+
finishRetryCount = 0;
|
|
6860
6896
|
// Resize redraw suppression
|
|
6861
6897
|
resizeSuppressUntil = 0;
|
|
6862
6898
|
// Debug: status transition history
|
|
@@ -6878,6 +6914,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
6878
6914
|
static MAX_TRACE_ENTRIES = 250;
|
|
6879
6915
|
providerResolutionMeta;
|
|
6880
6916
|
static IDLE_FINISH_CONFIRM_MS = 900;
|
|
6917
|
+
static FINISH_RETRY_DELAY_MS = 300;
|
|
6918
|
+
static MAX_FINISH_RETRIES = 2;
|
|
6881
6919
|
syncMessageViews() {
|
|
6882
6920
|
this.messages = [...this.committedMessages];
|
|
6883
6921
|
this.structuredMessages = [...this.committedMessages];
|
|
@@ -6937,7 +6975,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
6937
6975
|
recentBuffer: buffer.slice(-1e3) || this.recentOutputBuffer,
|
|
6938
6976
|
screenText: this.terminalScreen.getText(),
|
|
6939
6977
|
messages: [...baseMessages],
|
|
6940
|
-
partialResponse
|
|
6978
|
+
partialResponse,
|
|
6979
|
+
promptText: scope?.prompt || ""
|
|
6941
6980
|
};
|
|
6942
6981
|
}
|
|
6943
6982
|
setStatus(status, trigger) {
|
|
@@ -7180,6 +7219,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
7180
7219
|
this.terminalScreen.reset(24, 80);
|
|
7181
7220
|
this.pendingTerminalQueryTail = "";
|
|
7182
7221
|
this.currentTurnScope = null;
|
|
7222
|
+
this.finishRetryCount = 0;
|
|
7223
|
+
if (this.finishRetryTimer) {
|
|
7224
|
+
clearTimeout(this.finishRetryTimer);
|
|
7225
|
+
this.finishRetryTimer = null;
|
|
7226
|
+
}
|
|
7183
7227
|
this.ready = false;
|
|
7184
7228
|
await this.ptyProcess.ready;
|
|
7185
7229
|
this.recordTrace("ready", {
|
|
@@ -7226,11 +7270,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
7226
7270
|
if (this.startupParseGate) {
|
|
7227
7271
|
this.startupBuffer += cleanData;
|
|
7228
7272
|
const elapsed = Date.now() - this.spawnAt;
|
|
7229
|
-
const scriptStatus = this.runDetectStatus(this.startupBuffer);
|
|
7230
7273
|
const screenText = this.terminalScreen.getText() || "";
|
|
7274
|
+
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7275
|
+
const scriptStatus = startupModal ? "waiting_approval" : this.runDetectStatus(this.startupBuffer);
|
|
7231
7276
|
const hasInteractivePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
7232
7277
|
const startupStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7233
|
-
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
7278
|
+
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || !!startupModal && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
7234
7279
|
if (isReady) {
|
|
7235
7280
|
this.startupParseGate = false;
|
|
7236
7281
|
this.ready = true;
|
|
@@ -7262,7 +7307,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
7262
7307
|
this.approvalExitTimeout = setTimeout(() => {
|
|
7263
7308
|
if (this.currentStatus !== "waiting_approval") return;
|
|
7264
7309
|
const tail = this.recentOutputBuffer;
|
|
7265
|
-
const
|
|
7310
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
7311
|
+
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7312
|
+
const modal = this.runParseApproval(tail) || startupModal;
|
|
7266
7313
|
const stillWaiting = this.runDetectStatus(tail) === "waiting_approval" || !!modal;
|
|
7267
7314
|
if (stillWaiting) {
|
|
7268
7315
|
this.activeModal = modal || this.activeModal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
@@ -7282,6 +7329,63 @@ var init_provider_cli_adapter = __esm({
|
|
|
7282
7329
|
if (!text.trim()) return false;
|
|
7283
7330
|
return /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(text) || /⏎\s+send/i.test(text) || /\?\s*for\s*shortcuts/i.test(text) || /Type your message(?:\s+or\s+@path\/to\/file)?/i.test(text) || /workspace\s*\(\/directory\)/i.test(text) || /for\s*shortcuts/i.test(text);
|
|
7284
7331
|
}
|
|
7332
|
+
looksLikeVisibleAssistantCandidate(screenText) {
|
|
7333
|
+
const lines = sanitizeTerminalText(String(screenText || "")).split(/\r\n|\n|\r/g);
|
|
7334
|
+
for (const line of lines) {
|
|
7335
|
+
const trimmed = String(line || "").trim();
|
|
7336
|
+
if (!trimmed) continue;
|
|
7337
|
+
if (/^➜\s+\S+/.test(trimmed)) continue;
|
|
7338
|
+
if (/^Update available!/i.test(trimmed)) continue;
|
|
7339
|
+
if (/Claude Code v\d/i.test(trimmed)) continue;
|
|
7340
|
+
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) continue;
|
|
7341
|
+
if (/^[◐◑◒◓◴◵◶◷◸◹◺◿].*\/effort/i.test(trimmed)) continue;
|
|
7342
|
+
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+$/.test(trimmed)) continue;
|
|
7343
|
+
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) continue;
|
|
7344
|
+
const assistantMatch = trimmed.match(/^⏺\s+(.+)$/);
|
|
7345
|
+
if (!assistantMatch) continue;
|
|
7346
|
+
const content = assistantMatch[1].trim();
|
|
7347
|
+
if (!content) continue;
|
|
7348
|
+
if (/^(?:Bash|Read|Write|Edit|MultiEdit|Task|Glob|Grep|LS|NotebookEdit)\(/.test(content)) continue;
|
|
7349
|
+
if (/This command requires approval|Do you want to proceed|Allow once|Always allow/i.test(content)) continue;
|
|
7350
|
+
return true;
|
|
7351
|
+
}
|
|
7352
|
+
return false;
|
|
7353
|
+
}
|
|
7354
|
+
shouldRetryFinishResponse(commitResult) {
|
|
7355
|
+
if (!this.currentTurnScope) return false;
|
|
7356
|
+
if (this.currentStatus === "waiting_approval" || this.activeModal) return false;
|
|
7357
|
+
if (this.finishRetryCount >= _ProviderCliAdapter.MAX_FINISH_RETRIES) return false;
|
|
7358
|
+
if (commitResult.hasAssistant && commitResult.assistantContent.trim()) return false;
|
|
7359
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
7360
|
+
if (!this.looksLikeVisibleAssistantCandidate(screenText)) return false;
|
|
7361
|
+
const now = Date.now();
|
|
7362
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
7363
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7364
|
+
return quietForMs < 1200 || screenStableMs < 1200 || !commitResult.hasAssistant;
|
|
7365
|
+
}
|
|
7366
|
+
getStartupConfirmationModal(screenText) {
|
|
7367
|
+
const text = sanitizeTerminalText(String(screenText || ""));
|
|
7368
|
+
if (!text.trim()) return null;
|
|
7369
|
+
if (this.cliType === "claude-cli") {
|
|
7370
|
+
const hasTrustPrompt = /Quick safety check/i.test(text) || /Is this a project you trust/i.test(text) || /Do you trust (?:this project|the contents of this directory|the files in this folder)/i.test(text);
|
|
7371
|
+
const hasConfirmFooter = /Press Enter to (?:continue|confirm)/i.test(text) || /Enter to confirm/i.test(text) || /Esc to (?:cancel|exit)/i.test(text);
|
|
7372
|
+
if (hasTrustPrompt || hasConfirmFooter && /trust/i.test(text)) {
|
|
7373
|
+
return {
|
|
7374
|
+
message: "Confirm Claude Code project trust",
|
|
7375
|
+
buttons: ["Continue"]
|
|
7376
|
+
};
|
|
7377
|
+
}
|
|
7378
|
+
}
|
|
7379
|
+
return null;
|
|
7380
|
+
}
|
|
7381
|
+
shouldResolveModalWithEnter(modal, buttonIndex) {
|
|
7382
|
+
if (!modal || buttonIndex !== 0) return false;
|
|
7383
|
+
const buttons = Array.isArray(modal.buttons) ? modal.buttons : [];
|
|
7384
|
+
if (buttons.length !== 1) return false;
|
|
7385
|
+
const buttonLabel = String(buttons[0] || "").trim();
|
|
7386
|
+
const modalText = `${modal.message || ""} ${buttonLabel}`.trim();
|
|
7387
|
+
return looksLikeConfirmOnlyLabel(buttonLabel) || /Quick safety check|project trust|trust (?:this project|the contents of this directory|the files in this folder)|Enter to confirm/i.test(modalText);
|
|
7388
|
+
}
|
|
7285
7389
|
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
7286
7390
|
const startedAt = Date.now();
|
|
7287
7391
|
let loggedWait = false;
|
|
@@ -7331,9 +7435,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7331
7435
|
}
|
|
7332
7436
|
const tail = this.settledBuffer;
|
|
7333
7437
|
const screenText = this.terminalScreen.getText() || "";
|
|
7334
|
-
const
|
|
7438
|
+
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7439
|
+
const modal = this.runParseApproval(tail) || startupModal;
|
|
7335
7440
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
7336
|
-
const scriptStatus = rawScriptStatus;
|
|
7441
|
+
const scriptStatus = startupModal ? "waiting_approval" : rawScriptStatus;
|
|
7337
7442
|
const parsedTranscript = this.parseCurrentTranscript(
|
|
7338
7443
|
this.committedMessages,
|
|
7339
7444
|
this.responseBuffer,
|
|
@@ -7528,7 +7633,24 @@ var init_provider_cli_adapter = __esm({
|
|
|
7528
7633
|
this.recordTrace("finish_response", {
|
|
7529
7634
|
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
7530
7635
|
});
|
|
7531
|
-
this.commitCurrentTranscript();
|
|
7636
|
+
const commitResult = this.commitCurrentTranscript();
|
|
7637
|
+
if (this.shouldRetryFinishResponse(commitResult)) {
|
|
7638
|
+
this.finishRetryCount += 1;
|
|
7639
|
+
this.recordTrace("finish_response_retry", {
|
|
7640
|
+
retryCount: this.finishRetryCount,
|
|
7641
|
+
retryDelayMs: _ProviderCliAdapter.FINISH_RETRY_DELAY_MS,
|
|
7642
|
+
assistantContent: this.summarizeTraceText(commitResult.assistantContent, 220),
|
|
7643
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
7644
|
+
});
|
|
7645
|
+
if (this.finishRetryTimer) clearTimeout(this.finishRetryTimer);
|
|
7646
|
+
this.finishRetryTimer = setTimeout(() => {
|
|
7647
|
+
this.finishRetryTimer = null;
|
|
7648
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
7649
|
+
this.finishResponse();
|
|
7650
|
+
}
|
|
7651
|
+
}, _ProviderCliAdapter.FINISH_RETRY_DELAY_MS);
|
|
7652
|
+
return;
|
|
7653
|
+
}
|
|
7532
7654
|
if (this.responseTimeout) {
|
|
7533
7655
|
clearTimeout(this.responseTimeout);
|
|
7534
7656
|
this.responseTimeout = null;
|
|
@@ -7545,11 +7667,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
7545
7667
|
clearTimeout(this.submitRetryTimer);
|
|
7546
7668
|
this.submitRetryTimer = null;
|
|
7547
7669
|
}
|
|
7670
|
+
if (this.finishRetryTimer) {
|
|
7671
|
+
clearTimeout(this.finishRetryTimer);
|
|
7672
|
+
this.finishRetryTimer = null;
|
|
7673
|
+
}
|
|
7548
7674
|
this.responseBuffer = "";
|
|
7549
7675
|
this.isWaitingForResponse = false;
|
|
7550
7676
|
this.responseSettleIgnoreUntil = 0;
|
|
7551
7677
|
this.submitRetryUsed = false;
|
|
7552
7678
|
this.submitRetryPromptSnippet = "";
|
|
7679
|
+
this.finishRetryCount = 0;
|
|
7553
7680
|
this.currentTurnScope = null;
|
|
7554
7681
|
this.activeModal = null;
|
|
7555
7682
|
this.setStatus("idle", "response_finished");
|
|
@@ -7563,6 +7690,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
7563
7690
|
);
|
|
7564
7691
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
7565
7692
|
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
7693
|
+
const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
|
|
7694
|
+
if (promptForTrim) {
|
|
7695
|
+
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
7696
|
+
if (lastAssistantForTrim) {
|
|
7697
|
+
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
7566
7700
|
this.syncMessageViews();
|
|
7567
7701
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
7568
7702
|
this.recordTrace("commit_transcript", {
|
|
@@ -7578,7 +7712,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
7578
7712
|
`[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(this.summarizeTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
7579
7713
|
);
|
|
7580
7714
|
}
|
|
7715
|
+
return {
|
|
7716
|
+
hasAssistant: !!lastAssistant,
|
|
7717
|
+
assistantContent: lastAssistant?.content || ""
|
|
7718
|
+
};
|
|
7581
7719
|
}
|
|
7720
|
+
return {
|
|
7721
|
+
hasAssistant: false,
|
|
7722
|
+
assistantContent: ""
|
|
7723
|
+
};
|
|
7582
7724
|
}
|
|
7583
7725
|
// ─── Script Execution ──────────────────────────
|
|
7584
7726
|
runDetectStatus(text) {
|
|
@@ -7657,7 +7799,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
7657
7799
|
if (!this.cliScripts?.parseOutput) return null;
|
|
7658
7800
|
try {
|
|
7659
7801
|
const input = this.buildParseInput(baseMessages, partialResponse, scope);
|
|
7660
|
-
|
|
7802
|
+
const parsed = this.cliScripts.parseOutput(input);
|
|
7803
|
+
const promptForTrim = scope?.prompt || getLastUserPromptText(baseMessages);
|
|
7804
|
+
if (parsed && Array.isArray(parsed.messages) && promptForTrim) {
|
|
7805
|
+
const lastAssistant = [...parsed.messages].reverse().find((message) => message?.role === "assistant" && typeof message.content === "string");
|
|
7806
|
+
if (lastAssistant) {
|
|
7807
|
+
lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
|
|
7808
|
+
}
|
|
7809
|
+
}
|
|
7810
|
+
return parsed;
|
|
7661
7811
|
} catch (e) {
|
|
7662
7812
|
LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
|
|
7663
7813
|
return null;
|
|
@@ -7702,10 +7852,19 @@ ${data.message || ""}`.trim();
|
|
|
7702
7852
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
7703
7853
|
if (this.isWaitingForResponse) return;
|
|
7704
7854
|
await this.waitForInteractivePrompt();
|
|
7855
|
+
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
|
|
7856
|
+
if (blockingModal || this.currentStatus === "waiting_approval") {
|
|
7857
|
+
throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
|
|
7858
|
+
}
|
|
7705
7859
|
this.committedMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
7706
7860
|
this.syncMessageViews();
|
|
7707
7861
|
this.isWaitingForResponse = true;
|
|
7708
7862
|
this.responseBuffer = "";
|
|
7863
|
+
this.finishRetryCount = 0;
|
|
7864
|
+
if (this.finishRetryTimer) {
|
|
7865
|
+
clearTimeout(this.finishRetryTimer);
|
|
7866
|
+
this.finishRetryTimer = null;
|
|
7867
|
+
}
|
|
7709
7868
|
this.clearIdleFinishCandidate("send_message");
|
|
7710
7869
|
this.currentTurnScope = {
|
|
7711
7870
|
prompt: text,
|
|
@@ -7933,6 +8092,10 @@ ${data.message || ""}`.trim();
|
|
|
7933
8092
|
clearTimeout(this.submitRetryTimer);
|
|
7934
8093
|
this.submitRetryTimer = null;
|
|
7935
8094
|
}
|
|
8095
|
+
if (this.finishRetryTimer) {
|
|
8096
|
+
clearTimeout(this.finishRetryTimer);
|
|
8097
|
+
this.finishRetryTimer = null;
|
|
8098
|
+
}
|
|
7936
8099
|
if (this.responseTimeout) {
|
|
7937
8100
|
clearTimeout(this.responseTimeout);
|
|
7938
8101
|
this.responseTimeout = null;
|
|
@@ -7956,6 +8119,7 @@ ${data.message || ""}`.trim();
|
|
|
7956
8119
|
this.ptyOutputFlushTimer = null;
|
|
7957
8120
|
}
|
|
7958
8121
|
this.ptyOutputBuffer = "";
|
|
8122
|
+
this.finishRetryCount = 0;
|
|
7959
8123
|
if (this.ptyProcess) {
|
|
7960
8124
|
this.ptyProcess.write("");
|
|
7961
8125
|
setTimeout(() => {
|
|
@@ -7986,6 +8150,10 @@ ${data.message || ""}`.trim();
|
|
|
7986
8150
|
clearTimeout(this.submitRetryTimer);
|
|
7987
8151
|
this.submitRetryTimer = null;
|
|
7988
8152
|
}
|
|
8153
|
+
if (this.finishRetryTimer) {
|
|
8154
|
+
clearTimeout(this.finishRetryTimer);
|
|
8155
|
+
this.finishRetryTimer = null;
|
|
8156
|
+
}
|
|
7989
8157
|
if (this.responseTimeout) {
|
|
7990
8158
|
clearTimeout(this.responseTimeout);
|
|
7991
8159
|
this.responseTimeout = null;
|
|
@@ -8009,6 +8177,7 @@ ${data.message || ""}`.trim();
|
|
|
8009
8177
|
this.ptyOutputFlushTimer = null;
|
|
8010
8178
|
}
|
|
8011
8179
|
this.ptyOutputBuffer = "";
|
|
8180
|
+
this.finishRetryCount = 0;
|
|
8012
8181
|
if (this.ptyProcess) {
|
|
8013
8182
|
try {
|
|
8014
8183
|
if (typeof this.ptyProcess.detach === "function") {
|
|
@@ -8045,6 +8214,11 @@ ${data.message || ""}`.trim();
|
|
|
8045
8214
|
this.ptyOutputFlushTimer = null;
|
|
8046
8215
|
}
|
|
8047
8216
|
this.ptyOutputBuffer = "";
|
|
8217
|
+
if (this.finishRetryTimer) {
|
|
8218
|
+
clearTimeout(this.finishRetryTimer);
|
|
8219
|
+
this.finishRetryTimer = null;
|
|
8220
|
+
}
|
|
8221
|
+
this.finishRetryCount = 0;
|
|
8048
8222
|
this.terminalScreen.reset();
|
|
8049
8223
|
this.ptyProcess?.clearBuffer?.();
|
|
8050
8224
|
this.onStatusChange?.();
|
|
@@ -8064,10 +8238,11 @@ ${data.message || ""}`.trim();
|
|
|
8064
8238
|
}
|
|
8065
8239
|
resolveModal(buttonIndex) {
|
|
8066
8240
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !this.activeModal) return;
|
|
8241
|
+
const modal = this.activeModal;
|
|
8067
8242
|
this.clearIdleFinishCandidate("resolve_modal");
|
|
8068
8243
|
this.recordTrace("resolve_modal", {
|
|
8069
8244
|
buttonIndex,
|
|
8070
|
-
activeModal:
|
|
8245
|
+
activeModal: modal
|
|
8071
8246
|
});
|
|
8072
8247
|
this.activeModal = null;
|
|
8073
8248
|
this.lastApprovalResolvedAt = Date.now();
|
|
@@ -8078,7 +8253,9 @@ ${data.message || ""}`.trim();
|
|
|
8078
8253
|
}
|
|
8079
8254
|
this.setStatus("generating", "approval_resolved");
|
|
8080
8255
|
this.onStatusChange?.();
|
|
8081
|
-
if (
|
|
8256
|
+
if (this.shouldResolveModalWithEnter(modal, buttonIndex)) {
|
|
8257
|
+
this.ptyProcess.write("\r");
|
|
8258
|
+
} else if (buttonIndex in this.approvalKeys) {
|
|
8082
8259
|
this.ptyProcess.write(this.approvalKeys[buttonIndex]);
|
|
8083
8260
|
} else {
|
|
8084
8261
|
const DOWN = "\x1B[B";
|
|
@@ -30038,7 +30215,10 @@ function appendUpgradeLog(message) {
|
|
|
30038
30215
|
}
|
|
30039
30216
|
}
|
|
30040
30217
|
function getNpmExecutable() {
|
|
30041
|
-
return
|
|
30218
|
+
return "npm";
|
|
30219
|
+
}
|
|
30220
|
+
function getNpmExecOptions() {
|
|
30221
|
+
return { shell: process.platform === "win32" };
|
|
30042
30222
|
}
|
|
30043
30223
|
function killPid(pid) {
|
|
30044
30224
|
try {
|
|
@@ -30100,9 +30280,10 @@ function removeDaemonPidFile() {
|
|
|
30100
30280
|
}
|
|
30101
30281
|
}
|
|
30102
30282
|
function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
30103
|
-
const
|
|
30283
|
+
const npmExecOpts = getNpmExecOptions();
|
|
30284
|
+
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
30104
30285
|
if (!npmRoot) return;
|
|
30105
|
-
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8" }).trim();
|
|
30286
|
+
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
30106
30287
|
const binDir = process.platform === "win32" ? npmPrefix : path13.join(npmPrefix, "bin");
|
|
30107
30288
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
30108
30289
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
@@ -30163,7 +30344,8 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
30163
30344
|
{
|
|
30164
30345
|
encoding: "utf8",
|
|
30165
30346
|
stdio: "pipe",
|
|
30166
|
-
maxBuffer: 20 * 1024 * 1024
|
|
30347
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
30348
|
+
...getNpmExecOptions()
|
|
30167
30349
|
}
|
|
30168
30350
|
);
|
|
30169
30351
|
if (installOutput.trim()) {
|
|
@@ -33486,6 +33668,53 @@ async function runCliExerciseInternal(ctx, body) {
|
|
|
33486
33668
|
let lastModalKey = "";
|
|
33487
33669
|
let idleSince = 0;
|
|
33488
33670
|
let sawBusy = false;
|
|
33671
|
+
const noteStatus = (status) => {
|
|
33672
|
+
if (status !== lastStatus) {
|
|
33673
|
+
statusesSeen.push(status);
|
|
33674
|
+
lastStatus = status;
|
|
33675
|
+
}
|
|
33676
|
+
};
|
|
33677
|
+
const resolveActiveModalIfNeeded = (status, modal) => {
|
|
33678
|
+
if (!autoResolveApprovals || status !== "waiting_approval" || !modal || !Array.isArray(modal.buttons) || modal.buttons.length === 0) {
|
|
33679
|
+
return false;
|
|
33680
|
+
}
|
|
33681
|
+
const clampedIndex = Math.max(0, Math.min(Number(approvalButtonIndex) || 0, modal.buttons.length - 1));
|
|
33682
|
+
const modalKey = JSON.stringify({
|
|
33683
|
+
message: modal.message || "",
|
|
33684
|
+
buttons: modal.buttons,
|
|
33685
|
+
index: clampedIndex
|
|
33686
|
+
});
|
|
33687
|
+
if (modalKey === lastModalKey || typeof bundle?.adapter?.resolveModal !== "function") {
|
|
33688
|
+
return false;
|
|
33689
|
+
}
|
|
33690
|
+
lastModalKey = modalKey;
|
|
33691
|
+
approvalsResolved.push({
|
|
33692
|
+
at: Date.now(),
|
|
33693
|
+
buttonIndex: clampedIndex,
|
|
33694
|
+
label: modal.buttons[clampedIndex] || null
|
|
33695
|
+
});
|
|
33696
|
+
bundle.adapter.resolveModal(clampedIndex);
|
|
33697
|
+
return true;
|
|
33698
|
+
};
|
|
33699
|
+
const preflightStartedAt = Date.now();
|
|
33700
|
+
while (Date.now() - preflightStartedAt < Math.max(1e3, readyTimeoutMs)) {
|
|
33701
|
+
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
33702
|
+
if (!bundle) {
|
|
33703
|
+
throw new Error("CLI instance disappeared before exercise send");
|
|
33704
|
+
}
|
|
33705
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
33706
|
+
const trace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
33707
|
+
const status = String(debug?.status || bundle.target.status || "unknown");
|
|
33708
|
+
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
33709
|
+
noteStatus(status);
|
|
33710
|
+
if (resolveActiveModalIfNeeded(status, modal)) {
|
|
33711
|
+
await sleep(150);
|
|
33712
|
+
continue;
|
|
33713
|
+
}
|
|
33714
|
+
const startupParseGate = !!debug?.startupParseGate;
|
|
33715
|
+
if (status === "idle" && !startupParseGate) break;
|
|
33716
|
+
await sleep(150);
|
|
33717
|
+
}
|
|
33489
33718
|
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
33490
33719
|
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
33491
33720
|
await sleep(150);
|
|
@@ -33500,32 +33729,14 @@ async function runCliExerciseInternal(ctx, body) {
|
|
|
33500
33729
|
const sawSendMessage = traceEntries.some((entry) => entry?.type === "send_message");
|
|
33501
33730
|
const sawSubmitWrite = traceEntries.some((entry) => entry?.type === "submit_write");
|
|
33502
33731
|
const hasTurnStarted = sawSendMessage || sawSubmitWrite || !!debug?.currentTurnScope;
|
|
33503
|
-
|
|
33504
|
-
statusesSeen.push(status);
|
|
33505
|
-
lastStatus = status;
|
|
33506
|
-
}
|
|
33732
|
+
noteStatus(status);
|
|
33507
33733
|
if (status === "generating" || status === "waiting_approval") {
|
|
33508
33734
|
sawBusy = true;
|
|
33509
33735
|
idleSince = 0;
|
|
33510
33736
|
}
|
|
33511
33737
|
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
33512
|
-
if (
|
|
33513
|
-
|
|
33514
|
-
const modalKey = JSON.stringify({
|
|
33515
|
-
message: modal.message || "",
|
|
33516
|
-
buttons: modal.buttons,
|
|
33517
|
-
index: clampedIndex
|
|
33518
|
-
});
|
|
33519
|
-
if (modalKey !== lastModalKey && typeof bundle.adapter.resolveModal === "function") {
|
|
33520
|
-
lastModalKey = modalKey;
|
|
33521
|
-
approvalsResolved.push({
|
|
33522
|
-
at: Date.now(),
|
|
33523
|
-
buttonIndex: clampedIndex,
|
|
33524
|
-
label: modal.buttons[clampedIndex] || null
|
|
33525
|
-
});
|
|
33526
|
-
bundle.adapter.resolveModal(clampedIndex);
|
|
33527
|
-
continue;
|
|
33528
|
-
}
|
|
33738
|
+
if (resolveActiveModalIfNeeded(status, modal)) {
|
|
33739
|
+
continue;
|
|
33529
33740
|
}
|
|
33530
33741
|
const traceCount = Number(trace?.entryCount || 0);
|
|
33531
33742
|
const hasProgress = hasTurnStarted && (traceCount > preTraceCount || statusesSeen.length > 1 || approvalsResolved.length > 0);
|
|
@@ -35185,6 +35396,13 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
35185
35396
|
lines.push("19. Literal string checks are allowed only for stable proper nouns or exact product chrome that cannot be expressed safely as a broader pattern. Everything else should generalize.");
|
|
35186
35397
|
lines.push("20. When a bug comes from noisy PTY text, first normalize and classify the line family; do NOT just append another special-case substring to the parser.");
|
|
35187
35398
|
lines.push("");
|
|
35399
|
+
if (verification?.focusAreas?.length) {
|
|
35400
|
+
lines.push("## Provider-Specific Focus Areas");
|
|
35401
|
+
for (const area of verification.focusAreas) {
|
|
35402
|
+
lines.push(`- ${area}`);
|
|
35403
|
+
}
|
|
35404
|
+
lines.push("");
|
|
35405
|
+
}
|
|
35188
35406
|
lines.push("## Task");
|
|
35189
35407
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
35190
35408
|
lines.push("");
|
|
@@ -46292,7 +46510,7 @@ var init_adhdev_daemon = __esm({
|
|
|
46292
46510
|
import_ws3 = require("ws");
|
|
46293
46511
|
import_chalk2 = __toESM(require("chalk"));
|
|
46294
46512
|
init_version();
|
|
46295
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.
|
|
46513
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.16" });
|
|
46296
46514
|
DANGEROUS_PATTERNS = [
|
|
46297
46515
|
/\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
|
|
46298
46516
|
/\bsudo\b/i,
|
|
@@ -48267,29 +48485,21 @@ function getDefaultAutoFixReference(category, type, providers) {
|
|
|
48267
48485
|
function escapeRegex2(value) {
|
|
48268
48486
|
return String(value || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
48269
48487
|
}
|
|
48270
|
-
|
|
48271
|
-
|
|
48272
|
-
|
|
48273
|
-
const escapedDir = escapeRegex2(normalizedDir);
|
|
48274
|
-
return {
|
|
48488
|
+
var CLI_PROVIDER_FIX_PROMPT = 'Create a file at tmp/adhdev_provider_fix_test.py that prints the current working directory and the squares of 1 through 5, then run python3 tmp/adhdev_provider_fix_test.py and tell me the exact output. Start the final answer with "Exact output:" and include the working directory plus the command stdout verbatim.';
|
|
48489
|
+
var CLI_AUTO_FIX_VERIFICATION_PROFILES = {
|
|
48490
|
+
"codex-cli": {
|
|
48275
48491
|
fixtureName: "codex-cli-provider-fix",
|
|
48276
|
-
request: {
|
|
48277
|
-
type,
|
|
48278
|
-
workingDir: providerDir,
|
|
48279
|
-
freshSession: true,
|
|
48280
|
-
autoLaunch: true,
|
|
48281
|
-
autoResolveApprovals: true,
|
|
48282
|
-
approvalButtonIndex: 0,
|
|
48283
|
-
timeoutMs: 9e4,
|
|
48284
|
-
traceLimit: 200,
|
|
48285
|
-
text: "Create a file at tmp/adhdev_provider_fix_test.py that prints the current working directory and the squares of 1 through 5, then run python3 tmp/adhdev_provider_fix_test.py and tell me the exact output."
|
|
48286
|
-
},
|
|
48287
48492
|
inspectFields: [
|
|
48288
48493
|
"debug.messages",
|
|
48289
48494
|
"trace.entries[].payload.parsedLastAssistant",
|
|
48290
48495
|
"trace.entries[].payload.detectStatus",
|
|
48291
48496
|
"trace.entries[].payload.parsedStatus"
|
|
48292
48497
|
],
|
|
48498
|
+
focusAreas: [
|
|
48499
|
+
"Startup or trust screens must be classified as approval/current chrome, not assistant transcript content.",
|
|
48500
|
+
"Prefer fixing provider.json submit/approval behavior before piling on parser heuristics.",
|
|
48501
|
+
"The final assistant transcript must preserve the exact stdout block and current working directory."
|
|
48502
|
+
],
|
|
48293
48503
|
lastAssistantMustContainAny: [
|
|
48294
48504
|
"Exact output:",
|
|
48295
48505
|
"1",
|
|
@@ -48298,16 +48508,81 @@ function getCliAutoFixVerification(type, providerDir) {
|
|
|
48298
48508
|
"16",
|
|
48299
48509
|
"25"
|
|
48300
48510
|
],
|
|
48301
|
-
lastAssistantMustMatchAny: [
|
|
48302
|
-
escapedDir
|
|
48303
|
-
],
|
|
48304
48511
|
lastAssistantMustNotContainAny: [
|
|
48305
48512
|
"Do you trust the contents of this directory?",
|
|
48306
48513
|
"OpenAI Codex",
|
|
48307
48514
|
"Tip: New",
|
|
48308
48515
|
"Summarize recent commits"
|
|
48309
48516
|
],
|
|
48310
|
-
description: "Codex CLI must classify startup/trust screens correctly, transition idle -> generating -> idle, and preserve the exact stdout block in the final assistant transcript."
|
|
48517
|
+
description: "Codex CLI must classify startup/trust screens correctly, transition idle -> generating -> idle, and preserve the exact stdout block in the final assistant transcript.",
|
|
48518
|
+
timeoutMs: 9e4
|
|
48519
|
+
},
|
|
48520
|
+
"claude-cli": {
|
|
48521
|
+
fixtureName: "claude-cli-provider-fix",
|
|
48522
|
+
inspectFields: [
|
|
48523
|
+
"statusesSeen",
|
|
48524
|
+
"approvalsResolved",
|
|
48525
|
+
"debug.messages",
|
|
48526
|
+
"trace.entries[].payload.detectStatus",
|
|
48527
|
+
"trace.entries[].payload.parsedStatus",
|
|
48528
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
48529
|
+
"trace.entries[].payload.approval"
|
|
48530
|
+
],
|
|
48531
|
+
focusAreas: [
|
|
48532
|
+
"Some environments show a startup trust or safety confirmation before the first prompt; treat that screen as waiting_approval, not assistant content.",
|
|
48533
|
+
"Single-action startup confirmations should resolve with Enter/confirm handling instead of assuming numbered approval options.",
|
|
48534
|
+
"Do not leak footer chrome like shortcuts help, version banners, /effort text, or startup trust wording into the parsed transcript."
|
|
48535
|
+
],
|
|
48536
|
+
lastAssistantMustContainAny: [
|
|
48537
|
+
"Exact output:",
|
|
48538
|
+
"1",
|
|
48539
|
+
"4",
|
|
48540
|
+
"9",
|
|
48541
|
+
"16",
|
|
48542
|
+
"25"
|
|
48543
|
+
],
|
|
48544
|
+
lastAssistantMustNotContainAny: [
|
|
48545
|
+
"Quick safety check",
|
|
48546
|
+
"Is this a project you trust",
|
|
48547
|
+
"Enter to confirm",
|
|
48548
|
+
"Claude Code",
|
|
48549
|
+
"Type your message"
|
|
48550
|
+
],
|
|
48551
|
+
description: "Claude CLI must survive startup trust/safety prompts, resolve them cleanly, transition back to generating/idle, and keep startup chrome out of the final assistant transcript.",
|
|
48552
|
+
timeoutMs: 12e4
|
|
48553
|
+
}
|
|
48554
|
+
};
|
|
48555
|
+
function getCliAutoFixVerification(type, providerDir) {
|
|
48556
|
+
const profile = CLI_AUTO_FIX_VERIFICATION_PROFILES[type];
|
|
48557
|
+
if (!profile) return null;
|
|
48558
|
+
const normalizedDir = providerDir.replace(/\\/g, "/");
|
|
48559
|
+
const escapedDir = escapeRegex2(normalizedDir);
|
|
48560
|
+
return {
|
|
48561
|
+
fixtureName: profile.fixtureName,
|
|
48562
|
+
request: {
|
|
48563
|
+
type,
|
|
48564
|
+
workingDir: providerDir,
|
|
48565
|
+
freshSession: true,
|
|
48566
|
+
autoLaunch: true,
|
|
48567
|
+
autoResolveApprovals: true,
|
|
48568
|
+
approvalButtonIndex: 0,
|
|
48569
|
+
timeoutMs: profile.timeoutMs ?? 9e4,
|
|
48570
|
+
traceLimit: 200,
|
|
48571
|
+
text: CLI_PROVIDER_FIX_PROMPT
|
|
48572
|
+
},
|
|
48573
|
+
inspectFields: profile.inspectFields || [
|
|
48574
|
+
"debug.messages",
|
|
48575
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
48576
|
+
"trace.entries[].payload.detectStatus",
|
|
48577
|
+
"trace.entries[].payload.parsedStatus"
|
|
48578
|
+
],
|
|
48579
|
+
focusAreas: profile.focusAreas || [],
|
|
48580
|
+
lastAssistantMustContainAny: profile.lastAssistantMustContainAny || [],
|
|
48581
|
+
lastAssistantMustMatchAny: [
|
|
48582
|
+
escapedDir
|
|
48583
|
+
],
|
|
48584
|
+
lastAssistantMustNotContainAny: profile.lastAssistantMustNotContainAny || [],
|
|
48585
|
+
description: profile.description
|
|
48311
48586
|
};
|
|
48312
48587
|
}
|
|
48313
48588
|
function hideCommand2(command) {
|