adhdev 0.9.6 → 0.9.9
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 +400 -488
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +400 -488
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -5813,6 +5813,18 @@ function validateRole(role, source, index) {
|
|
|
5813
5813
|
}
|
|
5814
5814
|
return role;
|
|
5815
5815
|
}
|
|
5816
|
+
function validateBubbleState(state, source, index) {
|
|
5817
|
+
if (typeof state !== "string" || !VALID_BUBBLE_STATES.includes(state)) {
|
|
5818
|
+
throw new Error(`${source}: messages[${index}].bubbleState must be one of ${VALID_BUBBLE_STATES.join(", ")}`);
|
|
5819
|
+
}
|
|
5820
|
+
return state;
|
|
5821
|
+
}
|
|
5822
|
+
function validateTurnStatus(turnStatus, source) {
|
|
5823
|
+
if (typeof turnStatus !== "string" || !VALID_TURN_STATUSES.includes(turnStatus)) {
|
|
5824
|
+
throw new Error(`${source}: turnStatus must be one of ${VALID_TURN_STATUSES.join(", ")}`);
|
|
5825
|
+
}
|
|
5826
|
+
return turnStatus;
|
|
5827
|
+
}
|
|
5816
5828
|
function validateMessageContent(content, source, index) {
|
|
5817
5829
|
if (typeof content === "string") return content;
|
|
5818
5830
|
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
@@ -5828,6 +5840,9 @@ function validateMessage(message, source, index) {
|
|
|
5828
5840
|
};
|
|
5829
5841
|
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
5830
5842
|
if (typeof message.id === "string") normalized.id = message.id;
|
|
5843
|
+
if (typeof message.bubbleId === "string") normalized.bubbleId = message.bubbleId;
|
|
5844
|
+
if (typeof message.providerUnitKey === "string") normalized.providerUnitKey = message.providerUnitKey;
|
|
5845
|
+
if (message.bubbleState !== void 0) normalized.bubbleState = validateBubbleState(message.bubbleState, source, index);
|
|
5831
5846
|
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
5832
5847
|
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
5833
5848
|
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
@@ -5895,6 +5910,8 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
|
5895
5910
|
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
5896
5911
|
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
5897
5912
|
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
5913
|
+
if (typeof raw.currentTurnId === "string") normalized.currentTurnId = raw.currentTurnId;
|
|
5914
|
+
if (raw.turnStatus !== void 0) normalized.turnStatus = validateTurnStatus(raw.turnStatus, source);
|
|
5898
5915
|
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
5899
5916
|
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
5900
5917
|
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
@@ -5907,13 +5924,15 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
|
5907
5924
|
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
5908
5925
|
return normalized;
|
|
5909
5926
|
}
|
|
5910
|
-
var VALID_STATUSES, VALID_ROLES;
|
|
5927
|
+
var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
|
|
5911
5928
|
var init_read_chat_contract = __esm({
|
|
5912
5929
|
"../../oss/packages/daemon-core/src/providers/read-chat-contract.ts"() {
|
|
5913
5930
|
"use strict";
|
|
5914
5931
|
init_contracts();
|
|
5915
5932
|
VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
5916
5933
|
VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
5934
|
+
VALID_BUBBLE_STATES = ["draft", "streaming", "final", "removed"];
|
|
5935
|
+
VALID_TURN_STATUSES = ["open", "waiting_approval", "complete", "error"];
|
|
5917
5936
|
}
|
|
5918
5937
|
});
|
|
5919
5938
|
|
|
@@ -8825,25 +8844,23 @@ async function handleResolveAction(h, args) {
|
|
|
8825
8844
|
const effectiveModal = statusModal || surfacedModal;
|
|
8826
8845
|
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
8827
8846
|
LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
|
|
8828
|
-
if (
|
|
8847
|
+
if (!effectiveModal) {
|
|
8829
8848
|
return { success: false, error: "Not in approval state" };
|
|
8830
8849
|
}
|
|
8831
|
-
const buttons = effectiveModal
|
|
8850
|
+
const buttons = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
|
|
8832
8851
|
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
8833
|
-
if (buttonIndex < 0) {
|
|
8852
|
+
if (buttonIndex < 0 && button) {
|
|
8834
8853
|
const btnLower = button.toLowerCase();
|
|
8835
8854
|
buttonIndex = buttons.findIndex((b) => b.toLowerCase().includes(btnLower));
|
|
8836
8855
|
}
|
|
8856
|
+
if (buttonIndex < 0 && (action === "reject" || action === "deny")) {
|
|
8857
|
+
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
8858
|
+
}
|
|
8859
|
+
if (buttonIndex < 0 && (action === "always" || /always/i.test(button))) {
|
|
8860
|
+
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
8861
|
+
}
|
|
8837
8862
|
if (buttonIndex < 0) {
|
|
8838
|
-
|
|
8839
|
-
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
8840
|
-
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
8841
|
-
} else if (action === "always" || /always/i.test(button)) {
|
|
8842
|
-
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
8843
|
-
if (buttonIndex < 0) buttonIndex = 1;
|
|
8844
|
-
} else {
|
|
8845
|
-
buttonIndex = 0;
|
|
8846
|
-
}
|
|
8863
|
+
return { success: false, error: "Approval action did not match any visible button" };
|
|
8847
8864
|
}
|
|
8848
8865
|
if (typeof adapter.resolveModal === "function") {
|
|
8849
8866
|
adapter.resolveModal(buttonIndex);
|
|
@@ -12088,8 +12105,35 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
12088
12105
|
function normalizeScreenSnapshot(text) {
|
|
12089
12106
|
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
12090
12107
|
}
|
|
12108
|
+
function shouldReflowComparableMessageLines(lines) {
|
|
12109
|
+
return Array.isArray(lines) && lines.length > 1 && lines.slice(0, -1).every((line) => String(line || "").trim().length >= 48) && !lines.some((line) => /^```/.test(line)) && !lines.some((line) => /^\|/.test(line)) && !lines.some((line) => /^\s*(?:[-*+] |\d+\.\s)/.test(line));
|
|
12110
|
+
}
|
|
12111
|
+
function joinComparableMessageLines(lines) {
|
|
12112
|
+
return lines.reduce((acc, line) => {
|
|
12113
|
+
const next = String(line || "").trim();
|
|
12114
|
+
if (!next) return acc;
|
|
12115
|
+
if (!acc) return next;
|
|
12116
|
+
if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
|
|
12117
|
+
return `${acc}${next}`;
|
|
12118
|
+
}
|
|
12119
|
+
if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
|
|
12120
|
+
return `${acc}${next}`;
|
|
12121
|
+
}
|
|
12122
|
+
const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
|
|
12123
|
+
const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
|
|
12124
|
+
if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
|
|
12125
|
+
return `${acc}${next}`;
|
|
12126
|
+
}
|
|
12127
|
+
return `${acc} ${next}`;
|
|
12128
|
+
}, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
|
|
12129
|
+
}
|
|
12091
12130
|
function normalizeComparableMessageContent(text) {
|
|
12092
|
-
|
|
12131
|
+
const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
12132
|
+
if (lines.length === 0) return "";
|
|
12133
|
+
if (shouldReflowComparableMessageLines(lines)) {
|
|
12134
|
+
return joinComparableMessageLines(lines);
|
|
12135
|
+
}
|
|
12136
|
+
return lines.join(" ").replace(/\s+/g, " ").trim();
|
|
12093
12137
|
}
|
|
12094
12138
|
function trimPromptEchoPrefix(text, promptText) {
|
|
12095
12139
|
const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
|
|
@@ -12122,9 +12166,6 @@ function getLastUserPromptText(messages) {
|
|
|
12122
12166
|
}
|
|
12123
12167
|
return "";
|
|
12124
12168
|
}
|
|
12125
|
-
function looksLikeConfirmOnlyLabel(label) {
|
|
12126
|
-
return /^(?:continue|confirm|ok|yes|trust|proceed|enter)$/i.test(String(label || "").trim());
|
|
12127
|
-
}
|
|
12128
12169
|
function parsePatternEntry(x) {
|
|
12129
12170
|
if (x instanceof RegExp) return x;
|
|
12130
12171
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -12151,7 +12192,7 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
12151
12192
|
}
|
|
12152
12193
|
};
|
|
12153
12194
|
}
|
|
12154
|
-
var os11, path10, import_child_process4, buildCliSpawnEnv;
|
|
12195
|
+
var os11, path10, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
|
|
12155
12196
|
var init_provider_cli_shared = __esm({
|
|
12156
12197
|
"../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
|
|
12157
12198
|
"use strict";
|
|
@@ -12160,6 +12201,32 @@ var init_provider_cli_shared = __esm({
|
|
|
12160
12201
|
import_child_process4 = require("child_process");
|
|
12161
12202
|
init_spawn_env();
|
|
12162
12203
|
buildCliSpawnEnv = sanitizeSpawnEnv;
|
|
12204
|
+
COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
|
|
12205
|
+
"a",
|
|
12206
|
+
"an",
|
|
12207
|
+
"and",
|
|
12208
|
+
"as",
|
|
12209
|
+
"at",
|
|
12210
|
+
"but",
|
|
12211
|
+
"by",
|
|
12212
|
+
"for",
|
|
12213
|
+
"from",
|
|
12214
|
+
"in",
|
|
12215
|
+
"into",
|
|
12216
|
+
"is",
|
|
12217
|
+
"it",
|
|
12218
|
+
"of",
|
|
12219
|
+
"on",
|
|
12220
|
+
"or",
|
|
12221
|
+
"that",
|
|
12222
|
+
"the",
|
|
12223
|
+
"their",
|
|
12224
|
+
"then",
|
|
12225
|
+
"this",
|
|
12226
|
+
"to",
|
|
12227
|
+
"was",
|
|
12228
|
+
"with"
|
|
12229
|
+
]);
|
|
12163
12230
|
}
|
|
12164
12231
|
});
|
|
12165
12232
|
|
|
@@ -12215,8 +12282,44 @@ function hydrateCliParsedMessages(parsedMessages, options) {
|
|
|
12215
12282
|
};
|
|
12216
12283
|
});
|
|
12217
12284
|
}
|
|
12285
|
+
function chooseMoreComparableCliMessage(left2, right2) {
|
|
12286
|
+
const leftComparable = normalizeComparableMessageContent(left2.content || "");
|
|
12287
|
+
const rightComparable = normalizeComparableMessageContent(right2.content || "");
|
|
12288
|
+
if (leftComparable && leftComparable === rightComparable) {
|
|
12289
|
+
const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
12290
|
+
const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
12291
|
+
return rightNewlines < leftNewlines ? right2 : left2;
|
|
12292
|
+
}
|
|
12293
|
+
return rightComparable.length > leftComparable.length ? right2 : left2;
|
|
12294
|
+
}
|
|
12295
|
+
function dedupeConsecutiveComparableCliMessages(messages) {
|
|
12296
|
+
const deduped = [];
|
|
12297
|
+
for (const message of messages) {
|
|
12298
|
+
const current = {
|
|
12299
|
+
...message,
|
|
12300
|
+
content: typeof message.content === "string" ? message.content : String(message.content || "")
|
|
12301
|
+
};
|
|
12302
|
+
const previous = deduped[deduped.length - 1];
|
|
12303
|
+
if (!previous) {
|
|
12304
|
+
deduped.push(current);
|
|
12305
|
+
continue;
|
|
12306
|
+
}
|
|
12307
|
+
const previousComparable = normalizeComparableMessageContent(previous.content || "");
|
|
12308
|
+
const currentComparable = normalizeComparableMessageContent(current.content || "");
|
|
12309
|
+
const sameRole = previous.role === current.role;
|
|
12310
|
+
const sameKind = (previous.kind || "standard") === (current.kind || "standard");
|
|
12311
|
+
const sameSender = (previous.senderName || "") === (current.senderName || "");
|
|
12312
|
+
const comparableMatch = previousComparable && previousComparable === currentComparable;
|
|
12313
|
+
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
12314
|
+
deduped[deduped.length - 1] = chooseMoreComparableCliMessage(previous, current);
|
|
12315
|
+
continue;
|
|
12316
|
+
}
|
|
12317
|
+
deduped.push(current);
|
|
12318
|
+
}
|
|
12319
|
+
return deduped;
|
|
12320
|
+
}
|
|
12218
12321
|
function normalizeCliParsedMessages(parsedMessages, options) {
|
|
12219
|
-
return hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
12322
|
+
return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
12220
12323
|
role: message.role,
|
|
12221
12324
|
content: message.content,
|
|
12222
12325
|
timestamp: message.timestamp,
|
|
@@ -12226,7 +12329,7 @@ function normalizeCliParsedMessages(parsedMessages, options) {
|
|
|
12226
12329
|
index: message.index,
|
|
12227
12330
|
meta: message.meta,
|
|
12228
12331
|
senderName: message.senderName
|
|
12229
|
-
}));
|
|
12332
|
+
})));
|
|
12230
12333
|
}
|
|
12231
12334
|
function buildCliParseInput(options) {
|
|
12232
12335
|
const {
|
|
@@ -12889,7 +12992,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12889
12992
|
if (!hasStartupOutput) return;
|
|
12890
12993
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
12891
12994
|
if (stableMs < 2e3) return;
|
|
12892
|
-
const startupModal = this.
|
|
12995
|
+
const startupModal = this.runParseApproval(this.recentOutputBuffer);
|
|
12893
12996
|
this.startupParseGate = false;
|
|
12894
12997
|
if (this.startupSettleTimer) {
|
|
12895
12998
|
clearTimeout(this.startupSettleTimer);
|
|
@@ -12946,11 +13049,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
12946
13049
|
if (this.currentStatus !== "waiting_approval") return;
|
|
12947
13050
|
const tail = this.recentOutputBuffer;
|
|
12948
13051
|
const screenText = this.terminalScreen.getText() || "";
|
|
12949
|
-
const
|
|
12950
|
-
const modal = this.runParseApproval(tail) || startupModal;
|
|
13052
|
+
const modal = this.runParseApproval(tail);
|
|
12951
13053
|
const stillWaiting = this.runDetectStatus(tail) === "waiting_approval" || !!modal;
|
|
12952
13054
|
if (stillWaiting) {
|
|
12953
|
-
|
|
13055
|
+
if (!modal) {
|
|
13056
|
+
LOG.warn("CLI", `[${this.cliType}] approval timeout check found no actionable modal; keeping approval state fail-closed`);
|
|
13057
|
+
this.activeModal = null;
|
|
13058
|
+
this.onStatusChange?.();
|
|
13059
|
+
this.armApprovalExitTimeout();
|
|
13060
|
+
return;
|
|
13061
|
+
}
|
|
13062
|
+
this.activeModal = modal;
|
|
12954
13063
|
this.onStatusChange?.();
|
|
12955
13064
|
this.armApprovalExitTimeout();
|
|
12956
13065
|
return;
|
|
@@ -12962,81 +13071,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
12962
13071
|
this.onStatusChange?.();
|
|
12963
13072
|
}, 6e4);
|
|
12964
13073
|
}
|
|
12965
|
-
looksLikeVisibleIdlePrompt(screenText) {
|
|
12966
|
-
const text = String(screenText || "");
|
|
12967
|
-
if (!text.trim()) return false;
|
|
12968
|
-
if (this.cliType === "codex-cli" && /(^|\n)\s*[❯›>]\s+(?:Find and fix a bug in @filename|Improve documentation in @filename|Use \/skills|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Run \/review on my current changes)(?:\n|$)/im.test(text)) {
|
|
12969
|
-
return true;
|
|
12970
|
-
}
|
|
12971
|
-
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);
|
|
12972
|
-
}
|
|
12973
|
-
findLastMatchingLineIndex(lines, predicate) {
|
|
12974
|
-
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
12975
|
-
if (predicate(lines[index])) return index;
|
|
12976
|
-
}
|
|
12977
|
-
return -1;
|
|
12978
|
-
}
|
|
12979
|
-
looksLikeClaudeGeneratingLine(line) {
|
|
12980
|
-
const trimmed = String(line || "").trim();
|
|
12981
|
-
if (!trimmed) return false;
|
|
12982
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) return false;
|
|
12983
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
|
|
12984
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+\S+.*\b(?:thinking|thought for \d+s?)\b/i.test(trimmed)) return true;
|
|
12985
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+[A-Z][A-Za-z-]{3,}ing\b.*(?:…|\.{3})/u.test(trimmed)) return true;
|
|
12986
|
-
if (/^[⏺•]\s+(?:Reading|Writing|Editing|Searching|Inspecting|Planning|Analyzing|Synthesizing|Drafting|Running|Listing|Scanning|Matching)\b.*(?:…|\.{3})/i.test(trimmed)) {
|
|
12987
|
-
return /ctrl\+o to expand/i.test(trimmed) || /\b\d+\s+(?:file|files|pattern|patterns|director(?:y|ies)|match|matches|result|results)\b/i.test(trimmed);
|
|
12988
|
-
}
|
|
12989
|
-
return false;
|
|
12990
|
-
}
|
|
12991
|
-
detectClaudeGeneratingOverride(screenText, tail) {
|
|
12992
|
-
if (this.cliType !== "claude-cli") return false;
|
|
12993
|
-
const source = sanitizeTerminalText(screenText || tail || "");
|
|
12994
|
-
if (!source.trim()) return false;
|
|
12995
|
-
const allLines = source.split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
12996
|
-
if (allLines.length === 0) return false;
|
|
12997
|
-
const recentLines = allLines.slice(-12);
|
|
12998
|
-
const promptIndex = this.findLastMatchingLineIndex(recentLines, (line) => /^[❯›>]\s*$/.test(line));
|
|
12999
|
-
const activeRegion = promptIndex >= 0 ? recentLines.slice(Math.max(0, promptIndex - 2), promptIndex) : recentLines;
|
|
13000
|
-
if (activeRegion.length === 0) return false;
|
|
13001
|
-
return activeRegion.some((line) => this.looksLikeClaudeGeneratingLine(line));
|
|
13002
|
-
}
|
|
13003
|
-
refineDetectedStatus(status, tail, screenText) {
|
|
13004
|
-
if (this.startupParseGate) {
|
|
13005
|
-
return this.getStartupConfirmationModal(screenText || "") ? "waiting_approval" : "starting";
|
|
13006
|
-
}
|
|
13007
|
-
if (status === "waiting_approval") return status;
|
|
13008
|
-
if (this.detectClaudeGeneratingOverride(screenText || "", tail)) return "generating";
|
|
13009
|
-
return status;
|
|
13010
|
-
}
|
|
13011
|
-
looksLikeVisibleAssistantCandidate(screenText) {
|
|
13012
|
-
const lines = sanitizeTerminalText(String(screenText || "")).split(/\r\n|\n|\r/g);
|
|
13013
|
-
for (const line of lines) {
|
|
13014
|
-
const trimmed = String(line || "").trim();
|
|
13015
|
-
if (!trimmed) continue;
|
|
13016
|
-
if (/^➜\s+\S+/.test(trimmed)) continue;
|
|
13017
|
-
if (/^Update available!/i.test(trimmed)) continue;
|
|
13018
|
-
if (/Claude Code v\d/i.test(trimmed)) continue;
|
|
13019
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) continue;
|
|
13020
|
-
if (/^[◐◑◒◓◴◵◶◷◸◹◺◿].*\/effort/i.test(trimmed)) continue;
|
|
13021
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+$/.test(trimmed)) continue;
|
|
13022
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) continue;
|
|
13023
|
-
const assistantMatch = trimmed.match(/^⏺\s+(.+)$/);
|
|
13024
|
-
if (!assistantMatch) continue;
|
|
13025
|
-
const content = assistantMatch[1].trim();
|
|
13026
|
-
if (!content) continue;
|
|
13027
|
-
if (/^(?:Bash|Read|Write|Edit|MultiEdit|Task|Glob|Grep|LS|NotebookEdit)\(/.test(content)) continue;
|
|
13028
|
-
if (/This command requires approval|Do you want to proceed|Allow once|Always allow/i.test(content)) continue;
|
|
13029
|
-
return true;
|
|
13030
|
-
}
|
|
13031
|
-
return false;
|
|
13032
|
-
}
|
|
13033
13074
|
shouldRetryFinishResponse(commitResult) {
|
|
13034
13075
|
if (!this.currentTurnScope) return false;
|
|
13035
13076
|
if (this.currentStatus === "waiting_approval" || this.activeModal) return false;
|
|
13036
13077
|
if (this.finishRetryCount >= _ProviderCliAdapter.MAX_FINISH_RETRIES) return false;
|
|
13037
13078
|
if (commitResult.hasAssistant && commitResult.assistantContent.trim()) return false;
|
|
13038
|
-
|
|
13039
|
-
if (!this.looksLikeVisibleAssistantCandidate(screenText)) return false;
|
|
13079
|
+
if (this.runDetectStatus(this.recentOutputBuffer) !== "idle") return false;
|
|
13040
13080
|
const now = Date.now();
|
|
13041
13081
|
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
13042
13082
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
@@ -13060,45 +13100,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
13060
13100
|
}
|
|
13061
13101
|
return false;
|
|
13062
13102
|
}
|
|
13063
|
-
getStartupConfirmationModal(screenText) {
|
|
13064
|
-
const text = sanitizeTerminalText(String(screenText || ""));
|
|
13065
|
-
if (!text.trim()) return null;
|
|
13066
|
-
if (this.cliType === "claude-cli") {
|
|
13067
|
-
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);
|
|
13068
|
-
const hasConfirmFooter = /Press Enter to (?:continue|confirm)/i.test(text) || /Enter to confirm/i.test(text) || /Esc to (?:cancel|exit)/i.test(text);
|
|
13069
|
-
if (hasTrustPrompt || hasConfirmFooter && /trust/i.test(text)) {
|
|
13070
|
-
return {
|
|
13071
|
-
message: "Confirm Claude Code project trust",
|
|
13072
|
-
buttons: ["Continue"]
|
|
13073
|
-
};
|
|
13074
|
-
}
|
|
13075
|
-
}
|
|
13076
|
-
return null;
|
|
13077
|
-
}
|
|
13078
|
-
shouldResolveModalWithEnter(modal, buttonIndex) {
|
|
13079
|
-
if (!modal || buttonIndex !== 0) return false;
|
|
13080
|
-
const buttons = Array.isArray(modal.buttons) ? modal.buttons : [];
|
|
13081
|
-
if (buttons.length !== 1) return false;
|
|
13082
|
-
const buttonLabel = String(buttons[0] || "").trim();
|
|
13083
|
-
return looksLikeConfirmOnlyLabel(buttonLabel);
|
|
13084
|
-
}
|
|
13085
13103
|
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
13086
13104
|
const startedAt = Date.now();
|
|
13087
13105
|
let loggedWait = false;
|
|
13088
13106
|
while (Date.now() - startedAt < maxWaitMs) {
|
|
13089
13107
|
this.resolveStartupState("interactive_wait");
|
|
13090
13108
|
const screenText = this.terminalScreen.getText() || "";
|
|
13091
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
13092
13109
|
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
13093
13110
|
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
13094
13111
|
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
13095
|
-
const
|
|
13096
|
-
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "generating";
|
|
13112
|
+
const interactiveReady = status === "idle" && stableMs >= 700 && recentlyOutput >= 350;
|
|
13097
13113
|
if (interactiveReady) {
|
|
13098
13114
|
if (loggedWait) {
|
|
13099
13115
|
LOG.info(
|
|
13100
13116
|
"CLI",
|
|
13101
|
-
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput}
|
|
13117
|
+
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput})`
|
|
13102
13118
|
);
|
|
13103
13119
|
}
|
|
13104
13120
|
return;
|
|
@@ -13107,7 +13123,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13107
13123
|
loggedWait = true;
|
|
13108
13124
|
LOG.info(
|
|
13109
13125
|
"CLI",
|
|
13110
|
-
`[${this.cliType}] Waiting for interactive prompt:
|
|
13126
|
+
`[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
13111
13127
|
);
|
|
13112
13128
|
}
|
|
13113
13129
|
await new Promise((resolve18) => setTimeout(resolve18, 50));
|
|
@@ -13118,13 +13134,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
13118
13134
|
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
13119
13135
|
);
|
|
13120
13136
|
}
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
const
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
}
|
|
13137
|
+
trimLastAssistantEcho(messages, prompt2) {
|
|
13138
|
+
if (!prompt2) return;
|
|
13139
|
+
const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
|
|
13140
|
+
if (last) last.content = trimPromptEchoPrefix(last.content, prompt2);
|
|
13141
|
+
}
|
|
13142
|
+
clearAllTimers() {
|
|
13128
13143
|
if (this.responseTimeout) {
|
|
13129
13144
|
clearTimeout(this.responseTimeout);
|
|
13130
13145
|
this.responseTimeout = null;
|
|
@@ -13137,10 +13152,38 @@ var init_provider_cli_adapter = __esm({
|
|
|
13137
13152
|
clearTimeout(this.approvalExitTimeout);
|
|
13138
13153
|
this.approvalExitTimeout = null;
|
|
13139
13154
|
}
|
|
13155
|
+
if (this.submitRetryTimer) {
|
|
13156
|
+
clearTimeout(this.submitRetryTimer);
|
|
13157
|
+
this.submitRetryTimer = null;
|
|
13158
|
+
}
|
|
13140
13159
|
if (this.finishRetryTimer) {
|
|
13141
13160
|
clearTimeout(this.finishRetryTimer);
|
|
13142
13161
|
this.finishRetryTimer = null;
|
|
13143
13162
|
}
|
|
13163
|
+
if (this.settleTimer) {
|
|
13164
|
+
clearTimeout(this.settleTimer);
|
|
13165
|
+
this.settleTimer = null;
|
|
13166
|
+
}
|
|
13167
|
+
if (this.pendingScriptStatusTimer) {
|
|
13168
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
13169
|
+
this.pendingScriptStatusTimer = null;
|
|
13170
|
+
}
|
|
13171
|
+
if (this.pendingOutputParseTimer) {
|
|
13172
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
13173
|
+
this.pendingOutputParseTimer = null;
|
|
13174
|
+
}
|
|
13175
|
+
if (this.ptyOutputFlushTimer) {
|
|
13176
|
+
clearTimeout(this.ptyOutputFlushTimer);
|
|
13177
|
+
this.ptyOutputFlushTimer = null;
|
|
13178
|
+
}
|
|
13179
|
+
}
|
|
13180
|
+
clearStaleIdleResponseGuard(reason) {
|
|
13181
|
+
const blockingModal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
13182
|
+
const isIdle = this.runDetectStatus(this.recentOutputBuffer) === "idle";
|
|
13183
|
+
if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !isIdle || !!blockingModal) {
|
|
13184
|
+
return false;
|
|
13185
|
+
}
|
|
13186
|
+
this.clearAllTimers();
|
|
13144
13187
|
this.clearIdleFinishCandidate(reason);
|
|
13145
13188
|
this.responseBuffer = "";
|
|
13146
13189
|
this.isWaitingForResponse = false;
|
|
@@ -13150,10 +13193,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13150
13193
|
this.finishRetryCount = 0;
|
|
13151
13194
|
this.currentTurnScope = null;
|
|
13152
13195
|
this.activeModal = null;
|
|
13153
|
-
this.recordTrace("stale_idle_response_cleared", {
|
|
13154
|
-
reason,
|
|
13155
|
-
screenText: summarizeCliTraceText(screenText, 240)
|
|
13156
|
-
});
|
|
13196
|
+
this.recordTrace("stale_idle_response_cleared", { reason });
|
|
13157
13197
|
return true;
|
|
13158
13198
|
}
|
|
13159
13199
|
hasMeaningfulResponseBuffer(promptSnippet) {
|
|
@@ -13188,16 +13228,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
13188
13228
|
if (this.startupParseGate) {
|
|
13189
13229
|
return;
|
|
13190
13230
|
}
|
|
13191
|
-
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
13192
13231
|
const parsedTranscript = this.parseCurrentTranscript(
|
|
13193
13232
|
this.committedMessages,
|
|
13194
13233
|
this.responseBuffer,
|
|
13195
13234
|
this.currentTurnScope
|
|
13196
13235
|
);
|
|
13197
13236
|
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
|
|
13198
|
-
const modal = this.runParseApproval(tail) || parsedModal
|
|
13237
|
+
const modal = this.runParseApproval(tail) || parsedModal;
|
|
13199
13238
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
13200
|
-
const scriptStatus =
|
|
13239
|
+
const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
|
|
13201
13240
|
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
13202
13241
|
committedMessages: this.committedMessages,
|
|
13203
13242
|
scope: this.currentTurnScope,
|
|
@@ -13252,15 +13291,44 @@ var init_provider_cli_adapter = __esm({
|
|
|
13252
13291
|
}
|
|
13253
13292
|
if (!scriptStatus) return;
|
|
13254
13293
|
const prevStatus = this.currentStatus;
|
|
13255
|
-
const
|
|
13294
|
+
const ctx = { now, screenText, modal, scriptStatus, parsedTranscript, parsedMessages, lastParsedAssistant, parsedShowsLiveAssistantProgress, prevStatus };
|
|
13295
|
+
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
13296
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
13297
|
+
LOG.info(
|
|
13298
|
+
"CLI",
|
|
13299
|
+
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)} scriptStatus=${String(scriptStatus || "")} parsedStatus=${String(parsedTranscript?.status || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
|
|
13300
|
+
);
|
|
13301
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedTranscript?.status === "idle" && !!lastParsedAssistant);
|
|
13302
|
+
if (shouldHoldGenerating) {
|
|
13303
|
+
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
13304
|
+
return;
|
|
13305
|
+
}
|
|
13306
|
+
if (scriptStatus === "waiting_approval") {
|
|
13307
|
+
this.applyWaitingApproval(ctx);
|
|
13308
|
+
return;
|
|
13309
|
+
}
|
|
13310
|
+
if (scriptStatus === "generating") {
|
|
13311
|
+
this.applyGenerating(ctx);
|
|
13312
|
+
return;
|
|
13313
|
+
}
|
|
13314
|
+
if (scriptStatus === "idle") {
|
|
13315
|
+
this.applyIdle(ctx, now);
|
|
13316
|
+
}
|
|
13317
|
+
}
|
|
13318
|
+
// Returns false if the caller should bail out (debounce pending).
|
|
13319
|
+
applyPendingScriptStatusDebounce(ctx) {
|
|
13320
|
+
const { now, scriptStatus, prevStatus } = ctx;
|
|
13321
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (scriptStatus === "generating" || scriptStatus === "waiting_approval");
|
|
13322
|
+
if (!shouldDebounce) {
|
|
13256
13323
|
this.pendingScriptStatus = null;
|
|
13257
13324
|
this.pendingScriptStatusSince = 0;
|
|
13258
13325
|
if (this.pendingScriptStatusTimer) {
|
|
13259
13326
|
clearTimeout(this.pendingScriptStatusTimer);
|
|
13260
13327
|
this.pendingScriptStatusTimer = null;
|
|
13261
13328
|
}
|
|
13262
|
-
|
|
13263
|
-
|
|
13329
|
+
return true;
|
|
13330
|
+
}
|
|
13331
|
+
const armPending = (delayMs) => {
|
|
13264
13332
|
if (this.pendingScriptStatusTimer) clearTimeout(this.pendingScriptStatusTimer);
|
|
13265
13333
|
this.pendingScriptStatusTimer = setTimeout(() => {
|
|
13266
13334
|
this.pendingScriptStatusTimer = null;
|
|
@@ -13268,200 +13336,187 @@ var init_provider_cli_adapter = __esm({
|
|
|
13268
13336
|
this.evaluateSettled();
|
|
13269
13337
|
}, delayMs);
|
|
13270
13338
|
};
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
13277
|
-
return;
|
|
13278
|
-
}
|
|
13279
|
-
const elapsed = now - this.pendingScriptStatusSince;
|
|
13280
|
-
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
13281
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
13282
|
-
return;
|
|
13283
|
-
}
|
|
13284
|
-
} else {
|
|
13285
|
-
clearPendingScriptStatus();
|
|
13286
|
-
}
|
|
13287
|
-
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
13288
|
-
const statusActivityHoldMs = this.getStatusActivityHoldMs();
|
|
13289
|
-
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
13290
|
-
const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
|
|
13291
|
-
if (this.currentTurnScope && this.cliType === "claude-cli") {
|
|
13292
|
-
LOG.info(
|
|
13293
|
-
"CLI",
|
|
13294
|
-
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} scriptStatus=${String(scriptStatus || "")} parsedStatus=${String(parsedTranscript?.status || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} visibleIdlePrompt=${String(visibleIdlePrompt)} visibleAssistantCandidate=${String(visibleAssistantCandidate)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
|
|
13295
|
-
);
|
|
13339
|
+
if (this.pendingScriptStatus !== scriptStatus) {
|
|
13340
|
+
this.pendingScriptStatus = scriptStatus;
|
|
13341
|
+
this.pendingScriptStatusSince = now;
|
|
13342
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
13343
|
+
return false;
|
|
13296
13344
|
}
|
|
13297
|
-
const
|
|
13298
|
-
if (
|
|
13299
|
-
|
|
13300
|
-
|
|
13301
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13302
|
-
this.idleTimeout = setTimeout(() => {
|
|
13303
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
13304
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13305
|
-
this.finishResponse();
|
|
13306
|
-
}
|
|
13307
|
-
}, this.timeouts.generatingIdle);
|
|
13308
|
-
this.recordTrace("hold_generating_recent_activity", {
|
|
13309
|
-
scriptStatus,
|
|
13310
|
-
recentInteractiveActivity,
|
|
13311
|
-
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
13312
|
-
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
13313
|
-
holdMs: statusActivityHoldMs,
|
|
13314
|
-
...buildCliTraceParseSnapshot({
|
|
13315
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
13316
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
13317
|
-
responseBuffer: this.responseBuffer,
|
|
13318
|
-
partialResponse: this.responseBuffer,
|
|
13319
|
-
scope: this.currentTurnScope
|
|
13320
|
-
})
|
|
13321
|
-
});
|
|
13322
|
-
this.onStatusChange?.();
|
|
13323
|
-
return;
|
|
13345
|
+
const elapsed = now - this.pendingScriptStatusSince;
|
|
13346
|
+
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
13347
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
13348
|
+
return false;
|
|
13324
13349
|
}
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
this.
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
13343
|
-
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
this.
|
|
13348
|
-
|
|
13350
|
+
return true;
|
|
13351
|
+
}
|
|
13352
|
+
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
13353
|
+
const { scriptStatus } = ctx;
|
|
13354
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
13355
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
13356
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13357
|
+
this.idleTimeout = setTimeout(() => {
|
|
13358
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
13359
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13360
|
+
this.finishResponse();
|
|
13361
|
+
}
|
|
13362
|
+
}, this.timeouts.generatingIdle);
|
|
13363
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
13364
|
+
scriptStatus,
|
|
13365
|
+
recentInteractiveActivity,
|
|
13366
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
13367
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
13368
|
+
holdMs: this.getStatusActivityHoldMs(),
|
|
13369
|
+
...buildCliTraceParseSnapshot({
|
|
13370
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
13371
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
13372
|
+
responseBuffer: this.responseBuffer,
|
|
13373
|
+
partialResponse: this.responseBuffer,
|
|
13374
|
+
scope: this.currentTurnScope
|
|
13375
|
+
})
|
|
13376
|
+
});
|
|
13377
|
+
this.onStatusChange?.();
|
|
13378
|
+
}
|
|
13379
|
+
applyWaitingApproval(ctx) {
|
|
13380
|
+
const { modal } = ctx;
|
|
13381
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
13382
|
+
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
13383
|
+
if (inCooldown && !modal) {
|
|
13384
|
+
if (this.approvalExitTimeout) {
|
|
13385
|
+
clearTimeout(this.approvalExitTimeout);
|
|
13386
|
+
this.approvalExitTimeout = null;
|
|
13349
13387
|
}
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
this.setStatus("
|
|
13353
|
-
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
13388
|
+
this.activeModal = null;
|
|
13389
|
+
if (this.isWaitingForResponse) {
|
|
13390
|
+
this.setStatus("generating", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
13354
13391
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13355
|
-
this.
|
|
13356
|
-
|
|
13357
|
-
|
|
13392
|
+
this.idleTimeout = setTimeout(() => {
|
|
13393
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
13394
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13395
|
+
this.finishResponse();
|
|
13396
|
+
}
|
|
13397
|
+
}, this.timeouts.generatingIdle);
|
|
13398
|
+
} else {
|
|
13399
|
+
this.setStatus("idle", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
13358
13400
|
}
|
|
13401
|
+
this.onStatusChange?.();
|
|
13402
|
+
return;
|
|
13359
13403
|
}
|
|
13360
|
-
if (
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
const noActiveTurn = !this.currentTurnScope;
|
|
13364
|
-
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText) || /accept edits on/i.test(effectiveScreenText) && (/Update available!/i.test(screenText) || /\/effort/i.test(screenText) || /^.*➜\s+\S+/m.test(effectiveScreenText));
|
|
13365
|
-
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
13404
|
+
if (!inCooldown) {
|
|
13405
|
+
if (!modal) {
|
|
13406
|
+
LOG.warn("CLI", `[${this.cliType}] detectStatus reported waiting_approval without parseApproval modal; ignoring non-actionable approval state`);
|
|
13366
13407
|
return;
|
|
13367
13408
|
}
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
this.approvalExitTimeout = null;
|
|
13372
|
-
}
|
|
13373
|
-
this.activeModal = null;
|
|
13374
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
13375
|
-
}
|
|
13376
|
-
if (!this.isWaitingForResponse) {
|
|
13377
|
-
this.isWaitingForResponse = true;
|
|
13378
|
-
this.responseBuffer = "";
|
|
13379
|
-
}
|
|
13380
|
-
this.setStatus("generating", "script_detect");
|
|
13409
|
+
this.isWaitingForResponse = true;
|
|
13410
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
13411
|
+
this.activeModal = modal;
|
|
13381
13412
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13382
|
-
this.
|
|
13383
|
-
if (this.isWaitingForResponse) {
|
|
13384
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13385
|
-
this.finishResponse();
|
|
13386
|
-
}
|
|
13387
|
-
}, this.timeouts.generatingIdle);
|
|
13413
|
+
this.armApprovalExitTimeout();
|
|
13388
13414
|
this.onStatusChange?.();
|
|
13415
|
+
}
|
|
13416
|
+
}
|
|
13417
|
+
applyGenerating(ctx) {
|
|
13418
|
+
const { screenText, modal, parsedShowsLiveAssistantProgress, prevStatus } = ctx;
|
|
13419
|
+
this.clearIdleFinishCandidate("generating");
|
|
13420
|
+
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
13421
|
+
const noActiveTurn = !this.currentTurnScope;
|
|
13422
|
+
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText) || /accept edits on/i.test(effectiveScreenText) && (/Update available!/i.test(screenText) || /\/effort/i.test(screenText) || /^.*➜\s+\S+/m.test(effectiveScreenText));
|
|
13423
|
+
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
13389
13424
|
return;
|
|
13390
13425
|
}
|
|
13391
|
-
if (
|
|
13392
|
-
if (
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
this.approvalExitTimeout = null;
|
|
13396
|
-
}
|
|
13397
|
-
this.activeModal = null;
|
|
13398
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
13426
|
+
if (prevStatus === "waiting_approval") {
|
|
13427
|
+
if (this.approvalExitTimeout) {
|
|
13428
|
+
clearTimeout(this.approvalExitTimeout);
|
|
13429
|
+
this.approvalExitTimeout = null;
|
|
13399
13430
|
}
|
|
13431
|
+
this.activeModal = null;
|
|
13432
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
13433
|
+
}
|
|
13434
|
+
if (!this.isWaitingForResponse) {
|
|
13435
|
+
this.isWaitingForResponse = true;
|
|
13436
|
+
this.responseBuffer = "";
|
|
13437
|
+
}
|
|
13438
|
+
this.setStatus("generating", "script_detect");
|
|
13439
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13440
|
+
this.idleTimeout = setTimeout(() => {
|
|
13400
13441
|
if (this.isWaitingForResponse) {
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13409
|
-
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13414
|
-
|
|
13415
|
-
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
hasModal: !!modal,
|
|
13420
|
-
idleQuietThresholdMs,
|
|
13421
|
-
idleStableThresholdMs,
|
|
13422
|
-
idleReady,
|
|
13423
|
-
idleFinishConfirmMs,
|
|
13424
|
-
idleFinishCandidate: candidate,
|
|
13425
|
-
candidateQuiet,
|
|
13426
|
-
canFinishImmediately,
|
|
13427
|
-
submitPendingUntil: this.submitPendingUntil,
|
|
13428
|
-
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
13429
|
-
...buildCliTraceParseSnapshot({
|
|
13430
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
13431
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
13432
|
-
responseBuffer: this.responseBuffer,
|
|
13433
|
-
partialResponse: this.responseBuffer,
|
|
13434
|
-
scope: this.currentTurnScope
|
|
13435
|
-
})
|
|
13436
|
-
});
|
|
13437
|
-
if (canFinishImmediately) {
|
|
13438
|
-
this.clearIdleFinishCandidate("finish_response");
|
|
13439
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13440
|
-
this.finishResponse();
|
|
13441
|
-
return;
|
|
13442
|
-
}
|
|
13443
|
-
if (idleReady) {
|
|
13444
|
-
if (!candidate) {
|
|
13445
|
-
this.armIdleFinishCandidate(assistantLength);
|
|
13446
|
-
return;
|
|
13447
|
-
}
|
|
13448
|
-
} else {
|
|
13449
|
-
this.clearIdleFinishCandidate("idle_not_ready");
|
|
13450
|
-
}
|
|
13451
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13452
|
-
this.idleTimeout = setTimeout(() => {
|
|
13453
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
13454
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13455
|
-
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
13456
|
-
this.finishResponse();
|
|
13457
|
-
}
|
|
13458
|
-
}, this.timeouts.idleFinish);
|
|
13459
|
-
} else if (prevStatus !== "idle") {
|
|
13442
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13443
|
+
this.finishResponse();
|
|
13444
|
+
}
|
|
13445
|
+
}, this.timeouts.generatingIdle);
|
|
13446
|
+
this.onStatusChange?.();
|
|
13447
|
+
}
|
|
13448
|
+
applyIdle(ctx, now) {
|
|
13449
|
+
const { screenText, modal, lastParsedAssistant, prevStatus } = ctx;
|
|
13450
|
+
if (prevStatus === "waiting_approval") {
|
|
13451
|
+
if (this.approvalExitTimeout) {
|
|
13452
|
+
clearTimeout(this.approvalExitTimeout);
|
|
13453
|
+
this.approvalExitTimeout = null;
|
|
13454
|
+
}
|
|
13455
|
+
this.activeModal = null;
|
|
13456
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
13457
|
+
}
|
|
13458
|
+
if (!this.isWaitingForResponse) {
|
|
13459
|
+
if (prevStatus !== "idle") {
|
|
13460
13460
|
this.clearIdleFinishCandidate("idle_without_response");
|
|
13461
13461
|
this.setStatus("idle", "script_detect");
|
|
13462
13462
|
this.onStatusChange?.();
|
|
13463
13463
|
}
|
|
13464
|
+
return;
|
|
13464
13465
|
}
|
|
13466
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
13467
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
13468
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
13469
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
13470
|
+
const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
|
|
13471
|
+
const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
|
|
13472
|
+
const idleReady = !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleFinishConfirmMs;
|
|
13473
|
+
const candidate = this.idleFinishCandidate;
|
|
13474
|
+
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
|
|
13475
|
+
this.recordTrace("idle_decision", {
|
|
13476
|
+
quietForMs,
|
|
13477
|
+
screenStableMs,
|
|
13478
|
+
hasAssistantTurn,
|
|
13479
|
+
assistantLength,
|
|
13480
|
+
hasModal: !!modal,
|
|
13481
|
+
idleQuietThresholdMs,
|
|
13482
|
+
idleStableThresholdMs: idleFinishConfirmMs,
|
|
13483
|
+
idleReady,
|
|
13484
|
+
idleFinishConfirmMs,
|
|
13485
|
+
idleFinishCandidate: candidate,
|
|
13486
|
+
candidateQuiet,
|
|
13487
|
+
canFinishImmediately: idleReady && candidateQuiet,
|
|
13488
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
13489
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
13490
|
+
...buildCliTraceParseSnapshot({
|
|
13491
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
13492
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
13493
|
+
responseBuffer: this.responseBuffer,
|
|
13494
|
+
partialResponse: this.responseBuffer,
|
|
13495
|
+
scope: this.currentTurnScope
|
|
13496
|
+
})
|
|
13497
|
+
});
|
|
13498
|
+
if (idleReady && candidateQuiet) {
|
|
13499
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
13500
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13501
|
+
this.finishResponse();
|
|
13502
|
+
return;
|
|
13503
|
+
}
|
|
13504
|
+
if (idleReady) {
|
|
13505
|
+
if (!candidate) {
|
|
13506
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
13507
|
+
return;
|
|
13508
|
+
}
|
|
13509
|
+
} else {
|
|
13510
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
13511
|
+
}
|
|
13512
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
13513
|
+
this.idleTimeout = setTimeout(() => {
|
|
13514
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
13515
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
13516
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
13517
|
+
this.finishResponse();
|
|
13518
|
+
}
|
|
13519
|
+
}, this.timeouts.idleFinish);
|
|
13465
13520
|
}
|
|
13466
13521
|
finishResponse() {
|
|
13467
13522
|
if (this.submitPendingUntil > Date.now()) return;
|
|
@@ -13500,26 +13555,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13500
13555
|
}, _ProviderCliAdapter.FINISH_RETRY_DELAY_MS);
|
|
13501
13556
|
return;
|
|
13502
13557
|
}
|
|
13503
|
-
|
|
13504
|
-
clearTimeout(this.responseTimeout);
|
|
13505
|
-
this.responseTimeout = null;
|
|
13506
|
-
}
|
|
13507
|
-
if (this.idleTimeout) {
|
|
13508
|
-
clearTimeout(this.idleTimeout);
|
|
13509
|
-
this.idleTimeout = null;
|
|
13510
|
-
}
|
|
13511
|
-
if (this.approvalExitTimeout) {
|
|
13512
|
-
clearTimeout(this.approvalExitTimeout);
|
|
13513
|
-
this.approvalExitTimeout = null;
|
|
13514
|
-
}
|
|
13515
|
-
if (this.submitRetryTimer) {
|
|
13516
|
-
clearTimeout(this.submitRetryTimer);
|
|
13517
|
-
this.submitRetryTimer = null;
|
|
13518
|
-
}
|
|
13519
|
-
if (this.finishRetryTimer) {
|
|
13520
|
-
clearTimeout(this.finishRetryTimer);
|
|
13521
|
-
this.finishRetryTimer = null;
|
|
13522
|
-
}
|
|
13558
|
+
this.clearAllTimers();
|
|
13523
13559
|
this.responseBuffer = "";
|
|
13524
13560
|
this.isWaitingForResponse = false;
|
|
13525
13561
|
this.responseSettleIgnoreUntil = 0;
|
|
@@ -13531,18 +13567,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
13531
13567
|
this.setStatus("idle", "response_finished");
|
|
13532
13568
|
this.onStatusChange?.();
|
|
13533
13569
|
}
|
|
13534
|
-
maybeCommitVisibleIdleTranscript(parsed
|
|
13570
|
+
maybeCommitVisibleIdleTranscript(parsed) {
|
|
13535
13571
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
13536
13572
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
13537
13573
|
if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
|
|
13538
13574
|
return false;
|
|
13539
13575
|
}
|
|
13540
|
-
if (options?.requireVisibleAssistantCandidate) {
|
|
13541
|
-
const candidateText = options.screenText || this.terminalScreen.getText() || "";
|
|
13542
|
-
if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
|
|
13543
|
-
return false;
|
|
13544
|
-
}
|
|
13545
|
-
}
|
|
13546
13576
|
const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
13547
13577
|
committedMessages: this.committedMessages,
|
|
13548
13578
|
scope: this.currentTurnScope,
|
|
@@ -13551,33 +13581,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
13551
13581
|
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
13552
13582
|
if (!visibleAssistant) return false;
|
|
13553
13583
|
this.committedMessages = hydratedForIdleCommit;
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
13557
|
-
if (lastAssistantForTrim) {
|
|
13558
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
13559
|
-
}
|
|
13560
|
-
}
|
|
13561
|
-
if (this.responseTimeout) {
|
|
13562
|
-
clearTimeout(this.responseTimeout);
|
|
13563
|
-
this.responseTimeout = null;
|
|
13564
|
-
}
|
|
13565
|
-
if (this.idleTimeout) {
|
|
13566
|
-
clearTimeout(this.idleTimeout);
|
|
13567
|
-
this.idleTimeout = null;
|
|
13568
|
-
}
|
|
13569
|
-
if (this.approvalExitTimeout) {
|
|
13570
|
-
clearTimeout(this.approvalExitTimeout);
|
|
13571
|
-
this.approvalExitTimeout = null;
|
|
13572
|
-
}
|
|
13573
|
-
if (this.submitRetryTimer) {
|
|
13574
|
-
clearTimeout(this.submitRetryTimer);
|
|
13575
|
-
this.submitRetryTimer = null;
|
|
13576
|
-
}
|
|
13577
|
-
if (this.finishRetryTimer) {
|
|
13578
|
-
clearTimeout(this.finishRetryTimer);
|
|
13579
|
-
this.finishRetryTimer = null;
|
|
13580
|
-
}
|
|
13584
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
13585
|
+
this.clearAllTimers();
|
|
13581
13586
|
this.syncMessageViews();
|
|
13582
13587
|
this.responseBuffer = "";
|
|
13583
13588
|
this.isWaitingForResponse = false;
|
|
@@ -13607,13 +13612,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13607
13612
|
scope: this.currentTurnScope,
|
|
13608
13613
|
lastOutputAt: this.lastOutputAt
|
|
13609
13614
|
});
|
|
13610
|
-
|
|
13611
|
-
if (promptForTrim) {
|
|
13612
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
13613
|
-
if (lastAssistantForTrim) {
|
|
13614
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
13615
|
-
}
|
|
13616
|
-
}
|
|
13615
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
13617
13616
|
this.syncMessageViews();
|
|
13618
13617
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
13619
13618
|
if (this.currentTurnScope) {
|
|
@@ -13671,7 +13670,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13671
13670
|
screen: buildCliScreenSnapshot(screenText),
|
|
13672
13671
|
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
13673
13672
|
});
|
|
13674
|
-
return
|
|
13673
|
+
return status;
|
|
13675
13674
|
} catch (e) {
|
|
13676
13675
|
LOG.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
13677
13676
|
return null;
|
|
@@ -13711,23 +13710,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
13711
13710
|
if (!inApprovalCooldown) {
|
|
13712
13711
|
return parsed;
|
|
13713
13712
|
}
|
|
13714
|
-
const
|
|
13715
|
-
const visibleModal = this.runParseApproval(recentBuffer) || startupModal;
|
|
13713
|
+
const visibleModal = this.runParseApproval(recentBuffer);
|
|
13716
13714
|
if (visibleModal) {
|
|
13717
13715
|
return parsed;
|
|
13718
13716
|
}
|
|
13719
13717
|
const detectedStatus = this.runDetectStatus(recentBuffer);
|
|
13720
|
-
const
|
|
13718
|
+
const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
|
|
13721
13719
|
return {
|
|
13722
13720
|
...parsed,
|
|
13723
|
-
status:
|
|
13721
|
+
status: resolvedStatus,
|
|
13724
13722
|
activeModal: null
|
|
13725
13723
|
};
|
|
13726
13724
|
}
|
|
13727
13725
|
// ─── Public API (CliAdapter) ───────────────────
|
|
13728
13726
|
getStatus() {
|
|
13729
|
-
const
|
|
13730
|
-
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
13727
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
13731
13728
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
13732
13729
|
let effectiveModal = startupModal || this.activeModal;
|
|
13733
13730
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
@@ -13808,8 +13805,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
13808
13805
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
13809
13806
|
}));
|
|
13810
13807
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
13811
|
-
const
|
|
13812
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, committedHydratedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && visibleIdlePrompt);
|
|
13808
|
+
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, committedHydratedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle");
|
|
13813
13809
|
if (shouldAdoptParsedIdleReplay) {
|
|
13814
13810
|
this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
13815
13811
|
committedMessages: this.committedMessages,
|
|
@@ -13938,17 +13934,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
13938
13934
|
if (parsed && typeof parsed === "object") {
|
|
13939
13935
|
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
13940
13936
|
}
|
|
13941
|
-
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
13942
|
-
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
13943
|
-
parsed.status = refinedStatus;
|
|
13944
|
-
}
|
|
13945
13937
|
const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
const lastAssistant = [...normalizedParsed.messages].reverse().find((message) => message?.role === "assistant" && typeof message.content === "string");
|
|
13949
|
-
if (lastAssistant) {
|
|
13950
|
-
lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
|
|
13951
|
-
}
|
|
13938
|
+
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
13939
|
+
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
13952
13940
|
}
|
|
13953
13941
|
this.parseErrorMessage = null;
|
|
13954
13942
|
return normalizedParsed;
|
|
@@ -13976,16 +13964,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
13976
13964
|
LOG.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
|
|
13977
13965
|
}
|
|
13978
13966
|
}
|
|
13979
|
-
if (!promptText
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
${data.explanation || ""}
|
|
13983
|
-
|
|
13984
|
-
${data.message || ""}`.trim();
|
|
13985
|
-
}
|
|
13986
|
-
if (promptText) {
|
|
13987
|
-
await this.sendMessage(promptText);
|
|
13967
|
+
if (!promptText) {
|
|
13968
|
+
LOG.warn("CLI", `[${this.cliType}] resolveAction skipped: provider script did not supply a prompt`);
|
|
13969
|
+
return;
|
|
13988
13970
|
}
|
|
13971
|
+
await this.sendMessage(promptText);
|
|
13989
13972
|
}
|
|
13990
13973
|
async sendMessage(text) {
|
|
13991
13974
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
@@ -14003,9 +13986,7 @@ ${data.message || ""}`.trim();
|
|
|
14003
13986
|
}
|
|
14004
13987
|
if (!this.ready) {
|
|
14005
13988
|
this.resolveStartupState("send_precheck");
|
|
14006
|
-
|
|
14007
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
14008
|
-
if (hasPrompt && this.currentStatus === "idle") {
|
|
13989
|
+
if (this.runDetectStatus(this.recentOutputBuffer) === "idle" && this.currentStatus === "idle") {
|
|
14009
13990
|
this.ready = true;
|
|
14010
13991
|
this.startupParseGate = false;
|
|
14011
13992
|
LOG.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
@@ -14111,7 +14092,10 @@ ${data.message || ""}`.trim();
|
|
|
14111
14092
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
14112
14093
|
const screenText2 = this.terminalScreen.getText();
|
|
14113
14094
|
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
14114
|
-
|
|
14095
|
+
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
14096
|
+
if (liveApproval) return;
|
|
14097
|
+
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
14098
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
14115
14099
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
14116
14100
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
14117
14101
|
this.recordTrace("submit_write", {
|
|
@@ -14148,6 +14132,10 @@ ${data.message || ""}`.trim();
|
|
|
14148
14132
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
14149
14133
|
const screenText = this.terminalScreen.getText();
|
|
14150
14134
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
14135
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
14136
|
+
if (liveApproval) return;
|
|
14137
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
14138
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
14151
14139
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
14152
14140
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
14153
14141
|
this.recordTrace("submit_write", {
|
|
@@ -14279,44 +14267,9 @@ ${data.message || ""}`.trim();
|
|
|
14279
14267
|
}
|
|
14280
14268
|
shutdown() {
|
|
14281
14269
|
this.clearIdleFinishCandidate("shutdown");
|
|
14282
|
-
|
|
14283
|
-
clearTimeout(this.settleTimer);
|
|
14284
|
-
this.settleTimer = null;
|
|
14285
|
-
}
|
|
14286
|
-
if (this.approvalExitTimeout) {
|
|
14287
|
-
clearTimeout(this.approvalExitTimeout);
|
|
14288
|
-
this.approvalExitTimeout = null;
|
|
14289
|
-
}
|
|
14290
|
-
if (this.submitRetryTimer) {
|
|
14291
|
-
clearTimeout(this.submitRetryTimer);
|
|
14292
|
-
this.submitRetryTimer = null;
|
|
14293
|
-
}
|
|
14294
|
-
if (this.finishRetryTimer) {
|
|
14295
|
-
clearTimeout(this.finishRetryTimer);
|
|
14296
|
-
this.finishRetryTimer = null;
|
|
14297
|
-
}
|
|
14298
|
-
if (this.responseTimeout) {
|
|
14299
|
-
clearTimeout(this.responseTimeout);
|
|
14300
|
-
this.responseTimeout = null;
|
|
14301
|
-
}
|
|
14302
|
-
if (this.idleTimeout) {
|
|
14303
|
-
clearTimeout(this.idleTimeout);
|
|
14304
|
-
this.idleTimeout = null;
|
|
14305
|
-
}
|
|
14306
|
-
if (this.pendingScriptStatusTimer) {
|
|
14307
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
14308
|
-
this.pendingScriptStatusTimer = null;
|
|
14309
|
-
}
|
|
14310
|
-
if (this.pendingOutputParseTimer) {
|
|
14311
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
14312
|
-
this.pendingOutputParseTimer = null;
|
|
14313
|
-
}
|
|
14270
|
+
this.clearAllTimers();
|
|
14314
14271
|
this.pendingOutputParseBuffer = "";
|
|
14315
14272
|
this.pendingTerminalQueryTail = "";
|
|
14316
|
-
if (this.ptyOutputFlushTimer) {
|
|
14317
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
14318
|
-
this.ptyOutputFlushTimer = null;
|
|
14319
|
-
}
|
|
14320
14273
|
this.ptyOutputBuffer = "";
|
|
14321
14274
|
this.finishRetryCount = 0;
|
|
14322
14275
|
if (this.ptyProcess) {
|
|
@@ -14337,44 +14290,9 @@ ${data.message || ""}`.trim();
|
|
|
14337
14290
|
}
|
|
14338
14291
|
detach() {
|
|
14339
14292
|
this.clearIdleFinishCandidate("detach");
|
|
14340
|
-
|
|
14341
|
-
clearTimeout(this.settleTimer);
|
|
14342
|
-
this.settleTimer = null;
|
|
14343
|
-
}
|
|
14344
|
-
if (this.approvalExitTimeout) {
|
|
14345
|
-
clearTimeout(this.approvalExitTimeout);
|
|
14346
|
-
this.approvalExitTimeout = null;
|
|
14347
|
-
}
|
|
14348
|
-
if (this.submitRetryTimer) {
|
|
14349
|
-
clearTimeout(this.submitRetryTimer);
|
|
14350
|
-
this.submitRetryTimer = null;
|
|
14351
|
-
}
|
|
14352
|
-
if (this.finishRetryTimer) {
|
|
14353
|
-
clearTimeout(this.finishRetryTimer);
|
|
14354
|
-
this.finishRetryTimer = null;
|
|
14355
|
-
}
|
|
14356
|
-
if (this.responseTimeout) {
|
|
14357
|
-
clearTimeout(this.responseTimeout);
|
|
14358
|
-
this.responseTimeout = null;
|
|
14359
|
-
}
|
|
14360
|
-
if (this.idleTimeout) {
|
|
14361
|
-
clearTimeout(this.idleTimeout);
|
|
14362
|
-
this.idleTimeout = null;
|
|
14363
|
-
}
|
|
14364
|
-
if (this.pendingScriptStatusTimer) {
|
|
14365
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
14366
|
-
this.pendingScriptStatusTimer = null;
|
|
14367
|
-
}
|
|
14368
|
-
if (this.pendingOutputParseTimer) {
|
|
14369
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
14370
|
-
this.pendingOutputParseTimer = null;
|
|
14371
|
-
}
|
|
14293
|
+
this.clearAllTimers();
|
|
14372
14294
|
this.pendingOutputParseBuffer = "";
|
|
14373
14295
|
this.pendingTerminalQueryTail = "";
|
|
14374
|
-
if (this.ptyOutputFlushTimer) {
|
|
14375
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
14376
|
-
this.ptyOutputFlushTimer = null;
|
|
14377
|
-
}
|
|
14378
14296
|
this.ptyOutputBuffer = "";
|
|
14379
14297
|
this.finishRetryCount = 0;
|
|
14380
14298
|
if (this.ptyProcess) {
|
|
@@ -14436,8 +14354,7 @@ ${data.message || ""}`.trim();
|
|
|
14436
14354
|
this.ptyProcess?.write(data);
|
|
14437
14355
|
}
|
|
14438
14356
|
resolveModal(buttonIndex) {
|
|
14439
|
-
|
|
14440
|
-
let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
14357
|
+
let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
14441
14358
|
if (!modal && typeof this.cliScripts?.parseOutput === "function") {
|
|
14442
14359
|
try {
|
|
14443
14360
|
const parsed = this.getScriptParsedStatus();
|
|
@@ -14468,12 +14385,7 @@ ${data.message || ""}`.trim();
|
|
|
14468
14385
|
}
|
|
14469
14386
|
this.setStatus("generating", "approval_resolved");
|
|
14470
14387
|
this.onStatusChange?.();
|
|
14471
|
-
|
|
14472
|
-
if (startupTrustModal && buttonIndex in this.approvalKeys) {
|
|
14473
|
-
this.ptyProcess.write(`${this.approvalKeys[buttonIndex]}\r`);
|
|
14474
|
-
} else if (this.shouldResolveModalWithEnter(modal, buttonIndex)) {
|
|
14475
|
-
this.ptyProcess.write("\r");
|
|
14476
|
-
} else if (buttonIndex in this.approvalKeys) {
|
|
14388
|
+
if (buttonIndex in this.approvalKeys) {
|
|
14477
14389
|
this.ptyProcess.write(this.approvalKeys[buttonIndex]);
|
|
14478
14390
|
} else {
|
|
14479
14391
|
const DOWN = "\x1B[B";
|
|
@@ -14493,7 +14405,7 @@ ${data.message || ""}`.trim();
|
|
|
14493
14405
|
}
|
|
14494
14406
|
getDebugState() {
|
|
14495
14407
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
14496
|
-
const startupModal = this.startupParseGate ? this.
|
|
14408
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
14497
14409
|
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
14498
14410
|
const effectiveReady = this.ready || !!startupModal;
|
|
14499
14411
|
return {
|
|
@@ -87180,7 +87092,7 @@ var init_adhdev_daemon = __esm({
|
|
|
87180
87092
|
init_version();
|
|
87181
87093
|
init_src();
|
|
87182
87094
|
init_runtime_defaults();
|
|
87183
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.
|
|
87095
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.9" });
|
|
87184
87096
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
87185
87097
|
localHttpServer = null;
|
|
87186
87098
|
localWss = null;
|