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/index.js
CHANGED
|
@@ -5293,6 +5293,18 @@ function validateRole(role, source, index) {
|
|
|
5293
5293
|
}
|
|
5294
5294
|
return role;
|
|
5295
5295
|
}
|
|
5296
|
+
function validateBubbleState(state, source, index) {
|
|
5297
|
+
if (typeof state !== "string" || !VALID_BUBBLE_STATES.includes(state)) {
|
|
5298
|
+
throw new Error(`${source}: messages[${index}].bubbleState must be one of ${VALID_BUBBLE_STATES.join(", ")}`);
|
|
5299
|
+
}
|
|
5300
|
+
return state;
|
|
5301
|
+
}
|
|
5302
|
+
function validateTurnStatus(turnStatus, source) {
|
|
5303
|
+
if (typeof turnStatus !== "string" || !VALID_TURN_STATUSES.includes(turnStatus)) {
|
|
5304
|
+
throw new Error(`${source}: turnStatus must be one of ${VALID_TURN_STATUSES.join(", ")}`);
|
|
5305
|
+
}
|
|
5306
|
+
return turnStatus;
|
|
5307
|
+
}
|
|
5296
5308
|
function validateMessageContent(content, source, index) {
|
|
5297
5309
|
if (typeof content === "string") return content;
|
|
5298
5310
|
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
@@ -5308,6 +5320,9 @@ function validateMessage(message, source, index) {
|
|
|
5308
5320
|
};
|
|
5309
5321
|
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
5310
5322
|
if (typeof message.id === "string") normalized.id = message.id;
|
|
5323
|
+
if (typeof message.bubbleId === "string") normalized.bubbleId = message.bubbleId;
|
|
5324
|
+
if (typeof message.providerUnitKey === "string") normalized.providerUnitKey = message.providerUnitKey;
|
|
5325
|
+
if (message.bubbleState !== void 0) normalized.bubbleState = validateBubbleState(message.bubbleState, source, index);
|
|
5311
5326
|
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
5312
5327
|
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
5313
5328
|
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
@@ -5375,6 +5390,8 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
|
5375
5390
|
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
5376
5391
|
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
5377
5392
|
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
5393
|
+
if (typeof raw.currentTurnId === "string") normalized.currentTurnId = raw.currentTurnId;
|
|
5394
|
+
if (raw.turnStatus !== void 0) normalized.turnStatus = validateTurnStatus(raw.turnStatus, source);
|
|
5378
5395
|
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
5379
5396
|
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
5380
5397
|
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
@@ -5387,13 +5404,15 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
|
5387
5404
|
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
5388
5405
|
return normalized;
|
|
5389
5406
|
}
|
|
5390
|
-
var VALID_STATUSES, VALID_ROLES;
|
|
5407
|
+
var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
|
|
5391
5408
|
var init_read_chat_contract = __esm({
|
|
5392
5409
|
"../../oss/packages/daemon-core/src/providers/read-chat-contract.ts"() {
|
|
5393
5410
|
"use strict";
|
|
5394
5411
|
init_contracts();
|
|
5395
5412
|
VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
5396
5413
|
VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
5414
|
+
VALID_BUBBLE_STATES = ["draft", "streaming", "final", "removed"];
|
|
5415
|
+
VALID_TURN_STATUSES = ["open", "waiting_approval", "complete", "error"];
|
|
5397
5416
|
}
|
|
5398
5417
|
});
|
|
5399
5418
|
|
|
@@ -8305,25 +8324,23 @@ async function handleResolveAction(h, args) {
|
|
|
8305
8324
|
const effectiveModal = statusModal || surfacedModal;
|
|
8306
8325
|
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
8307
8326
|
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"}`);
|
|
8308
|
-
if (
|
|
8327
|
+
if (!effectiveModal) {
|
|
8309
8328
|
return { success: false, error: "Not in approval state" };
|
|
8310
8329
|
}
|
|
8311
|
-
const buttons = effectiveModal
|
|
8330
|
+
const buttons = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
|
|
8312
8331
|
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
8313
|
-
if (buttonIndex < 0) {
|
|
8332
|
+
if (buttonIndex < 0 && button) {
|
|
8314
8333
|
const btnLower = button.toLowerCase();
|
|
8315
8334
|
buttonIndex = buttons.findIndex((b) => b.toLowerCase().includes(btnLower));
|
|
8316
8335
|
}
|
|
8336
|
+
if (buttonIndex < 0 && (action === "reject" || action === "deny")) {
|
|
8337
|
+
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
8338
|
+
}
|
|
8339
|
+
if (buttonIndex < 0 && (action === "always" || /always/i.test(button))) {
|
|
8340
|
+
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
8341
|
+
}
|
|
8317
8342
|
if (buttonIndex < 0) {
|
|
8318
|
-
|
|
8319
|
-
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
8320
|
-
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
8321
|
-
} else if (action === "always" || /always/i.test(button)) {
|
|
8322
|
-
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
8323
|
-
if (buttonIndex < 0) buttonIndex = 1;
|
|
8324
|
-
} else {
|
|
8325
|
-
buttonIndex = 0;
|
|
8326
|
-
}
|
|
8343
|
+
return { success: false, error: "Approval action did not match any visible button" };
|
|
8327
8344
|
}
|
|
8328
8345
|
if (typeof adapter.resolveModal === "function") {
|
|
8329
8346
|
adapter.resolveModal(buttonIndex);
|
|
@@ -11132,8 +11149,35 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
11132
11149
|
function normalizeScreenSnapshot(text) {
|
|
11133
11150
|
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
11134
11151
|
}
|
|
11152
|
+
function shouldReflowComparableMessageLines(lines) {
|
|
11153
|
+
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));
|
|
11154
|
+
}
|
|
11155
|
+
function joinComparableMessageLines(lines) {
|
|
11156
|
+
return lines.reduce((acc, line) => {
|
|
11157
|
+
const next = String(line || "").trim();
|
|
11158
|
+
if (!next) return acc;
|
|
11159
|
+
if (!acc) return next;
|
|
11160
|
+
if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
|
|
11161
|
+
return `${acc}${next}`;
|
|
11162
|
+
}
|
|
11163
|
+
if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
|
|
11164
|
+
return `${acc}${next}`;
|
|
11165
|
+
}
|
|
11166
|
+
const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
|
|
11167
|
+
const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
|
|
11168
|
+
if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
|
|
11169
|
+
return `${acc}${next}`;
|
|
11170
|
+
}
|
|
11171
|
+
return `${acc} ${next}`;
|
|
11172
|
+
}, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
|
|
11173
|
+
}
|
|
11135
11174
|
function normalizeComparableMessageContent(text) {
|
|
11136
|
-
|
|
11175
|
+
const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
11176
|
+
if (lines.length === 0) return "";
|
|
11177
|
+
if (shouldReflowComparableMessageLines(lines)) {
|
|
11178
|
+
return joinComparableMessageLines(lines);
|
|
11179
|
+
}
|
|
11180
|
+
return lines.join(" ").replace(/\s+/g, " ").trim();
|
|
11137
11181
|
}
|
|
11138
11182
|
function trimPromptEchoPrefix(text, promptText) {
|
|
11139
11183
|
const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
|
|
@@ -11166,9 +11210,6 @@ function getLastUserPromptText(messages) {
|
|
|
11166
11210
|
}
|
|
11167
11211
|
return "";
|
|
11168
11212
|
}
|
|
11169
|
-
function looksLikeConfirmOnlyLabel(label) {
|
|
11170
|
-
return /^(?:continue|confirm|ok|yes|trust|proceed|enter)$/i.test(String(label || "").trim());
|
|
11171
|
-
}
|
|
11172
11213
|
function parsePatternEntry(x) {
|
|
11173
11214
|
if (x instanceof RegExp) return x;
|
|
11174
11215
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -11195,7 +11236,7 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
11195
11236
|
}
|
|
11196
11237
|
};
|
|
11197
11238
|
}
|
|
11198
|
-
var os10, path9, import_child_process4, buildCliSpawnEnv;
|
|
11239
|
+
var os10, path9, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
|
|
11199
11240
|
var init_provider_cli_shared = __esm({
|
|
11200
11241
|
"../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
|
|
11201
11242
|
"use strict";
|
|
@@ -11204,6 +11245,32 @@ var init_provider_cli_shared = __esm({
|
|
|
11204
11245
|
import_child_process4 = require("child_process");
|
|
11205
11246
|
init_spawn_env();
|
|
11206
11247
|
buildCliSpawnEnv = sanitizeSpawnEnv;
|
|
11248
|
+
COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
|
|
11249
|
+
"a",
|
|
11250
|
+
"an",
|
|
11251
|
+
"and",
|
|
11252
|
+
"as",
|
|
11253
|
+
"at",
|
|
11254
|
+
"but",
|
|
11255
|
+
"by",
|
|
11256
|
+
"for",
|
|
11257
|
+
"from",
|
|
11258
|
+
"in",
|
|
11259
|
+
"into",
|
|
11260
|
+
"is",
|
|
11261
|
+
"it",
|
|
11262
|
+
"of",
|
|
11263
|
+
"on",
|
|
11264
|
+
"or",
|
|
11265
|
+
"that",
|
|
11266
|
+
"the",
|
|
11267
|
+
"their",
|
|
11268
|
+
"then",
|
|
11269
|
+
"this",
|
|
11270
|
+
"to",
|
|
11271
|
+
"was",
|
|
11272
|
+
"with"
|
|
11273
|
+
]);
|
|
11207
11274
|
}
|
|
11208
11275
|
});
|
|
11209
11276
|
|
|
@@ -11259,8 +11326,44 @@ function hydrateCliParsedMessages(parsedMessages, options) {
|
|
|
11259
11326
|
};
|
|
11260
11327
|
});
|
|
11261
11328
|
}
|
|
11329
|
+
function chooseMoreComparableCliMessage(left2, right2) {
|
|
11330
|
+
const leftComparable = normalizeComparableMessageContent(left2.content || "");
|
|
11331
|
+
const rightComparable = normalizeComparableMessageContent(right2.content || "");
|
|
11332
|
+
if (leftComparable && leftComparable === rightComparable) {
|
|
11333
|
+
const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
11334
|
+
const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
11335
|
+
return rightNewlines < leftNewlines ? right2 : left2;
|
|
11336
|
+
}
|
|
11337
|
+
return rightComparable.length > leftComparable.length ? right2 : left2;
|
|
11338
|
+
}
|
|
11339
|
+
function dedupeConsecutiveComparableCliMessages(messages) {
|
|
11340
|
+
const deduped = [];
|
|
11341
|
+
for (const message of messages) {
|
|
11342
|
+
const current = {
|
|
11343
|
+
...message,
|
|
11344
|
+
content: typeof message.content === "string" ? message.content : String(message.content || "")
|
|
11345
|
+
};
|
|
11346
|
+
const previous = deduped[deduped.length - 1];
|
|
11347
|
+
if (!previous) {
|
|
11348
|
+
deduped.push(current);
|
|
11349
|
+
continue;
|
|
11350
|
+
}
|
|
11351
|
+
const previousComparable = normalizeComparableMessageContent(previous.content || "");
|
|
11352
|
+
const currentComparable = normalizeComparableMessageContent(current.content || "");
|
|
11353
|
+
const sameRole = previous.role === current.role;
|
|
11354
|
+
const sameKind = (previous.kind || "standard") === (current.kind || "standard");
|
|
11355
|
+
const sameSender = (previous.senderName || "") === (current.senderName || "");
|
|
11356
|
+
const comparableMatch = previousComparable && previousComparable === currentComparable;
|
|
11357
|
+
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
11358
|
+
deduped[deduped.length - 1] = chooseMoreComparableCliMessage(previous, current);
|
|
11359
|
+
continue;
|
|
11360
|
+
}
|
|
11361
|
+
deduped.push(current);
|
|
11362
|
+
}
|
|
11363
|
+
return deduped;
|
|
11364
|
+
}
|
|
11262
11365
|
function normalizeCliParsedMessages(parsedMessages, options) {
|
|
11263
|
-
return hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
11366
|
+
return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
11264
11367
|
role: message.role,
|
|
11265
11368
|
content: message.content,
|
|
11266
11369
|
timestamp: message.timestamp,
|
|
@@ -11270,7 +11373,7 @@ function normalizeCliParsedMessages(parsedMessages, options) {
|
|
|
11270
11373
|
index: message.index,
|
|
11271
11374
|
meta: message.meta,
|
|
11272
11375
|
senderName: message.senderName
|
|
11273
|
-
}));
|
|
11376
|
+
})));
|
|
11274
11377
|
}
|
|
11275
11378
|
function buildCliParseInput(options) {
|
|
11276
11379
|
const {
|
|
@@ -11933,7 +12036,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
11933
12036
|
if (!hasStartupOutput) return;
|
|
11934
12037
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
11935
12038
|
if (stableMs < 2e3) return;
|
|
11936
|
-
const startupModal = this.
|
|
12039
|
+
const startupModal = this.runParseApproval(this.recentOutputBuffer);
|
|
11937
12040
|
this.startupParseGate = false;
|
|
11938
12041
|
if (this.startupSettleTimer) {
|
|
11939
12042
|
clearTimeout(this.startupSettleTimer);
|
|
@@ -11990,11 +12093,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
11990
12093
|
if (this.currentStatus !== "waiting_approval") return;
|
|
11991
12094
|
const tail = this.recentOutputBuffer;
|
|
11992
12095
|
const screenText = this.terminalScreen.getText() || "";
|
|
11993
|
-
const
|
|
11994
|
-
const modal = this.runParseApproval(tail) || startupModal;
|
|
12096
|
+
const modal = this.runParseApproval(tail);
|
|
11995
12097
|
const stillWaiting = this.runDetectStatus(tail) === "waiting_approval" || !!modal;
|
|
11996
12098
|
if (stillWaiting) {
|
|
11997
|
-
|
|
12099
|
+
if (!modal) {
|
|
12100
|
+
LOG.warn("CLI", `[${this.cliType}] approval timeout check found no actionable modal; keeping approval state fail-closed`);
|
|
12101
|
+
this.activeModal = null;
|
|
12102
|
+
this.onStatusChange?.();
|
|
12103
|
+
this.armApprovalExitTimeout();
|
|
12104
|
+
return;
|
|
12105
|
+
}
|
|
12106
|
+
this.activeModal = modal;
|
|
11998
12107
|
this.onStatusChange?.();
|
|
11999
12108
|
this.armApprovalExitTimeout();
|
|
12000
12109
|
return;
|
|
@@ -12006,81 +12115,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
12006
12115
|
this.onStatusChange?.();
|
|
12007
12116
|
}, 6e4);
|
|
12008
12117
|
}
|
|
12009
|
-
looksLikeVisibleIdlePrompt(screenText) {
|
|
12010
|
-
const text = String(screenText || "");
|
|
12011
|
-
if (!text.trim()) return false;
|
|
12012
|
-
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)) {
|
|
12013
|
-
return true;
|
|
12014
|
-
}
|
|
12015
|
-
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);
|
|
12016
|
-
}
|
|
12017
|
-
findLastMatchingLineIndex(lines, predicate) {
|
|
12018
|
-
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
12019
|
-
if (predicate(lines[index])) return index;
|
|
12020
|
-
}
|
|
12021
|
-
return -1;
|
|
12022
|
-
}
|
|
12023
|
-
looksLikeClaudeGeneratingLine(line) {
|
|
12024
|
-
const trimmed = String(line || "").trim();
|
|
12025
|
-
if (!trimmed) return false;
|
|
12026
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) return false;
|
|
12027
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
|
|
12028
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+\S+.*\b(?:thinking|thought for \d+s?)\b/i.test(trimmed)) return true;
|
|
12029
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+[A-Z][A-Za-z-]{3,}ing\b.*(?:…|\.{3})/u.test(trimmed)) return true;
|
|
12030
|
-
if (/^[⏺•]\s+(?:Reading|Writing|Editing|Searching|Inspecting|Planning|Analyzing|Synthesizing|Drafting|Running|Listing|Scanning|Matching)\b.*(?:…|\.{3})/i.test(trimmed)) {
|
|
12031
|
-
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);
|
|
12032
|
-
}
|
|
12033
|
-
return false;
|
|
12034
|
-
}
|
|
12035
|
-
detectClaudeGeneratingOverride(screenText, tail) {
|
|
12036
|
-
if (this.cliType !== "claude-cli") return false;
|
|
12037
|
-
const source = sanitizeTerminalText(screenText || tail || "");
|
|
12038
|
-
if (!source.trim()) return false;
|
|
12039
|
-
const allLines = source.split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
12040
|
-
if (allLines.length === 0) return false;
|
|
12041
|
-
const recentLines = allLines.slice(-12);
|
|
12042
|
-
const promptIndex = this.findLastMatchingLineIndex(recentLines, (line) => /^[❯›>]\s*$/.test(line));
|
|
12043
|
-
const activeRegion = promptIndex >= 0 ? recentLines.slice(Math.max(0, promptIndex - 2), promptIndex) : recentLines;
|
|
12044
|
-
if (activeRegion.length === 0) return false;
|
|
12045
|
-
return activeRegion.some((line) => this.looksLikeClaudeGeneratingLine(line));
|
|
12046
|
-
}
|
|
12047
|
-
refineDetectedStatus(status, tail, screenText) {
|
|
12048
|
-
if (this.startupParseGate) {
|
|
12049
|
-
return this.getStartupConfirmationModal(screenText || "") ? "waiting_approval" : "starting";
|
|
12050
|
-
}
|
|
12051
|
-
if (status === "waiting_approval") return status;
|
|
12052
|
-
if (this.detectClaudeGeneratingOverride(screenText || "", tail)) return "generating";
|
|
12053
|
-
return status;
|
|
12054
|
-
}
|
|
12055
|
-
looksLikeVisibleAssistantCandidate(screenText) {
|
|
12056
|
-
const lines = sanitizeTerminalText(String(screenText || "")).split(/\r\n|\n|\r/g);
|
|
12057
|
-
for (const line of lines) {
|
|
12058
|
-
const trimmed = String(line || "").trim();
|
|
12059
|
-
if (!trimmed) continue;
|
|
12060
|
-
if (/^➜\s+\S+/.test(trimmed)) continue;
|
|
12061
|
-
if (/^Update available!/i.test(trimmed)) continue;
|
|
12062
|
-
if (/Claude Code v\d/i.test(trimmed)) continue;
|
|
12063
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) continue;
|
|
12064
|
-
if (/^[◐◑◒◓◴◵◶◷◸◹◺◿].*\/effort/i.test(trimmed)) continue;
|
|
12065
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+$/.test(trimmed)) continue;
|
|
12066
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) continue;
|
|
12067
|
-
const assistantMatch = trimmed.match(/^⏺\s+(.+)$/);
|
|
12068
|
-
if (!assistantMatch) continue;
|
|
12069
|
-
const content = assistantMatch[1].trim();
|
|
12070
|
-
if (!content) continue;
|
|
12071
|
-
if (/^(?:Bash|Read|Write|Edit|MultiEdit|Task|Glob|Grep|LS|NotebookEdit)\(/.test(content)) continue;
|
|
12072
|
-
if (/This command requires approval|Do you want to proceed|Allow once|Always allow/i.test(content)) continue;
|
|
12073
|
-
return true;
|
|
12074
|
-
}
|
|
12075
|
-
return false;
|
|
12076
|
-
}
|
|
12077
12118
|
shouldRetryFinishResponse(commitResult) {
|
|
12078
12119
|
if (!this.currentTurnScope) return false;
|
|
12079
12120
|
if (this.currentStatus === "waiting_approval" || this.activeModal) return false;
|
|
12080
12121
|
if (this.finishRetryCount >= _ProviderCliAdapter.MAX_FINISH_RETRIES) return false;
|
|
12081
12122
|
if (commitResult.hasAssistant && commitResult.assistantContent.trim()) return false;
|
|
12082
|
-
|
|
12083
|
-
if (!this.looksLikeVisibleAssistantCandidate(screenText)) return false;
|
|
12123
|
+
if (this.runDetectStatus(this.recentOutputBuffer) !== "idle") return false;
|
|
12084
12124
|
const now = Date.now();
|
|
12085
12125
|
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
12086
12126
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
@@ -12104,45 +12144,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
12104
12144
|
}
|
|
12105
12145
|
return false;
|
|
12106
12146
|
}
|
|
12107
|
-
getStartupConfirmationModal(screenText) {
|
|
12108
|
-
const text = sanitizeTerminalText(String(screenText || ""));
|
|
12109
|
-
if (!text.trim()) return null;
|
|
12110
|
-
if (this.cliType === "claude-cli") {
|
|
12111
|
-
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);
|
|
12112
|
-
const hasConfirmFooter = /Press Enter to (?:continue|confirm)/i.test(text) || /Enter to confirm/i.test(text) || /Esc to (?:cancel|exit)/i.test(text);
|
|
12113
|
-
if (hasTrustPrompt || hasConfirmFooter && /trust/i.test(text)) {
|
|
12114
|
-
return {
|
|
12115
|
-
message: "Confirm Claude Code project trust",
|
|
12116
|
-
buttons: ["Continue"]
|
|
12117
|
-
};
|
|
12118
|
-
}
|
|
12119
|
-
}
|
|
12120
|
-
return null;
|
|
12121
|
-
}
|
|
12122
|
-
shouldResolveModalWithEnter(modal, buttonIndex) {
|
|
12123
|
-
if (!modal || buttonIndex !== 0) return false;
|
|
12124
|
-
const buttons = Array.isArray(modal.buttons) ? modal.buttons : [];
|
|
12125
|
-
if (buttons.length !== 1) return false;
|
|
12126
|
-
const buttonLabel = String(buttons[0] || "").trim();
|
|
12127
|
-
return looksLikeConfirmOnlyLabel(buttonLabel);
|
|
12128
|
-
}
|
|
12129
12147
|
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
12130
12148
|
const startedAt = Date.now();
|
|
12131
12149
|
let loggedWait = false;
|
|
12132
12150
|
while (Date.now() - startedAt < maxWaitMs) {
|
|
12133
12151
|
this.resolveStartupState("interactive_wait");
|
|
12134
12152
|
const screenText = this.terminalScreen.getText() || "";
|
|
12135
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
12136
12153
|
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
12137
12154
|
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
12138
12155
|
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
12139
|
-
const
|
|
12140
|
-
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "generating";
|
|
12156
|
+
const interactiveReady = status === "idle" && stableMs >= 700 && recentlyOutput >= 350;
|
|
12141
12157
|
if (interactiveReady) {
|
|
12142
12158
|
if (loggedWait) {
|
|
12143
12159
|
LOG.info(
|
|
12144
12160
|
"CLI",
|
|
12145
|
-
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput}
|
|
12161
|
+
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput})`
|
|
12146
12162
|
);
|
|
12147
12163
|
}
|
|
12148
12164
|
return;
|
|
@@ -12151,7 +12167,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12151
12167
|
loggedWait = true;
|
|
12152
12168
|
LOG.info(
|
|
12153
12169
|
"CLI",
|
|
12154
|
-
`[${this.cliType}] Waiting for interactive prompt:
|
|
12170
|
+
`[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
12155
12171
|
);
|
|
12156
12172
|
}
|
|
12157
12173
|
await new Promise((resolve16) => setTimeout(resolve16, 50));
|
|
@@ -12162,13 +12178,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
12162
12178
|
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
12163
12179
|
);
|
|
12164
12180
|
}
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
const
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
}
|
|
12181
|
+
trimLastAssistantEcho(messages, prompt2) {
|
|
12182
|
+
if (!prompt2) return;
|
|
12183
|
+
const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
|
|
12184
|
+
if (last) last.content = trimPromptEchoPrefix(last.content, prompt2);
|
|
12185
|
+
}
|
|
12186
|
+
clearAllTimers() {
|
|
12172
12187
|
if (this.responseTimeout) {
|
|
12173
12188
|
clearTimeout(this.responseTimeout);
|
|
12174
12189
|
this.responseTimeout = null;
|
|
@@ -12181,10 +12196,38 @@ var init_provider_cli_adapter = __esm({
|
|
|
12181
12196
|
clearTimeout(this.approvalExitTimeout);
|
|
12182
12197
|
this.approvalExitTimeout = null;
|
|
12183
12198
|
}
|
|
12199
|
+
if (this.submitRetryTimer) {
|
|
12200
|
+
clearTimeout(this.submitRetryTimer);
|
|
12201
|
+
this.submitRetryTimer = null;
|
|
12202
|
+
}
|
|
12184
12203
|
if (this.finishRetryTimer) {
|
|
12185
12204
|
clearTimeout(this.finishRetryTimer);
|
|
12186
12205
|
this.finishRetryTimer = null;
|
|
12187
12206
|
}
|
|
12207
|
+
if (this.settleTimer) {
|
|
12208
|
+
clearTimeout(this.settleTimer);
|
|
12209
|
+
this.settleTimer = null;
|
|
12210
|
+
}
|
|
12211
|
+
if (this.pendingScriptStatusTimer) {
|
|
12212
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
12213
|
+
this.pendingScriptStatusTimer = null;
|
|
12214
|
+
}
|
|
12215
|
+
if (this.pendingOutputParseTimer) {
|
|
12216
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
12217
|
+
this.pendingOutputParseTimer = null;
|
|
12218
|
+
}
|
|
12219
|
+
if (this.ptyOutputFlushTimer) {
|
|
12220
|
+
clearTimeout(this.ptyOutputFlushTimer);
|
|
12221
|
+
this.ptyOutputFlushTimer = null;
|
|
12222
|
+
}
|
|
12223
|
+
}
|
|
12224
|
+
clearStaleIdleResponseGuard(reason) {
|
|
12225
|
+
const blockingModal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
12226
|
+
const isIdle = this.runDetectStatus(this.recentOutputBuffer) === "idle";
|
|
12227
|
+
if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !isIdle || !!blockingModal) {
|
|
12228
|
+
return false;
|
|
12229
|
+
}
|
|
12230
|
+
this.clearAllTimers();
|
|
12188
12231
|
this.clearIdleFinishCandidate(reason);
|
|
12189
12232
|
this.responseBuffer = "";
|
|
12190
12233
|
this.isWaitingForResponse = false;
|
|
@@ -12194,10 +12237,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12194
12237
|
this.finishRetryCount = 0;
|
|
12195
12238
|
this.currentTurnScope = null;
|
|
12196
12239
|
this.activeModal = null;
|
|
12197
|
-
this.recordTrace("stale_idle_response_cleared", {
|
|
12198
|
-
reason,
|
|
12199
|
-
screenText: summarizeCliTraceText(screenText, 240)
|
|
12200
|
-
});
|
|
12240
|
+
this.recordTrace("stale_idle_response_cleared", { reason });
|
|
12201
12241
|
return true;
|
|
12202
12242
|
}
|
|
12203
12243
|
hasMeaningfulResponseBuffer(promptSnippet) {
|
|
@@ -12232,16 +12272,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
12232
12272
|
if (this.startupParseGate) {
|
|
12233
12273
|
return;
|
|
12234
12274
|
}
|
|
12235
|
-
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
12236
12275
|
const parsedTranscript = this.parseCurrentTranscript(
|
|
12237
12276
|
this.committedMessages,
|
|
12238
12277
|
this.responseBuffer,
|
|
12239
12278
|
this.currentTurnScope
|
|
12240
12279
|
);
|
|
12241
12280
|
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
|
|
12242
|
-
const modal = this.runParseApproval(tail) || parsedModal
|
|
12281
|
+
const modal = this.runParseApproval(tail) || parsedModal;
|
|
12243
12282
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
12244
|
-
const scriptStatus =
|
|
12283
|
+
const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
|
|
12245
12284
|
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
12246
12285
|
committedMessages: this.committedMessages,
|
|
12247
12286
|
scope: this.currentTurnScope,
|
|
@@ -12296,15 +12335,44 @@ var init_provider_cli_adapter = __esm({
|
|
|
12296
12335
|
}
|
|
12297
12336
|
if (!scriptStatus) return;
|
|
12298
12337
|
const prevStatus = this.currentStatus;
|
|
12299
|
-
const
|
|
12338
|
+
const ctx = { now, screenText, modal, scriptStatus, parsedTranscript, parsedMessages, lastParsedAssistant, parsedShowsLiveAssistantProgress, prevStatus };
|
|
12339
|
+
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
12340
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
12341
|
+
LOG.info(
|
|
12342
|
+
"CLI",
|
|
12343
|
+
`[${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)}`
|
|
12344
|
+
);
|
|
12345
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedTranscript?.status === "idle" && !!lastParsedAssistant);
|
|
12346
|
+
if (shouldHoldGenerating) {
|
|
12347
|
+
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
12348
|
+
return;
|
|
12349
|
+
}
|
|
12350
|
+
if (scriptStatus === "waiting_approval") {
|
|
12351
|
+
this.applyWaitingApproval(ctx);
|
|
12352
|
+
return;
|
|
12353
|
+
}
|
|
12354
|
+
if (scriptStatus === "generating") {
|
|
12355
|
+
this.applyGenerating(ctx);
|
|
12356
|
+
return;
|
|
12357
|
+
}
|
|
12358
|
+
if (scriptStatus === "idle") {
|
|
12359
|
+
this.applyIdle(ctx, now);
|
|
12360
|
+
}
|
|
12361
|
+
}
|
|
12362
|
+
// Returns false if the caller should bail out (debounce pending).
|
|
12363
|
+
applyPendingScriptStatusDebounce(ctx) {
|
|
12364
|
+
const { now, scriptStatus, prevStatus } = ctx;
|
|
12365
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (scriptStatus === "generating" || scriptStatus === "waiting_approval");
|
|
12366
|
+
if (!shouldDebounce) {
|
|
12300
12367
|
this.pendingScriptStatus = null;
|
|
12301
12368
|
this.pendingScriptStatusSince = 0;
|
|
12302
12369
|
if (this.pendingScriptStatusTimer) {
|
|
12303
12370
|
clearTimeout(this.pendingScriptStatusTimer);
|
|
12304
12371
|
this.pendingScriptStatusTimer = null;
|
|
12305
12372
|
}
|
|
12306
|
-
|
|
12307
|
-
|
|
12373
|
+
return true;
|
|
12374
|
+
}
|
|
12375
|
+
const armPending = (delayMs) => {
|
|
12308
12376
|
if (this.pendingScriptStatusTimer) clearTimeout(this.pendingScriptStatusTimer);
|
|
12309
12377
|
this.pendingScriptStatusTimer = setTimeout(() => {
|
|
12310
12378
|
this.pendingScriptStatusTimer = null;
|
|
@@ -12312,200 +12380,187 @@ var init_provider_cli_adapter = __esm({
|
|
|
12312
12380
|
this.evaluateSettled();
|
|
12313
12381
|
}, delayMs);
|
|
12314
12382
|
};
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
12321
|
-
return;
|
|
12322
|
-
}
|
|
12323
|
-
const elapsed = now - this.pendingScriptStatusSince;
|
|
12324
|
-
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
12325
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
12326
|
-
return;
|
|
12327
|
-
}
|
|
12328
|
-
} else {
|
|
12329
|
-
clearPendingScriptStatus();
|
|
12330
|
-
}
|
|
12331
|
-
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
12332
|
-
const statusActivityHoldMs = this.getStatusActivityHoldMs();
|
|
12333
|
-
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
12334
|
-
const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
|
|
12335
|
-
if (this.currentTurnScope && this.cliType === "claude-cli") {
|
|
12336
|
-
LOG.info(
|
|
12337
|
-
"CLI",
|
|
12338
|
-
`[${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)}`
|
|
12339
|
-
);
|
|
12383
|
+
if (this.pendingScriptStatus !== scriptStatus) {
|
|
12384
|
+
this.pendingScriptStatus = scriptStatus;
|
|
12385
|
+
this.pendingScriptStatusSince = now;
|
|
12386
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
12387
|
+
return false;
|
|
12340
12388
|
}
|
|
12341
|
-
const
|
|
12342
|
-
if (
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12346
|
-
this.idleTimeout = setTimeout(() => {
|
|
12347
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
12348
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12349
|
-
this.finishResponse();
|
|
12350
|
-
}
|
|
12351
|
-
}, this.timeouts.generatingIdle);
|
|
12352
|
-
this.recordTrace("hold_generating_recent_activity", {
|
|
12353
|
-
scriptStatus,
|
|
12354
|
-
recentInteractiveActivity,
|
|
12355
|
-
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
12356
|
-
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
12357
|
-
holdMs: statusActivityHoldMs,
|
|
12358
|
-
...buildCliTraceParseSnapshot({
|
|
12359
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
12360
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
12361
|
-
responseBuffer: this.responseBuffer,
|
|
12362
|
-
partialResponse: this.responseBuffer,
|
|
12363
|
-
scope: this.currentTurnScope
|
|
12364
|
-
})
|
|
12365
|
-
});
|
|
12366
|
-
this.onStatusChange?.();
|
|
12367
|
-
return;
|
|
12389
|
+
const elapsed = now - this.pendingScriptStatusSince;
|
|
12390
|
+
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
12391
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
12392
|
+
return false;
|
|
12368
12393
|
}
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
this.
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
this.
|
|
12392
|
-
|
|
12394
|
+
return true;
|
|
12395
|
+
}
|
|
12396
|
+
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
12397
|
+
const { scriptStatus } = ctx;
|
|
12398
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
12399
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
12400
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12401
|
+
this.idleTimeout = setTimeout(() => {
|
|
12402
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
12403
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12404
|
+
this.finishResponse();
|
|
12405
|
+
}
|
|
12406
|
+
}, this.timeouts.generatingIdle);
|
|
12407
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
12408
|
+
scriptStatus,
|
|
12409
|
+
recentInteractiveActivity,
|
|
12410
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
12411
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
12412
|
+
holdMs: this.getStatusActivityHoldMs(),
|
|
12413
|
+
...buildCliTraceParseSnapshot({
|
|
12414
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
12415
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
12416
|
+
responseBuffer: this.responseBuffer,
|
|
12417
|
+
partialResponse: this.responseBuffer,
|
|
12418
|
+
scope: this.currentTurnScope
|
|
12419
|
+
})
|
|
12420
|
+
});
|
|
12421
|
+
this.onStatusChange?.();
|
|
12422
|
+
}
|
|
12423
|
+
applyWaitingApproval(ctx) {
|
|
12424
|
+
const { modal } = ctx;
|
|
12425
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
12426
|
+
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
12427
|
+
if (inCooldown && !modal) {
|
|
12428
|
+
if (this.approvalExitTimeout) {
|
|
12429
|
+
clearTimeout(this.approvalExitTimeout);
|
|
12430
|
+
this.approvalExitTimeout = null;
|
|
12393
12431
|
}
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
this.setStatus("
|
|
12397
|
-
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
12432
|
+
this.activeModal = null;
|
|
12433
|
+
if (this.isWaitingForResponse) {
|
|
12434
|
+
this.setStatus("generating", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
12398
12435
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12399
|
-
this.
|
|
12400
|
-
|
|
12401
|
-
|
|
12436
|
+
this.idleTimeout = setTimeout(() => {
|
|
12437
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
12438
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12439
|
+
this.finishResponse();
|
|
12440
|
+
}
|
|
12441
|
+
}, this.timeouts.generatingIdle);
|
|
12442
|
+
} else {
|
|
12443
|
+
this.setStatus("idle", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
12402
12444
|
}
|
|
12445
|
+
this.onStatusChange?.();
|
|
12446
|
+
return;
|
|
12403
12447
|
}
|
|
12404
|
-
if (
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
const noActiveTurn = !this.currentTurnScope;
|
|
12408
|
-
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));
|
|
12409
|
-
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
12448
|
+
if (!inCooldown) {
|
|
12449
|
+
if (!modal) {
|
|
12450
|
+
LOG.warn("CLI", `[${this.cliType}] detectStatus reported waiting_approval without parseApproval modal; ignoring non-actionable approval state`);
|
|
12410
12451
|
return;
|
|
12411
12452
|
}
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
this.approvalExitTimeout = null;
|
|
12416
|
-
}
|
|
12417
|
-
this.activeModal = null;
|
|
12418
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
12419
|
-
}
|
|
12420
|
-
if (!this.isWaitingForResponse) {
|
|
12421
|
-
this.isWaitingForResponse = true;
|
|
12422
|
-
this.responseBuffer = "";
|
|
12423
|
-
}
|
|
12424
|
-
this.setStatus("generating", "script_detect");
|
|
12453
|
+
this.isWaitingForResponse = true;
|
|
12454
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
12455
|
+
this.activeModal = modal;
|
|
12425
12456
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12426
|
-
this.
|
|
12427
|
-
if (this.isWaitingForResponse) {
|
|
12428
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12429
|
-
this.finishResponse();
|
|
12430
|
-
}
|
|
12431
|
-
}, this.timeouts.generatingIdle);
|
|
12457
|
+
this.armApprovalExitTimeout();
|
|
12432
12458
|
this.onStatusChange?.();
|
|
12459
|
+
}
|
|
12460
|
+
}
|
|
12461
|
+
applyGenerating(ctx) {
|
|
12462
|
+
const { screenText, modal, parsedShowsLiveAssistantProgress, prevStatus } = ctx;
|
|
12463
|
+
this.clearIdleFinishCandidate("generating");
|
|
12464
|
+
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
12465
|
+
const noActiveTurn = !this.currentTurnScope;
|
|
12466
|
+
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));
|
|
12467
|
+
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
12433
12468
|
return;
|
|
12434
12469
|
}
|
|
12435
|
-
if (
|
|
12436
|
-
if (
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
this.approvalExitTimeout = null;
|
|
12440
|
-
}
|
|
12441
|
-
this.activeModal = null;
|
|
12442
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
12470
|
+
if (prevStatus === "waiting_approval") {
|
|
12471
|
+
if (this.approvalExitTimeout) {
|
|
12472
|
+
clearTimeout(this.approvalExitTimeout);
|
|
12473
|
+
this.approvalExitTimeout = null;
|
|
12443
12474
|
}
|
|
12475
|
+
this.activeModal = null;
|
|
12476
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
12477
|
+
}
|
|
12478
|
+
if (!this.isWaitingForResponse) {
|
|
12479
|
+
this.isWaitingForResponse = true;
|
|
12480
|
+
this.responseBuffer = "";
|
|
12481
|
+
}
|
|
12482
|
+
this.setStatus("generating", "script_detect");
|
|
12483
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12484
|
+
this.idleTimeout = setTimeout(() => {
|
|
12444
12485
|
if (this.isWaitingForResponse) {
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
hasModal: !!modal,
|
|
12464
|
-
idleQuietThresholdMs,
|
|
12465
|
-
idleStableThresholdMs,
|
|
12466
|
-
idleReady,
|
|
12467
|
-
idleFinishConfirmMs,
|
|
12468
|
-
idleFinishCandidate: candidate,
|
|
12469
|
-
candidateQuiet,
|
|
12470
|
-
canFinishImmediately,
|
|
12471
|
-
submitPendingUntil: this.submitPendingUntil,
|
|
12472
|
-
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
12473
|
-
...buildCliTraceParseSnapshot({
|
|
12474
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
12475
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
12476
|
-
responseBuffer: this.responseBuffer,
|
|
12477
|
-
partialResponse: this.responseBuffer,
|
|
12478
|
-
scope: this.currentTurnScope
|
|
12479
|
-
})
|
|
12480
|
-
});
|
|
12481
|
-
if (canFinishImmediately) {
|
|
12482
|
-
this.clearIdleFinishCandidate("finish_response");
|
|
12483
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12484
|
-
this.finishResponse();
|
|
12485
|
-
return;
|
|
12486
|
-
}
|
|
12487
|
-
if (idleReady) {
|
|
12488
|
-
if (!candidate) {
|
|
12489
|
-
this.armIdleFinishCandidate(assistantLength);
|
|
12490
|
-
return;
|
|
12491
|
-
}
|
|
12492
|
-
} else {
|
|
12493
|
-
this.clearIdleFinishCandidate("idle_not_ready");
|
|
12494
|
-
}
|
|
12495
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12496
|
-
this.idleTimeout = setTimeout(() => {
|
|
12497
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
12498
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12499
|
-
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
12500
|
-
this.finishResponse();
|
|
12501
|
-
}
|
|
12502
|
-
}, this.timeouts.idleFinish);
|
|
12503
|
-
} else if (prevStatus !== "idle") {
|
|
12486
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12487
|
+
this.finishResponse();
|
|
12488
|
+
}
|
|
12489
|
+
}, this.timeouts.generatingIdle);
|
|
12490
|
+
this.onStatusChange?.();
|
|
12491
|
+
}
|
|
12492
|
+
applyIdle(ctx, now) {
|
|
12493
|
+
const { screenText, modal, lastParsedAssistant, prevStatus } = ctx;
|
|
12494
|
+
if (prevStatus === "waiting_approval") {
|
|
12495
|
+
if (this.approvalExitTimeout) {
|
|
12496
|
+
clearTimeout(this.approvalExitTimeout);
|
|
12497
|
+
this.approvalExitTimeout = null;
|
|
12498
|
+
}
|
|
12499
|
+
this.activeModal = null;
|
|
12500
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
12501
|
+
}
|
|
12502
|
+
if (!this.isWaitingForResponse) {
|
|
12503
|
+
if (prevStatus !== "idle") {
|
|
12504
12504
|
this.clearIdleFinishCandidate("idle_without_response");
|
|
12505
12505
|
this.setStatus("idle", "script_detect");
|
|
12506
12506
|
this.onStatusChange?.();
|
|
12507
12507
|
}
|
|
12508
|
+
return;
|
|
12508
12509
|
}
|
|
12510
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
12511
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
12512
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
12513
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
12514
|
+
const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
|
|
12515
|
+
const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
|
|
12516
|
+
const idleReady = !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleFinishConfirmMs;
|
|
12517
|
+
const candidate = this.idleFinishCandidate;
|
|
12518
|
+
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
|
|
12519
|
+
this.recordTrace("idle_decision", {
|
|
12520
|
+
quietForMs,
|
|
12521
|
+
screenStableMs,
|
|
12522
|
+
hasAssistantTurn,
|
|
12523
|
+
assistantLength,
|
|
12524
|
+
hasModal: !!modal,
|
|
12525
|
+
idleQuietThresholdMs,
|
|
12526
|
+
idleStableThresholdMs: idleFinishConfirmMs,
|
|
12527
|
+
idleReady,
|
|
12528
|
+
idleFinishConfirmMs,
|
|
12529
|
+
idleFinishCandidate: candidate,
|
|
12530
|
+
candidateQuiet,
|
|
12531
|
+
canFinishImmediately: idleReady && candidateQuiet,
|
|
12532
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
12533
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
12534
|
+
...buildCliTraceParseSnapshot({
|
|
12535
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
12536
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
12537
|
+
responseBuffer: this.responseBuffer,
|
|
12538
|
+
partialResponse: this.responseBuffer,
|
|
12539
|
+
scope: this.currentTurnScope
|
|
12540
|
+
})
|
|
12541
|
+
});
|
|
12542
|
+
if (idleReady && candidateQuiet) {
|
|
12543
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
12544
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12545
|
+
this.finishResponse();
|
|
12546
|
+
return;
|
|
12547
|
+
}
|
|
12548
|
+
if (idleReady) {
|
|
12549
|
+
if (!candidate) {
|
|
12550
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
12551
|
+
return;
|
|
12552
|
+
}
|
|
12553
|
+
} else {
|
|
12554
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
12555
|
+
}
|
|
12556
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
12557
|
+
this.idleTimeout = setTimeout(() => {
|
|
12558
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
12559
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
12560
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
12561
|
+
this.finishResponse();
|
|
12562
|
+
}
|
|
12563
|
+
}, this.timeouts.idleFinish);
|
|
12509
12564
|
}
|
|
12510
12565
|
finishResponse() {
|
|
12511
12566
|
if (this.submitPendingUntil > Date.now()) return;
|
|
@@ -12544,26 +12599,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12544
12599
|
}, _ProviderCliAdapter.FINISH_RETRY_DELAY_MS);
|
|
12545
12600
|
return;
|
|
12546
12601
|
}
|
|
12547
|
-
|
|
12548
|
-
clearTimeout(this.responseTimeout);
|
|
12549
|
-
this.responseTimeout = null;
|
|
12550
|
-
}
|
|
12551
|
-
if (this.idleTimeout) {
|
|
12552
|
-
clearTimeout(this.idleTimeout);
|
|
12553
|
-
this.idleTimeout = null;
|
|
12554
|
-
}
|
|
12555
|
-
if (this.approvalExitTimeout) {
|
|
12556
|
-
clearTimeout(this.approvalExitTimeout);
|
|
12557
|
-
this.approvalExitTimeout = null;
|
|
12558
|
-
}
|
|
12559
|
-
if (this.submitRetryTimer) {
|
|
12560
|
-
clearTimeout(this.submitRetryTimer);
|
|
12561
|
-
this.submitRetryTimer = null;
|
|
12562
|
-
}
|
|
12563
|
-
if (this.finishRetryTimer) {
|
|
12564
|
-
clearTimeout(this.finishRetryTimer);
|
|
12565
|
-
this.finishRetryTimer = null;
|
|
12566
|
-
}
|
|
12602
|
+
this.clearAllTimers();
|
|
12567
12603
|
this.responseBuffer = "";
|
|
12568
12604
|
this.isWaitingForResponse = false;
|
|
12569
12605
|
this.responseSettleIgnoreUntil = 0;
|
|
@@ -12575,18 +12611,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
12575
12611
|
this.setStatus("idle", "response_finished");
|
|
12576
12612
|
this.onStatusChange?.();
|
|
12577
12613
|
}
|
|
12578
|
-
maybeCommitVisibleIdleTranscript(parsed
|
|
12614
|
+
maybeCommitVisibleIdleTranscript(parsed) {
|
|
12579
12615
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
12580
12616
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
12581
12617
|
if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
|
|
12582
12618
|
return false;
|
|
12583
12619
|
}
|
|
12584
|
-
if (options?.requireVisibleAssistantCandidate) {
|
|
12585
|
-
const candidateText = options.screenText || this.terminalScreen.getText() || "";
|
|
12586
|
-
if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
|
|
12587
|
-
return false;
|
|
12588
|
-
}
|
|
12589
|
-
}
|
|
12590
12620
|
const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
12591
12621
|
committedMessages: this.committedMessages,
|
|
12592
12622
|
scope: this.currentTurnScope,
|
|
@@ -12595,33 +12625,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
12595
12625
|
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
12596
12626
|
if (!visibleAssistant) return false;
|
|
12597
12627
|
this.committedMessages = hydratedForIdleCommit;
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
12601
|
-
if (lastAssistantForTrim) {
|
|
12602
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
12603
|
-
}
|
|
12604
|
-
}
|
|
12605
|
-
if (this.responseTimeout) {
|
|
12606
|
-
clearTimeout(this.responseTimeout);
|
|
12607
|
-
this.responseTimeout = null;
|
|
12608
|
-
}
|
|
12609
|
-
if (this.idleTimeout) {
|
|
12610
|
-
clearTimeout(this.idleTimeout);
|
|
12611
|
-
this.idleTimeout = null;
|
|
12612
|
-
}
|
|
12613
|
-
if (this.approvalExitTimeout) {
|
|
12614
|
-
clearTimeout(this.approvalExitTimeout);
|
|
12615
|
-
this.approvalExitTimeout = null;
|
|
12616
|
-
}
|
|
12617
|
-
if (this.submitRetryTimer) {
|
|
12618
|
-
clearTimeout(this.submitRetryTimer);
|
|
12619
|
-
this.submitRetryTimer = null;
|
|
12620
|
-
}
|
|
12621
|
-
if (this.finishRetryTimer) {
|
|
12622
|
-
clearTimeout(this.finishRetryTimer);
|
|
12623
|
-
this.finishRetryTimer = null;
|
|
12624
|
-
}
|
|
12628
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
12629
|
+
this.clearAllTimers();
|
|
12625
12630
|
this.syncMessageViews();
|
|
12626
12631
|
this.responseBuffer = "";
|
|
12627
12632
|
this.isWaitingForResponse = false;
|
|
@@ -12651,13 +12656,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12651
12656
|
scope: this.currentTurnScope,
|
|
12652
12657
|
lastOutputAt: this.lastOutputAt
|
|
12653
12658
|
});
|
|
12654
|
-
|
|
12655
|
-
if (promptForTrim) {
|
|
12656
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
12657
|
-
if (lastAssistantForTrim) {
|
|
12658
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
12659
|
-
}
|
|
12660
|
-
}
|
|
12659
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
12661
12660
|
this.syncMessageViews();
|
|
12662
12661
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
12663
12662
|
if (this.currentTurnScope) {
|
|
@@ -12715,7 +12714,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12715
12714
|
screen: buildCliScreenSnapshot(screenText),
|
|
12716
12715
|
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
12717
12716
|
});
|
|
12718
|
-
return
|
|
12717
|
+
return status;
|
|
12719
12718
|
} catch (e) {
|
|
12720
12719
|
LOG.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
12721
12720
|
return null;
|
|
@@ -12755,23 +12754,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
12755
12754
|
if (!inApprovalCooldown) {
|
|
12756
12755
|
return parsed;
|
|
12757
12756
|
}
|
|
12758
|
-
const
|
|
12759
|
-
const visibleModal = this.runParseApproval(recentBuffer) || startupModal;
|
|
12757
|
+
const visibleModal = this.runParseApproval(recentBuffer);
|
|
12760
12758
|
if (visibleModal) {
|
|
12761
12759
|
return parsed;
|
|
12762
12760
|
}
|
|
12763
12761
|
const detectedStatus = this.runDetectStatus(recentBuffer);
|
|
12764
|
-
const
|
|
12762
|
+
const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
|
|
12765
12763
|
return {
|
|
12766
12764
|
...parsed,
|
|
12767
|
-
status:
|
|
12765
|
+
status: resolvedStatus,
|
|
12768
12766
|
activeModal: null
|
|
12769
12767
|
};
|
|
12770
12768
|
}
|
|
12771
12769
|
// ─── Public API (CliAdapter) ───────────────────
|
|
12772
12770
|
getStatus() {
|
|
12773
|
-
const
|
|
12774
|
-
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
12771
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
12775
12772
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
12776
12773
|
let effectiveModal = startupModal || this.activeModal;
|
|
12777
12774
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
@@ -12852,8 +12849,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12852
12849
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
12853
12850
|
}));
|
|
12854
12851
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
12855
|
-
const
|
|
12856
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, committedHydratedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && visibleIdlePrompt);
|
|
12852
|
+
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");
|
|
12857
12853
|
if (shouldAdoptParsedIdleReplay) {
|
|
12858
12854
|
this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
12859
12855
|
committedMessages: this.committedMessages,
|
|
@@ -12982,17 +12978,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
12982
12978
|
if (parsed && typeof parsed === "object") {
|
|
12983
12979
|
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
12984
12980
|
}
|
|
12985
|
-
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
12986
|
-
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
12987
|
-
parsed.status = refinedStatus;
|
|
12988
|
-
}
|
|
12989
12981
|
const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
const lastAssistant = [...normalizedParsed.messages].reverse().find((message) => message?.role === "assistant" && typeof message.content === "string");
|
|
12993
|
-
if (lastAssistant) {
|
|
12994
|
-
lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
|
|
12995
|
-
}
|
|
12982
|
+
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
12983
|
+
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
12996
12984
|
}
|
|
12997
12985
|
this.parseErrorMessage = null;
|
|
12998
12986
|
return normalizedParsed;
|
|
@@ -13020,16 +13008,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
13020
13008
|
LOG.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
|
|
13021
13009
|
}
|
|
13022
13010
|
}
|
|
13023
|
-
if (!promptText
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
${data.explanation || ""}
|
|
13027
|
-
|
|
13028
|
-
${data.message || ""}`.trim();
|
|
13029
|
-
}
|
|
13030
|
-
if (promptText) {
|
|
13031
|
-
await this.sendMessage(promptText);
|
|
13011
|
+
if (!promptText) {
|
|
13012
|
+
LOG.warn("CLI", `[${this.cliType}] resolveAction skipped: provider script did not supply a prompt`);
|
|
13013
|
+
return;
|
|
13032
13014
|
}
|
|
13015
|
+
await this.sendMessage(promptText);
|
|
13033
13016
|
}
|
|
13034
13017
|
async sendMessage(text) {
|
|
13035
13018
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
@@ -13047,9 +13030,7 @@ ${data.message || ""}`.trim();
|
|
|
13047
13030
|
}
|
|
13048
13031
|
if (!this.ready) {
|
|
13049
13032
|
this.resolveStartupState("send_precheck");
|
|
13050
|
-
|
|
13051
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
13052
|
-
if (hasPrompt && this.currentStatus === "idle") {
|
|
13033
|
+
if (this.runDetectStatus(this.recentOutputBuffer) === "idle" && this.currentStatus === "idle") {
|
|
13053
13034
|
this.ready = true;
|
|
13054
13035
|
this.startupParseGate = false;
|
|
13055
13036
|
LOG.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
@@ -13155,7 +13136,10 @@ ${data.message || ""}`.trim();
|
|
|
13155
13136
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
13156
13137
|
const screenText2 = this.terminalScreen.getText();
|
|
13157
13138
|
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
13158
|
-
|
|
13139
|
+
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
13140
|
+
if (liveApproval) return;
|
|
13141
|
+
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
13142
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
13159
13143
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
13160
13144
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
13161
13145
|
this.recordTrace("submit_write", {
|
|
@@ -13192,6 +13176,10 @@ ${data.message || ""}`.trim();
|
|
|
13192
13176
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
13193
13177
|
const screenText = this.terminalScreen.getText();
|
|
13194
13178
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
13179
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
13180
|
+
if (liveApproval) return;
|
|
13181
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
13182
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
13195
13183
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
13196
13184
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
13197
13185
|
this.recordTrace("submit_write", {
|
|
@@ -13323,44 +13311,9 @@ ${data.message || ""}`.trim();
|
|
|
13323
13311
|
}
|
|
13324
13312
|
shutdown() {
|
|
13325
13313
|
this.clearIdleFinishCandidate("shutdown");
|
|
13326
|
-
|
|
13327
|
-
clearTimeout(this.settleTimer);
|
|
13328
|
-
this.settleTimer = null;
|
|
13329
|
-
}
|
|
13330
|
-
if (this.approvalExitTimeout) {
|
|
13331
|
-
clearTimeout(this.approvalExitTimeout);
|
|
13332
|
-
this.approvalExitTimeout = null;
|
|
13333
|
-
}
|
|
13334
|
-
if (this.submitRetryTimer) {
|
|
13335
|
-
clearTimeout(this.submitRetryTimer);
|
|
13336
|
-
this.submitRetryTimer = null;
|
|
13337
|
-
}
|
|
13338
|
-
if (this.finishRetryTimer) {
|
|
13339
|
-
clearTimeout(this.finishRetryTimer);
|
|
13340
|
-
this.finishRetryTimer = null;
|
|
13341
|
-
}
|
|
13342
|
-
if (this.responseTimeout) {
|
|
13343
|
-
clearTimeout(this.responseTimeout);
|
|
13344
|
-
this.responseTimeout = null;
|
|
13345
|
-
}
|
|
13346
|
-
if (this.idleTimeout) {
|
|
13347
|
-
clearTimeout(this.idleTimeout);
|
|
13348
|
-
this.idleTimeout = null;
|
|
13349
|
-
}
|
|
13350
|
-
if (this.pendingScriptStatusTimer) {
|
|
13351
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
13352
|
-
this.pendingScriptStatusTimer = null;
|
|
13353
|
-
}
|
|
13354
|
-
if (this.pendingOutputParseTimer) {
|
|
13355
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
13356
|
-
this.pendingOutputParseTimer = null;
|
|
13357
|
-
}
|
|
13314
|
+
this.clearAllTimers();
|
|
13358
13315
|
this.pendingOutputParseBuffer = "";
|
|
13359
13316
|
this.pendingTerminalQueryTail = "";
|
|
13360
|
-
if (this.ptyOutputFlushTimer) {
|
|
13361
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
13362
|
-
this.ptyOutputFlushTimer = null;
|
|
13363
|
-
}
|
|
13364
13317
|
this.ptyOutputBuffer = "";
|
|
13365
13318
|
this.finishRetryCount = 0;
|
|
13366
13319
|
if (this.ptyProcess) {
|
|
@@ -13381,44 +13334,9 @@ ${data.message || ""}`.trim();
|
|
|
13381
13334
|
}
|
|
13382
13335
|
detach() {
|
|
13383
13336
|
this.clearIdleFinishCandidate("detach");
|
|
13384
|
-
|
|
13385
|
-
clearTimeout(this.settleTimer);
|
|
13386
|
-
this.settleTimer = null;
|
|
13387
|
-
}
|
|
13388
|
-
if (this.approvalExitTimeout) {
|
|
13389
|
-
clearTimeout(this.approvalExitTimeout);
|
|
13390
|
-
this.approvalExitTimeout = null;
|
|
13391
|
-
}
|
|
13392
|
-
if (this.submitRetryTimer) {
|
|
13393
|
-
clearTimeout(this.submitRetryTimer);
|
|
13394
|
-
this.submitRetryTimer = null;
|
|
13395
|
-
}
|
|
13396
|
-
if (this.finishRetryTimer) {
|
|
13397
|
-
clearTimeout(this.finishRetryTimer);
|
|
13398
|
-
this.finishRetryTimer = null;
|
|
13399
|
-
}
|
|
13400
|
-
if (this.responseTimeout) {
|
|
13401
|
-
clearTimeout(this.responseTimeout);
|
|
13402
|
-
this.responseTimeout = null;
|
|
13403
|
-
}
|
|
13404
|
-
if (this.idleTimeout) {
|
|
13405
|
-
clearTimeout(this.idleTimeout);
|
|
13406
|
-
this.idleTimeout = null;
|
|
13407
|
-
}
|
|
13408
|
-
if (this.pendingScriptStatusTimer) {
|
|
13409
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
13410
|
-
this.pendingScriptStatusTimer = null;
|
|
13411
|
-
}
|
|
13412
|
-
if (this.pendingOutputParseTimer) {
|
|
13413
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
13414
|
-
this.pendingOutputParseTimer = null;
|
|
13415
|
-
}
|
|
13337
|
+
this.clearAllTimers();
|
|
13416
13338
|
this.pendingOutputParseBuffer = "";
|
|
13417
13339
|
this.pendingTerminalQueryTail = "";
|
|
13418
|
-
if (this.ptyOutputFlushTimer) {
|
|
13419
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
13420
|
-
this.ptyOutputFlushTimer = null;
|
|
13421
|
-
}
|
|
13422
13340
|
this.ptyOutputBuffer = "";
|
|
13423
13341
|
this.finishRetryCount = 0;
|
|
13424
13342
|
if (this.ptyProcess) {
|
|
@@ -13480,8 +13398,7 @@ ${data.message || ""}`.trim();
|
|
|
13480
13398
|
this.ptyProcess?.write(data);
|
|
13481
13399
|
}
|
|
13482
13400
|
resolveModal(buttonIndex) {
|
|
13483
|
-
|
|
13484
|
-
let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
13401
|
+
let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
13485
13402
|
if (!modal && typeof this.cliScripts?.parseOutput === "function") {
|
|
13486
13403
|
try {
|
|
13487
13404
|
const parsed = this.getScriptParsedStatus();
|
|
@@ -13512,12 +13429,7 @@ ${data.message || ""}`.trim();
|
|
|
13512
13429
|
}
|
|
13513
13430
|
this.setStatus("generating", "approval_resolved");
|
|
13514
13431
|
this.onStatusChange?.();
|
|
13515
|
-
|
|
13516
|
-
if (startupTrustModal && buttonIndex in this.approvalKeys) {
|
|
13517
|
-
this.ptyProcess.write(`${this.approvalKeys[buttonIndex]}\r`);
|
|
13518
|
-
} else if (this.shouldResolveModalWithEnter(modal, buttonIndex)) {
|
|
13519
|
-
this.ptyProcess.write("\r");
|
|
13520
|
-
} else if (buttonIndex in this.approvalKeys) {
|
|
13432
|
+
if (buttonIndex in this.approvalKeys) {
|
|
13521
13433
|
this.ptyProcess.write(this.approvalKeys[buttonIndex]);
|
|
13522
13434
|
} else {
|
|
13523
13435
|
const DOWN = "\x1B[B";
|
|
@@ -13537,7 +13449,7 @@ ${data.message || ""}`.trim();
|
|
|
13537
13449
|
}
|
|
13538
13450
|
getDebugState() {
|
|
13539
13451
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
13540
|
-
const startupModal = this.startupParseGate ? this.
|
|
13452
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
13541
13453
|
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
13542
13454
|
const effectiveReady = this.ready || !!startupModal;
|
|
13543
13455
|
return {
|
|
@@ -55460,7 +55372,7 @@ var init_adhdev_daemon = __esm({
|
|
|
55460
55372
|
init_version();
|
|
55461
55373
|
init_src();
|
|
55462
55374
|
init_runtime_defaults();
|
|
55463
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.
|
|
55375
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.9" });
|
|
55464
55376
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
55465
55377
|
localHttpServer = null;
|
|
55466
55378
|
localWss = null;
|