@adhdev/daemon-standalone 0.9.6 → 0.9.8
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/index.js +379 -485
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/index-BSO1MqUY.css +1 -0
- package/public/assets/index-CD9XKSqu.js +76 -0
- package/public/index.html +2 -2
- package/public/assets/index-B0FjL1WW.js +0 -76
- package/public/assets/index-D-URXQC3.css +0 -1
package/dist/index.js
CHANGED
|
@@ -29378,8 +29378,35 @@ var require_dist2 = __commonJS({
|
|
|
29378
29378
|
function normalizeScreenSnapshot(text) {
|
|
29379
29379
|
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
29380
29380
|
}
|
|
29381
|
+
function shouldReflowComparableMessageLines(lines) {
|
|
29382
|
+
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));
|
|
29383
|
+
}
|
|
29384
|
+
function joinComparableMessageLines(lines) {
|
|
29385
|
+
return lines.reduce((acc, line) => {
|
|
29386
|
+
const next = String(line || "").trim();
|
|
29387
|
+
if (!next) return acc;
|
|
29388
|
+
if (!acc) return next;
|
|
29389
|
+
if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
|
|
29390
|
+
return `${acc}${next}`;
|
|
29391
|
+
}
|
|
29392
|
+
if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
|
|
29393
|
+
return `${acc}${next}`;
|
|
29394
|
+
}
|
|
29395
|
+
const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
|
|
29396
|
+
const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
|
|
29397
|
+
if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
|
|
29398
|
+
return `${acc}${next}`;
|
|
29399
|
+
}
|
|
29400
|
+
return `${acc} ${next}`;
|
|
29401
|
+
}, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
|
|
29402
|
+
}
|
|
29381
29403
|
function normalizeComparableMessageContent(text) {
|
|
29382
|
-
|
|
29404
|
+
const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
29405
|
+
if (lines.length === 0) return "";
|
|
29406
|
+
if (shouldReflowComparableMessageLines(lines)) {
|
|
29407
|
+
return joinComparableMessageLines(lines);
|
|
29408
|
+
}
|
|
29409
|
+
return lines.join(" ").replace(/\s+/g, " ").trim();
|
|
29383
29410
|
}
|
|
29384
29411
|
function trimPromptEchoPrefix(text, promptText) {
|
|
29385
29412
|
const prompt = normalizeComparableMessageContent(String(promptText || ""));
|
|
@@ -29412,9 +29439,6 @@ var require_dist2 = __commonJS({
|
|
|
29412
29439
|
}
|
|
29413
29440
|
return "";
|
|
29414
29441
|
}
|
|
29415
|
-
function looksLikeConfirmOnlyLabel(label) {
|
|
29416
|
-
return /^(?:continue|confirm|ok|yes|trust|proceed|enter)$/i.test(String(label || "").trim());
|
|
29417
|
-
}
|
|
29418
29442
|
function parsePatternEntry(x) {
|
|
29419
29443
|
if (x instanceof RegExp) return x;
|
|
29420
29444
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -29445,6 +29469,7 @@ var require_dist2 = __commonJS({
|
|
|
29445
29469
|
var path9;
|
|
29446
29470
|
var import_child_process4;
|
|
29447
29471
|
var buildCliSpawnEnv;
|
|
29472
|
+
var COMMON_COMPARABLE_WRAP_WORDS;
|
|
29448
29473
|
var init_provider_cli_shared = __esm2({
|
|
29449
29474
|
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
29450
29475
|
"use strict";
|
|
@@ -29453,6 +29478,32 @@ var require_dist2 = __commonJS({
|
|
|
29453
29478
|
import_child_process4 = require("child_process");
|
|
29454
29479
|
init_spawn_env();
|
|
29455
29480
|
buildCliSpawnEnv = import_session_host_core3.sanitizeSpawnEnv;
|
|
29481
|
+
COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
|
|
29482
|
+
"a",
|
|
29483
|
+
"an",
|
|
29484
|
+
"and",
|
|
29485
|
+
"as",
|
|
29486
|
+
"at",
|
|
29487
|
+
"but",
|
|
29488
|
+
"by",
|
|
29489
|
+
"for",
|
|
29490
|
+
"from",
|
|
29491
|
+
"in",
|
|
29492
|
+
"into",
|
|
29493
|
+
"is",
|
|
29494
|
+
"it",
|
|
29495
|
+
"of",
|
|
29496
|
+
"on",
|
|
29497
|
+
"or",
|
|
29498
|
+
"that",
|
|
29499
|
+
"the",
|
|
29500
|
+
"their",
|
|
29501
|
+
"then",
|
|
29502
|
+
"this",
|
|
29503
|
+
"to",
|
|
29504
|
+
"was",
|
|
29505
|
+
"with"
|
|
29506
|
+
]);
|
|
29456
29507
|
}
|
|
29457
29508
|
});
|
|
29458
29509
|
function sliceFromOffset(text, start) {
|
|
@@ -29506,8 +29557,44 @@ var require_dist2 = __commonJS({
|
|
|
29506
29557
|
};
|
|
29507
29558
|
});
|
|
29508
29559
|
}
|
|
29560
|
+
function chooseMoreComparableCliMessage(left, right) {
|
|
29561
|
+
const leftComparable = normalizeComparableMessageContent(left.content || "");
|
|
29562
|
+
const rightComparable = normalizeComparableMessageContent(right.content || "");
|
|
29563
|
+
if (leftComparable && leftComparable === rightComparable) {
|
|
29564
|
+
const leftNewlines = String(left.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
29565
|
+
const rightNewlines = String(right.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
29566
|
+
return rightNewlines < leftNewlines ? right : left;
|
|
29567
|
+
}
|
|
29568
|
+
return rightComparable.length > leftComparable.length ? right : left;
|
|
29569
|
+
}
|
|
29570
|
+
function dedupeConsecutiveComparableCliMessages(messages) {
|
|
29571
|
+
const deduped = [];
|
|
29572
|
+
for (const message of messages) {
|
|
29573
|
+
const current = {
|
|
29574
|
+
...message,
|
|
29575
|
+
content: typeof message.content === "string" ? message.content : String(message.content || "")
|
|
29576
|
+
};
|
|
29577
|
+
const previous = deduped[deduped.length - 1];
|
|
29578
|
+
if (!previous) {
|
|
29579
|
+
deduped.push(current);
|
|
29580
|
+
continue;
|
|
29581
|
+
}
|
|
29582
|
+
const previousComparable = normalizeComparableMessageContent(previous.content || "");
|
|
29583
|
+
const currentComparable = normalizeComparableMessageContent(current.content || "");
|
|
29584
|
+
const sameRole = previous.role === current.role;
|
|
29585
|
+
const sameKind = (previous.kind || "standard") === (current.kind || "standard");
|
|
29586
|
+
const sameSender = (previous.senderName || "") === (current.senderName || "");
|
|
29587
|
+
const comparableMatch = previousComparable && previousComparable === currentComparable;
|
|
29588
|
+
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
29589
|
+
deduped[deduped.length - 1] = chooseMoreComparableCliMessage(previous, current);
|
|
29590
|
+
continue;
|
|
29591
|
+
}
|
|
29592
|
+
deduped.push(current);
|
|
29593
|
+
}
|
|
29594
|
+
return deduped;
|
|
29595
|
+
}
|
|
29509
29596
|
function normalizeCliParsedMessages(parsedMessages, options) {
|
|
29510
|
-
return hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
29597
|
+
return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
29511
29598
|
role: message.role,
|
|
29512
29599
|
content: message.content,
|
|
29513
29600
|
timestamp: message.timestamp,
|
|
@@ -29517,7 +29604,7 @@ var require_dist2 = __commonJS({
|
|
|
29517
29604
|
index: message.index,
|
|
29518
29605
|
meta: message.meta,
|
|
29519
29606
|
senderName: message.senderName
|
|
29520
|
-
}));
|
|
29607
|
+
})));
|
|
29521
29608
|
}
|
|
29522
29609
|
function buildCliParseInput(options) {
|
|
29523
29610
|
const {
|
|
@@ -30177,7 +30264,7 @@ var require_dist2 = __commonJS({
|
|
|
30177
30264
|
if (!hasStartupOutput) return;
|
|
30178
30265
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
30179
30266
|
if (stableMs < 2e3) return;
|
|
30180
|
-
const startupModal = this.
|
|
30267
|
+
const startupModal = this.runParseApproval(this.recentOutputBuffer);
|
|
30181
30268
|
this.startupParseGate = false;
|
|
30182
30269
|
if (this.startupSettleTimer) {
|
|
30183
30270
|
clearTimeout(this.startupSettleTimer);
|
|
@@ -30234,11 +30321,17 @@ var require_dist2 = __commonJS({
|
|
|
30234
30321
|
if (this.currentStatus !== "waiting_approval") return;
|
|
30235
30322
|
const tail = this.recentOutputBuffer;
|
|
30236
30323
|
const screenText = this.terminalScreen.getText() || "";
|
|
30237
|
-
const
|
|
30238
|
-
const modal = this.runParseApproval(tail) || startupModal;
|
|
30324
|
+
const modal = this.runParseApproval(tail);
|
|
30239
30325
|
const stillWaiting = this.runDetectStatus(tail) === "waiting_approval" || !!modal;
|
|
30240
30326
|
if (stillWaiting) {
|
|
30241
|
-
|
|
30327
|
+
if (!modal) {
|
|
30328
|
+
LOG2.warn("CLI", `[${this.cliType}] approval timeout check found no actionable modal; keeping approval state fail-closed`);
|
|
30329
|
+
this.activeModal = null;
|
|
30330
|
+
this.onStatusChange?.();
|
|
30331
|
+
this.armApprovalExitTimeout();
|
|
30332
|
+
return;
|
|
30333
|
+
}
|
|
30334
|
+
this.activeModal = modal;
|
|
30242
30335
|
this.onStatusChange?.();
|
|
30243
30336
|
this.armApprovalExitTimeout();
|
|
30244
30337
|
return;
|
|
@@ -30250,81 +30343,12 @@ var require_dist2 = __commonJS({
|
|
|
30250
30343
|
this.onStatusChange?.();
|
|
30251
30344
|
}, 6e4);
|
|
30252
30345
|
}
|
|
30253
|
-
looksLikeVisibleIdlePrompt(screenText) {
|
|
30254
|
-
const text = String(screenText || "");
|
|
30255
|
-
if (!text.trim()) return false;
|
|
30256
|
-
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)) {
|
|
30257
|
-
return true;
|
|
30258
|
-
}
|
|
30259
|
-
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);
|
|
30260
|
-
}
|
|
30261
|
-
findLastMatchingLineIndex(lines, predicate) {
|
|
30262
|
-
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
30263
|
-
if (predicate(lines[index])) return index;
|
|
30264
|
-
}
|
|
30265
|
-
return -1;
|
|
30266
|
-
}
|
|
30267
|
-
looksLikeClaudeGeneratingLine(line) {
|
|
30268
|
-
const trimmed = String(line || "").trim();
|
|
30269
|
-
if (!trimmed) return false;
|
|
30270
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) return false;
|
|
30271
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
|
|
30272
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+\S+.*\b(?:thinking|thought for \d+s?)\b/i.test(trimmed)) return true;
|
|
30273
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+[A-Z][A-Za-z-]{3,}ing\b.*(?:…|\.{3})/u.test(trimmed)) return true;
|
|
30274
|
-
if (/^[⏺•]\s+(?:Reading|Writing|Editing|Searching|Inspecting|Planning|Analyzing|Synthesizing|Drafting|Running|Listing|Scanning|Matching)\b.*(?:…|\.{3})/i.test(trimmed)) {
|
|
30275
|
-
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);
|
|
30276
|
-
}
|
|
30277
|
-
return false;
|
|
30278
|
-
}
|
|
30279
|
-
detectClaudeGeneratingOverride(screenText, tail) {
|
|
30280
|
-
if (this.cliType !== "claude-cli") return false;
|
|
30281
|
-
const source = sanitizeTerminalText(screenText || tail || "");
|
|
30282
|
-
if (!source.trim()) return false;
|
|
30283
|
-
const allLines = source.split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
30284
|
-
if (allLines.length === 0) return false;
|
|
30285
|
-
const recentLines = allLines.slice(-12);
|
|
30286
|
-
const promptIndex = this.findLastMatchingLineIndex(recentLines, (line) => /^[❯›>]\s*$/.test(line));
|
|
30287
|
-
const activeRegion = promptIndex >= 0 ? recentLines.slice(Math.max(0, promptIndex - 2), promptIndex) : recentLines;
|
|
30288
|
-
if (activeRegion.length === 0) return false;
|
|
30289
|
-
return activeRegion.some((line) => this.looksLikeClaudeGeneratingLine(line));
|
|
30290
|
-
}
|
|
30291
|
-
refineDetectedStatus(status, tail, screenText) {
|
|
30292
|
-
if (this.startupParseGate) {
|
|
30293
|
-
return this.getStartupConfirmationModal(screenText || "") ? "waiting_approval" : "starting";
|
|
30294
|
-
}
|
|
30295
|
-
if (status === "waiting_approval") return status;
|
|
30296
|
-
if (this.detectClaudeGeneratingOverride(screenText || "", tail)) return "generating";
|
|
30297
|
-
return status;
|
|
30298
|
-
}
|
|
30299
|
-
looksLikeVisibleAssistantCandidate(screenText) {
|
|
30300
|
-
const lines = sanitizeTerminalText(String(screenText || "")).split(/\r\n|\n|\r/g);
|
|
30301
|
-
for (const line of lines) {
|
|
30302
|
-
const trimmed = String(line || "").trim();
|
|
30303
|
-
if (!trimmed) continue;
|
|
30304
|
-
if (/^➜\s+\S+/.test(trimmed)) continue;
|
|
30305
|
-
if (/^Update available!/i.test(trimmed)) continue;
|
|
30306
|
-
if (/Claude Code v\d/i.test(trimmed)) continue;
|
|
30307
|
-
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) continue;
|
|
30308
|
-
if (/^[◐◑◒◓◴◵◶◷◸◹◺◿].*\/effort/i.test(trimmed)) continue;
|
|
30309
|
-
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+$/.test(trimmed)) continue;
|
|
30310
|
-
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) continue;
|
|
30311
|
-
const assistantMatch = trimmed.match(/^⏺\s+(.+)$/);
|
|
30312
|
-
if (!assistantMatch) continue;
|
|
30313
|
-
const content = assistantMatch[1].trim();
|
|
30314
|
-
if (!content) continue;
|
|
30315
|
-
if (/^(?:Bash|Read|Write|Edit|MultiEdit|Task|Glob|Grep|LS|NotebookEdit)\(/.test(content)) continue;
|
|
30316
|
-
if (/This command requires approval|Do you want to proceed|Allow once|Always allow/i.test(content)) continue;
|
|
30317
|
-
return true;
|
|
30318
|
-
}
|
|
30319
|
-
return false;
|
|
30320
|
-
}
|
|
30321
30346
|
shouldRetryFinishResponse(commitResult) {
|
|
30322
30347
|
if (!this.currentTurnScope) return false;
|
|
30323
30348
|
if (this.currentStatus === "waiting_approval" || this.activeModal) return false;
|
|
30324
30349
|
if (this.finishRetryCount >= _ProviderCliAdapter.MAX_FINISH_RETRIES) return false;
|
|
30325
30350
|
if (commitResult.hasAssistant && commitResult.assistantContent.trim()) return false;
|
|
30326
|
-
|
|
30327
|
-
if (!this.looksLikeVisibleAssistantCandidate(screenText)) return false;
|
|
30351
|
+
if (this.runDetectStatus(this.recentOutputBuffer) !== "idle") return false;
|
|
30328
30352
|
const now = Date.now();
|
|
30329
30353
|
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
30330
30354
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
@@ -30348,45 +30372,21 @@ var require_dist2 = __commonJS({
|
|
|
30348
30372
|
}
|
|
30349
30373
|
return false;
|
|
30350
30374
|
}
|
|
30351
|
-
getStartupConfirmationModal(screenText) {
|
|
30352
|
-
const text = sanitizeTerminalText(String(screenText || ""));
|
|
30353
|
-
if (!text.trim()) return null;
|
|
30354
|
-
if (this.cliType === "claude-cli") {
|
|
30355
|
-
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);
|
|
30356
|
-
const hasConfirmFooter = /Press Enter to (?:continue|confirm)/i.test(text) || /Enter to confirm/i.test(text) || /Esc to (?:cancel|exit)/i.test(text);
|
|
30357
|
-
if (hasTrustPrompt || hasConfirmFooter && /trust/i.test(text)) {
|
|
30358
|
-
return {
|
|
30359
|
-
message: "Confirm Claude Code project trust",
|
|
30360
|
-
buttons: ["Continue"]
|
|
30361
|
-
};
|
|
30362
|
-
}
|
|
30363
|
-
}
|
|
30364
|
-
return null;
|
|
30365
|
-
}
|
|
30366
|
-
shouldResolveModalWithEnter(modal, buttonIndex) {
|
|
30367
|
-
if (!modal || buttonIndex !== 0) return false;
|
|
30368
|
-
const buttons = Array.isArray(modal.buttons) ? modal.buttons : [];
|
|
30369
|
-
if (buttons.length !== 1) return false;
|
|
30370
|
-
const buttonLabel = String(buttons[0] || "").trim();
|
|
30371
|
-
return looksLikeConfirmOnlyLabel(buttonLabel);
|
|
30372
|
-
}
|
|
30373
30375
|
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
30374
30376
|
const startedAt = Date.now();
|
|
30375
30377
|
let loggedWait = false;
|
|
30376
30378
|
while (Date.now() - startedAt < maxWaitMs) {
|
|
30377
30379
|
this.resolveStartupState("interactive_wait");
|
|
30378
30380
|
const screenText = this.terminalScreen.getText() || "";
|
|
30379
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
30380
30381
|
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
30381
30382
|
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
30382
30383
|
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
30383
|
-
const
|
|
30384
|
-
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "generating";
|
|
30384
|
+
const interactiveReady = status === "idle" && stableMs >= 700 && recentlyOutput >= 350;
|
|
30385
30385
|
if (interactiveReady) {
|
|
30386
30386
|
if (loggedWait) {
|
|
30387
30387
|
LOG2.info(
|
|
30388
30388
|
"CLI",
|
|
30389
|
-
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput}
|
|
30389
|
+
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput})`
|
|
30390
30390
|
);
|
|
30391
30391
|
}
|
|
30392
30392
|
return;
|
|
@@ -30395,7 +30395,7 @@ var require_dist2 = __commonJS({
|
|
|
30395
30395
|
loggedWait = true;
|
|
30396
30396
|
LOG2.info(
|
|
30397
30397
|
"CLI",
|
|
30398
|
-
`[${this.cliType}] Waiting for interactive prompt:
|
|
30398
|
+
`[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
30399
30399
|
);
|
|
30400
30400
|
}
|
|
30401
30401
|
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
@@ -30406,13 +30406,12 @@ var require_dist2 = __commonJS({
|
|
|
30406
30406
|
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
30407
30407
|
);
|
|
30408
30408
|
}
|
|
30409
|
-
|
|
30410
|
-
|
|
30411
|
-
const
|
|
30412
|
-
|
|
30413
|
-
|
|
30414
|
-
|
|
30415
|
-
}
|
|
30409
|
+
trimLastAssistantEcho(messages, prompt) {
|
|
30410
|
+
if (!prompt) return;
|
|
30411
|
+
const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
|
|
30412
|
+
if (last) last.content = trimPromptEchoPrefix(last.content, prompt);
|
|
30413
|
+
}
|
|
30414
|
+
clearAllTimers() {
|
|
30416
30415
|
if (this.responseTimeout) {
|
|
30417
30416
|
clearTimeout(this.responseTimeout);
|
|
30418
30417
|
this.responseTimeout = null;
|
|
@@ -30425,10 +30424,38 @@ var require_dist2 = __commonJS({
|
|
|
30425
30424
|
clearTimeout(this.approvalExitTimeout);
|
|
30426
30425
|
this.approvalExitTimeout = null;
|
|
30427
30426
|
}
|
|
30427
|
+
if (this.submitRetryTimer) {
|
|
30428
|
+
clearTimeout(this.submitRetryTimer);
|
|
30429
|
+
this.submitRetryTimer = null;
|
|
30430
|
+
}
|
|
30428
30431
|
if (this.finishRetryTimer) {
|
|
30429
30432
|
clearTimeout(this.finishRetryTimer);
|
|
30430
30433
|
this.finishRetryTimer = null;
|
|
30431
30434
|
}
|
|
30435
|
+
if (this.settleTimer) {
|
|
30436
|
+
clearTimeout(this.settleTimer);
|
|
30437
|
+
this.settleTimer = null;
|
|
30438
|
+
}
|
|
30439
|
+
if (this.pendingScriptStatusTimer) {
|
|
30440
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
30441
|
+
this.pendingScriptStatusTimer = null;
|
|
30442
|
+
}
|
|
30443
|
+
if (this.pendingOutputParseTimer) {
|
|
30444
|
+
clearTimeout(this.pendingOutputParseTimer);
|
|
30445
|
+
this.pendingOutputParseTimer = null;
|
|
30446
|
+
}
|
|
30447
|
+
if (this.ptyOutputFlushTimer) {
|
|
30448
|
+
clearTimeout(this.ptyOutputFlushTimer);
|
|
30449
|
+
this.ptyOutputFlushTimer = null;
|
|
30450
|
+
}
|
|
30451
|
+
}
|
|
30452
|
+
clearStaleIdleResponseGuard(reason) {
|
|
30453
|
+
const blockingModal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
30454
|
+
const isIdle = this.runDetectStatus(this.recentOutputBuffer) === "idle";
|
|
30455
|
+
if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !isIdle || !!blockingModal) {
|
|
30456
|
+
return false;
|
|
30457
|
+
}
|
|
30458
|
+
this.clearAllTimers();
|
|
30432
30459
|
this.clearIdleFinishCandidate(reason);
|
|
30433
30460
|
this.responseBuffer = "";
|
|
30434
30461
|
this.isWaitingForResponse = false;
|
|
@@ -30438,10 +30465,7 @@ var require_dist2 = __commonJS({
|
|
|
30438
30465
|
this.finishRetryCount = 0;
|
|
30439
30466
|
this.currentTurnScope = null;
|
|
30440
30467
|
this.activeModal = null;
|
|
30441
|
-
this.recordTrace("stale_idle_response_cleared", {
|
|
30442
|
-
reason,
|
|
30443
|
-
screenText: summarizeCliTraceText(screenText, 240)
|
|
30444
|
-
});
|
|
30468
|
+
this.recordTrace("stale_idle_response_cleared", { reason });
|
|
30445
30469
|
return true;
|
|
30446
30470
|
}
|
|
30447
30471
|
hasMeaningfulResponseBuffer(promptSnippet) {
|
|
@@ -30476,16 +30500,15 @@ var require_dist2 = __commonJS({
|
|
|
30476
30500
|
if (this.startupParseGate) {
|
|
30477
30501
|
return;
|
|
30478
30502
|
}
|
|
30479
|
-
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
30480
30503
|
const parsedTranscript = this.parseCurrentTranscript(
|
|
30481
30504
|
this.committedMessages,
|
|
30482
30505
|
this.responseBuffer,
|
|
30483
30506
|
this.currentTurnScope
|
|
30484
30507
|
);
|
|
30485
30508
|
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
|
|
30486
|
-
const modal = this.runParseApproval(tail) || parsedModal
|
|
30509
|
+
const modal = this.runParseApproval(tail) || parsedModal;
|
|
30487
30510
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
30488
|
-
const scriptStatus =
|
|
30511
|
+
const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
|
|
30489
30512
|
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
30490
30513
|
committedMessages: this.committedMessages,
|
|
30491
30514
|
scope: this.currentTurnScope,
|
|
@@ -30540,15 +30563,44 @@ var require_dist2 = __commonJS({
|
|
|
30540
30563
|
}
|
|
30541
30564
|
if (!scriptStatus) return;
|
|
30542
30565
|
const prevStatus = this.currentStatus;
|
|
30543
|
-
const
|
|
30566
|
+
const ctx = { now, screenText, modal, scriptStatus, parsedTranscript, parsedMessages, lastParsedAssistant, parsedShowsLiveAssistantProgress, prevStatus };
|
|
30567
|
+
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
30568
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
30569
|
+
LOG2.info(
|
|
30570
|
+
"CLI",
|
|
30571
|
+
`[${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)}`
|
|
30572
|
+
);
|
|
30573
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedTranscript?.status === "idle" && !!lastParsedAssistant);
|
|
30574
|
+
if (shouldHoldGenerating) {
|
|
30575
|
+
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
30576
|
+
return;
|
|
30577
|
+
}
|
|
30578
|
+
if (scriptStatus === "waiting_approval") {
|
|
30579
|
+
this.applyWaitingApproval(ctx);
|
|
30580
|
+
return;
|
|
30581
|
+
}
|
|
30582
|
+
if (scriptStatus === "generating") {
|
|
30583
|
+
this.applyGenerating(ctx);
|
|
30584
|
+
return;
|
|
30585
|
+
}
|
|
30586
|
+
if (scriptStatus === "idle") {
|
|
30587
|
+
this.applyIdle(ctx, now);
|
|
30588
|
+
}
|
|
30589
|
+
}
|
|
30590
|
+
// Returns false if the caller should bail out (debounce pending).
|
|
30591
|
+
applyPendingScriptStatusDebounce(ctx) {
|
|
30592
|
+
const { now, scriptStatus, prevStatus } = ctx;
|
|
30593
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (scriptStatus === "generating" || scriptStatus === "waiting_approval");
|
|
30594
|
+
if (!shouldDebounce) {
|
|
30544
30595
|
this.pendingScriptStatus = null;
|
|
30545
30596
|
this.pendingScriptStatusSince = 0;
|
|
30546
30597
|
if (this.pendingScriptStatusTimer) {
|
|
30547
30598
|
clearTimeout(this.pendingScriptStatusTimer);
|
|
30548
30599
|
this.pendingScriptStatusTimer = null;
|
|
30549
30600
|
}
|
|
30550
|
-
|
|
30551
|
-
|
|
30601
|
+
return true;
|
|
30602
|
+
}
|
|
30603
|
+
const armPending = (delayMs) => {
|
|
30552
30604
|
if (this.pendingScriptStatusTimer) clearTimeout(this.pendingScriptStatusTimer);
|
|
30553
30605
|
this.pendingScriptStatusTimer = setTimeout(() => {
|
|
30554
30606
|
this.pendingScriptStatusTimer = null;
|
|
@@ -30556,200 +30608,187 @@ var require_dist2 = __commonJS({
|
|
|
30556
30608
|
this.evaluateSettled();
|
|
30557
30609
|
}, delayMs);
|
|
30558
30610
|
};
|
|
30559
|
-
|
|
30560
|
-
|
|
30561
|
-
|
|
30562
|
-
|
|
30563
|
-
|
|
30564
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
30565
|
-
return;
|
|
30566
|
-
}
|
|
30567
|
-
const elapsed = now - this.pendingScriptStatusSince;
|
|
30568
|
-
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
30569
|
-
armPendingScriptStatus(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
30570
|
-
return;
|
|
30571
|
-
}
|
|
30572
|
-
} else {
|
|
30573
|
-
clearPendingScriptStatus();
|
|
30574
|
-
}
|
|
30575
|
-
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
30576
|
-
const statusActivityHoldMs = this.getStatusActivityHoldMs();
|
|
30577
|
-
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
30578
|
-
const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
|
|
30579
|
-
if (this.currentTurnScope && this.cliType === "claude-cli") {
|
|
30580
|
-
LOG2.info(
|
|
30581
|
-
"CLI",
|
|
30582
|
-
`[${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)}`
|
|
30583
|
-
);
|
|
30611
|
+
if (this.pendingScriptStatus !== scriptStatus) {
|
|
30612
|
+
this.pendingScriptStatus = scriptStatus;
|
|
30613
|
+
this.pendingScriptStatusSince = now;
|
|
30614
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
30615
|
+
return false;
|
|
30584
30616
|
}
|
|
30585
|
-
const
|
|
30586
|
-
if (
|
|
30587
|
-
|
|
30588
|
-
|
|
30589
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30590
|
-
this.idleTimeout = setTimeout(() => {
|
|
30591
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30592
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30593
|
-
this.finishResponse();
|
|
30594
|
-
}
|
|
30595
|
-
}, this.timeouts.generatingIdle);
|
|
30596
|
-
this.recordTrace("hold_generating_recent_activity", {
|
|
30597
|
-
scriptStatus,
|
|
30598
|
-
recentInteractiveActivity,
|
|
30599
|
-
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
30600
|
-
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
30601
|
-
holdMs: statusActivityHoldMs,
|
|
30602
|
-
...buildCliTraceParseSnapshot({
|
|
30603
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
30604
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30605
|
-
responseBuffer: this.responseBuffer,
|
|
30606
|
-
partialResponse: this.responseBuffer,
|
|
30607
|
-
scope: this.currentTurnScope
|
|
30608
|
-
})
|
|
30609
|
-
});
|
|
30610
|
-
this.onStatusChange?.();
|
|
30611
|
-
return;
|
|
30617
|
+
const elapsed = now - this.pendingScriptStatusSince;
|
|
30618
|
+
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
30619
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
30620
|
+
return false;
|
|
30612
30621
|
}
|
|
30613
|
-
|
|
30614
|
-
|
|
30615
|
-
|
|
30616
|
-
|
|
30617
|
-
|
|
30618
|
-
|
|
30619
|
-
|
|
30620
|
-
|
|
30621
|
-
|
|
30622
|
-
this.
|
|
30623
|
-
|
|
30624
|
-
|
|
30625
|
-
|
|
30626
|
-
|
|
30627
|
-
|
|
30628
|
-
|
|
30629
|
-
|
|
30630
|
-
|
|
30631
|
-
|
|
30632
|
-
|
|
30633
|
-
|
|
30634
|
-
|
|
30635
|
-
this.
|
|
30636
|
-
|
|
30622
|
+
return true;
|
|
30623
|
+
}
|
|
30624
|
+
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
30625
|
+
const { scriptStatus } = ctx;
|
|
30626
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
30627
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
30628
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30629
|
+
this.idleTimeout = setTimeout(() => {
|
|
30630
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30631
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30632
|
+
this.finishResponse();
|
|
30633
|
+
}
|
|
30634
|
+
}, this.timeouts.generatingIdle);
|
|
30635
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
30636
|
+
scriptStatus,
|
|
30637
|
+
recentInteractiveActivity,
|
|
30638
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
30639
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
30640
|
+
holdMs: this.getStatusActivityHoldMs(),
|
|
30641
|
+
...buildCliTraceParseSnapshot({
|
|
30642
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
30643
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30644
|
+
responseBuffer: this.responseBuffer,
|
|
30645
|
+
partialResponse: this.responseBuffer,
|
|
30646
|
+
scope: this.currentTurnScope
|
|
30647
|
+
})
|
|
30648
|
+
});
|
|
30649
|
+
this.onStatusChange?.();
|
|
30650
|
+
}
|
|
30651
|
+
applyWaitingApproval(ctx) {
|
|
30652
|
+
const { modal } = ctx;
|
|
30653
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
30654
|
+
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
30655
|
+
if (inCooldown && !modal) {
|
|
30656
|
+
if (this.approvalExitTimeout) {
|
|
30657
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30658
|
+
this.approvalExitTimeout = null;
|
|
30637
30659
|
}
|
|
30638
|
-
|
|
30639
|
-
|
|
30640
|
-
this.setStatus("
|
|
30641
|
-
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
30660
|
+
this.activeModal = null;
|
|
30661
|
+
if (this.isWaitingForResponse) {
|
|
30662
|
+
this.setStatus("generating", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
30642
30663
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30643
|
-
this.
|
|
30644
|
-
|
|
30645
|
-
|
|
30664
|
+
this.idleTimeout = setTimeout(() => {
|
|
30665
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30666
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30667
|
+
this.finishResponse();
|
|
30668
|
+
}
|
|
30669
|
+
}, this.timeouts.generatingIdle);
|
|
30670
|
+
} else {
|
|
30671
|
+
this.setStatus("idle", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
30646
30672
|
}
|
|
30673
|
+
this.onStatusChange?.();
|
|
30674
|
+
return;
|
|
30647
30675
|
}
|
|
30648
|
-
if (
|
|
30649
|
-
|
|
30650
|
-
|
|
30651
|
-
const noActiveTurn = !this.currentTurnScope;
|
|
30652
|
-
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));
|
|
30653
|
-
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
30676
|
+
if (!inCooldown) {
|
|
30677
|
+
if (!modal) {
|
|
30678
|
+
LOG2.warn("CLI", `[${this.cliType}] detectStatus reported waiting_approval without parseApproval modal; ignoring non-actionable approval state`);
|
|
30654
30679
|
return;
|
|
30655
30680
|
}
|
|
30656
|
-
|
|
30657
|
-
|
|
30658
|
-
|
|
30659
|
-
this.approvalExitTimeout = null;
|
|
30660
|
-
}
|
|
30661
|
-
this.activeModal = null;
|
|
30662
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
30663
|
-
}
|
|
30664
|
-
if (!this.isWaitingForResponse) {
|
|
30665
|
-
this.isWaitingForResponse = true;
|
|
30666
|
-
this.responseBuffer = "";
|
|
30667
|
-
}
|
|
30668
|
-
this.setStatus("generating", "script_detect");
|
|
30681
|
+
this.isWaitingForResponse = true;
|
|
30682
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
30683
|
+
this.activeModal = modal;
|
|
30669
30684
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30670
|
-
this.
|
|
30671
|
-
if (this.isWaitingForResponse) {
|
|
30672
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30673
|
-
this.finishResponse();
|
|
30674
|
-
}
|
|
30675
|
-
}, this.timeouts.generatingIdle);
|
|
30685
|
+
this.armApprovalExitTimeout();
|
|
30676
30686
|
this.onStatusChange?.();
|
|
30687
|
+
}
|
|
30688
|
+
}
|
|
30689
|
+
applyGenerating(ctx) {
|
|
30690
|
+
const { screenText, modal, parsedShowsLiveAssistantProgress, prevStatus } = ctx;
|
|
30691
|
+
this.clearIdleFinishCandidate("generating");
|
|
30692
|
+
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
30693
|
+
const noActiveTurn = !this.currentTurnScope;
|
|
30694
|
+
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));
|
|
30695
|
+
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
30677
30696
|
return;
|
|
30678
30697
|
}
|
|
30679
|
-
if (
|
|
30680
|
-
if (
|
|
30681
|
-
|
|
30682
|
-
|
|
30683
|
-
this.approvalExitTimeout = null;
|
|
30684
|
-
}
|
|
30685
|
-
this.activeModal = null;
|
|
30686
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
30698
|
+
if (prevStatus === "waiting_approval") {
|
|
30699
|
+
if (this.approvalExitTimeout) {
|
|
30700
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30701
|
+
this.approvalExitTimeout = null;
|
|
30687
30702
|
}
|
|
30703
|
+
this.activeModal = null;
|
|
30704
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
30705
|
+
}
|
|
30706
|
+
if (!this.isWaitingForResponse) {
|
|
30707
|
+
this.isWaitingForResponse = true;
|
|
30708
|
+
this.responseBuffer = "";
|
|
30709
|
+
}
|
|
30710
|
+
this.setStatus("generating", "script_detect");
|
|
30711
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30712
|
+
this.idleTimeout = setTimeout(() => {
|
|
30688
30713
|
if (this.isWaitingForResponse) {
|
|
30689
|
-
|
|
30690
|
-
|
|
30691
|
-
|
|
30692
|
-
|
|
30693
|
-
|
|
30694
|
-
|
|
30695
|
-
|
|
30696
|
-
|
|
30697
|
-
|
|
30698
|
-
|
|
30699
|
-
|
|
30700
|
-
|
|
30701
|
-
|
|
30702
|
-
|
|
30703
|
-
|
|
30704
|
-
|
|
30705
|
-
|
|
30706
|
-
|
|
30707
|
-
hasModal: !!modal,
|
|
30708
|
-
idleQuietThresholdMs,
|
|
30709
|
-
idleStableThresholdMs,
|
|
30710
|
-
idleReady,
|
|
30711
|
-
idleFinishConfirmMs,
|
|
30712
|
-
idleFinishCandidate: candidate,
|
|
30713
|
-
candidateQuiet,
|
|
30714
|
-
canFinishImmediately,
|
|
30715
|
-
submitPendingUntil: this.submitPendingUntil,
|
|
30716
|
-
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
30717
|
-
...buildCliTraceParseSnapshot({
|
|
30718
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
30719
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30720
|
-
responseBuffer: this.responseBuffer,
|
|
30721
|
-
partialResponse: this.responseBuffer,
|
|
30722
|
-
scope: this.currentTurnScope
|
|
30723
|
-
})
|
|
30724
|
-
});
|
|
30725
|
-
if (canFinishImmediately) {
|
|
30726
|
-
this.clearIdleFinishCandidate("finish_response");
|
|
30727
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30728
|
-
this.finishResponse();
|
|
30729
|
-
return;
|
|
30730
|
-
}
|
|
30731
|
-
if (idleReady) {
|
|
30732
|
-
if (!candidate) {
|
|
30733
|
-
this.armIdleFinishCandidate(assistantLength);
|
|
30734
|
-
return;
|
|
30735
|
-
}
|
|
30736
|
-
} else {
|
|
30737
|
-
this.clearIdleFinishCandidate("idle_not_ready");
|
|
30738
|
-
}
|
|
30739
|
-
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30740
|
-
this.idleTimeout = setTimeout(() => {
|
|
30741
|
-
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30742
|
-
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30743
|
-
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
30744
|
-
this.finishResponse();
|
|
30745
|
-
}
|
|
30746
|
-
}, this.timeouts.idleFinish);
|
|
30747
|
-
} else if (prevStatus !== "idle") {
|
|
30714
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30715
|
+
this.finishResponse();
|
|
30716
|
+
}
|
|
30717
|
+
}, this.timeouts.generatingIdle);
|
|
30718
|
+
this.onStatusChange?.();
|
|
30719
|
+
}
|
|
30720
|
+
applyIdle(ctx, now) {
|
|
30721
|
+
const { screenText, modal, lastParsedAssistant, prevStatus } = ctx;
|
|
30722
|
+
if (prevStatus === "waiting_approval") {
|
|
30723
|
+
if (this.approvalExitTimeout) {
|
|
30724
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30725
|
+
this.approvalExitTimeout = null;
|
|
30726
|
+
}
|
|
30727
|
+
this.activeModal = null;
|
|
30728
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
30729
|
+
}
|
|
30730
|
+
if (!this.isWaitingForResponse) {
|
|
30731
|
+
if (prevStatus !== "idle") {
|
|
30748
30732
|
this.clearIdleFinishCandidate("idle_without_response");
|
|
30749
30733
|
this.setStatus("idle", "script_detect");
|
|
30750
30734
|
this.onStatusChange?.();
|
|
30751
30735
|
}
|
|
30736
|
+
return;
|
|
30737
|
+
}
|
|
30738
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
30739
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
30740
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
30741
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
30742
|
+
const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
|
|
30743
|
+
const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
|
|
30744
|
+
const idleReady = !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleFinishConfirmMs;
|
|
30745
|
+
const candidate = this.idleFinishCandidate;
|
|
30746
|
+
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
|
|
30747
|
+
this.recordTrace("idle_decision", {
|
|
30748
|
+
quietForMs,
|
|
30749
|
+
screenStableMs,
|
|
30750
|
+
hasAssistantTurn,
|
|
30751
|
+
assistantLength,
|
|
30752
|
+
hasModal: !!modal,
|
|
30753
|
+
idleQuietThresholdMs,
|
|
30754
|
+
idleStableThresholdMs: idleFinishConfirmMs,
|
|
30755
|
+
idleReady,
|
|
30756
|
+
idleFinishConfirmMs,
|
|
30757
|
+
idleFinishCandidate: candidate,
|
|
30758
|
+
candidateQuiet,
|
|
30759
|
+
canFinishImmediately: idleReady && candidateQuiet,
|
|
30760
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
30761
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
30762
|
+
...buildCliTraceParseSnapshot({
|
|
30763
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
30764
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30765
|
+
responseBuffer: this.responseBuffer,
|
|
30766
|
+
partialResponse: this.responseBuffer,
|
|
30767
|
+
scope: this.currentTurnScope
|
|
30768
|
+
})
|
|
30769
|
+
});
|
|
30770
|
+
if (idleReady && candidateQuiet) {
|
|
30771
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
30772
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30773
|
+
this.finishResponse();
|
|
30774
|
+
return;
|
|
30752
30775
|
}
|
|
30776
|
+
if (idleReady) {
|
|
30777
|
+
if (!candidate) {
|
|
30778
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
30779
|
+
return;
|
|
30780
|
+
}
|
|
30781
|
+
} else {
|
|
30782
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
30783
|
+
}
|
|
30784
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30785
|
+
this.idleTimeout = setTimeout(() => {
|
|
30786
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30787
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30788
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
30789
|
+
this.finishResponse();
|
|
30790
|
+
}
|
|
30791
|
+
}, this.timeouts.idleFinish);
|
|
30753
30792
|
}
|
|
30754
30793
|
finishResponse() {
|
|
30755
30794
|
if (this.submitPendingUntil > Date.now()) return;
|
|
@@ -30788,26 +30827,7 @@ var require_dist2 = __commonJS({
|
|
|
30788
30827
|
}, _ProviderCliAdapter.FINISH_RETRY_DELAY_MS);
|
|
30789
30828
|
return;
|
|
30790
30829
|
}
|
|
30791
|
-
|
|
30792
|
-
clearTimeout(this.responseTimeout);
|
|
30793
|
-
this.responseTimeout = null;
|
|
30794
|
-
}
|
|
30795
|
-
if (this.idleTimeout) {
|
|
30796
|
-
clearTimeout(this.idleTimeout);
|
|
30797
|
-
this.idleTimeout = null;
|
|
30798
|
-
}
|
|
30799
|
-
if (this.approvalExitTimeout) {
|
|
30800
|
-
clearTimeout(this.approvalExitTimeout);
|
|
30801
|
-
this.approvalExitTimeout = null;
|
|
30802
|
-
}
|
|
30803
|
-
if (this.submitRetryTimer) {
|
|
30804
|
-
clearTimeout(this.submitRetryTimer);
|
|
30805
|
-
this.submitRetryTimer = null;
|
|
30806
|
-
}
|
|
30807
|
-
if (this.finishRetryTimer) {
|
|
30808
|
-
clearTimeout(this.finishRetryTimer);
|
|
30809
|
-
this.finishRetryTimer = null;
|
|
30810
|
-
}
|
|
30830
|
+
this.clearAllTimers();
|
|
30811
30831
|
this.responseBuffer = "";
|
|
30812
30832
|
this.isWaitingForResponse = false;
|
|
30813
30833
|
this.responseSettleIgnoreUntil = 0;
|
|
@@ -30819,18 +30839,12 @@ var require_dist2 = __commonJS({
|
|
|
30819
30839
|
this.setStatus("idle", "response_finished");
|
|
30820
30840
|
this.onStatusChange?.();
|
|
30821
30841
|
}
|
|
30822
|
-
maybeCommitVisibleIdleTranscript(parsed
|
|
30842
|
+
maybeCommitVisibleIdleTranscript(parsed) {
|
|
30823
30843
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
30824
30844
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
30825
30845
|
if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
|
|
30826
30846
|
return false;
|
|
30827
30847
|
}
|
|
30828
|
-
if (options?.requireVisibleAssistantCandidate) {
|
|
30829
|
-
const candidateText = options.screenText || this.terminalScreen.getText() || "";
|
|
30830
|
-
if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
|
|
30831
|
-
return false;
|
|
30832
|
-
}
|
|
30833
|
-
}
|
|
30834
30848
|
const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
30835
30849
|
committedMessages: this.committedMessages,
|
|
30836
30850
|
scope: this.currentTurnScope,
|
|
@@ -30839,33 +30853,8 @@ var require_dist2 = __commonJS({
|
|
|
30839
30853
|
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
30840
30854
|
if (!visibleAssistant) return false;
|
|
30841
30855
|
this.committedMessages = hydratedForIdleCommit;
|
|
30842
|
-
|
|
30843
|
-
|
|
30844
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
30845
|
-
if (lastAssistantForTrim) {
|
|
30846
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
30847
|
-
}
|
|
30848
|
-
}
|
|
30849
|
-
if (this.responseTimeout) {
|
|
30850
|
-
clearTimeout(this.responseTimeout);
|
|
30851
|
-
this.responseTimeout = null;
|
|
30852
|
-
}
|
|
30853
|
-
if (this.idleTimeout) {
|
|
30854
|
-
clearTimeout(this.idleTimeout);
|
|
30855
|
-
this.idleTimeout = null;
|
|
30856
|
-
}
|
|
30857
|
-
if (this.approvalExitTimeout) {
|
|
30858
|
-
clearTimeout(this.approvalExitTimeout);
|
|
30859
|
-
this.approvalExitTimeout = null;
|
|
30860
|
-
}
|
|
30861
|
-
if (this.submitRetryTimer) {
|
|
30862
|
-
clearTimeout(this.submitRetryTimer);
|
|
30863
|
-
this.submitRetryTimer = null;
|
|
30864
|
-
}
|
|
30865
|
-
if (this.finishRetryTimer) {
|
|
30866
|
-
clearTimeout(this.finishRetryTimer);
|
|
30867
|
-
this.finishRetryTimer = null;
|
|
30868
|
-
}
|
|
30856
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
30857
|
+
this.clearAllTimers();
|
|
30869
30858
|
this.syncMessageViews();
|
|
30870
30859
|
this.responseBuffer = "";
|
|
30871
30860
|
this.isWaitingForResponse = false;
|
|
@@ -30895,13 +30884,7 @@ var require_dist2 = __commonJS({
|
|
|
30895
30884
|
scope: this.currentTurnScope,
|
|
30896
30885
|
lastOutputAt: this.lastOutputAt
|
|
30897
30886
|
});
|
|
30898
|
-
|
|
30899
|
-
if (promptForTrim) {
|
|
30900
|
-
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
30901
|
-
if (lastAssistantForTrim) {
|
|
30902
|
-
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
30903
|
-
}
|
|
30904
|
-
}
|
|
30887
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
30905
30888
|
this.syncMessageViews();
|
|
30906
30889
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
30907
30890
|
if (this.currentTurnScope) {
|
|
@@ -30959,7 +30942,7 @@ var require_dist2 = __commonJS({
|
|
|
30959
30942
|
screen: buildCliScreenSnapshot(screenText),
|
|
30960
30943
|
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
30961
30944
|
});
|
|
30962
|
-
return
|
|
30945
|
+
return status;
|
|
30963
30946
|
} catch (e) {
|
|
30964
30947
|
LOG2.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
30965
30948
|
return null;
|
|
@@ -30999,23 +30982,21 @@ var require_dist2 = __commonJS({
|
|
|
30999
30982
|
if (!inApprovalCooldown) {
|
|
31000
30983
|
return parsed;
|
|
31001
30984
|
}
|
|
31002
|
-
const
|
|
31003
|
-
const visibleModal = this.runParseApproval(recentBuffer) || startupModal;
|
|
30985
|
+
const visibleModal = this.runParseApproval(recentBuffer);
|
|
31004
30986
|
if (visibleModal) {
|
|
31005
30987
|
return parsed;
|
|
31006
30988
|
}
|
|
31007
30989
|
const detectedStatus = this.runDetectStatus(recentBuffer);
|
|
31008
|
-
const
|
|
30990
|
+
const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
|
|
31009
30991
|
return {
|
|
31010
30992
|
...parsed,
|
|
31011
|
-
status:
|
|
30993
|
+
status: resolvedStatus,
|
|
31012
30994
|
activeModal: null
|
|
31013
30995
|
};
|
|
31014
30996
|
}
|
|
31015
30997
|
// ─── Public API (CliAdapter) ───────────────────
|
|
31016
30998
|
getStatus() {
|
|
31017
|
-
const
|
|
31018
|
-
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
30999
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
31019
31000
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
31020
31001
|
let effectiveModal = startupModal || this.activeModal;
|
|
31021
31002
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
@@ -31096,8 +31077,7 @@ var require_dist2 = __commonJS({
|
|
|
31096
31077
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
31097
31078
|
}));
|
|
31098
31079
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
31099
|
-
const
|
|
31100
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, committedHydratedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && visibleIdlePrompt);
|
|
31080
|
+
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");
|
|
31101
31081
|
if (shouldAdoptParsedIdleReplay) {
|
|
31102
31082
|
this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
31103
31083
|
committedMessages: this.committedMessages,
|
|
@@ -31226,17 +31206,9 @@ var require_dist2 = __commonJS({
|
|
|
31226
31206
|
if (parsed && typeof parsed === "object") {
|
|
31227
31207
|
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
31228
31208
|
}
|
|
31229
|
-
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
31230
|
-
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
31231
|
-
parsed.status = refinedStatus;
|
|
31232
|
-
}
|
|
31233
31209
|
const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
|
|
31234
|
-
|
|
31235
|
-
|
|
31236
|
-
const lastAssistant = [...normalizedParsed.messages].reverse().find((message) => message?.role === "assistant" && typeof message.content === "string");
|
|
31237
|
-
if (lastAssistant) {
|
|
31238
|
-
lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
|
|
31239
|
-
}
|
|
31210
|
+
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
31211
|
+
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
31240
31212
|
}
|
|
31241
31213
|
this.parseErrorMessage = null;
|
|
31242
31214
|
return normalizedParsed;
|
|
@@ -31264,16 +31236,11 @@ var require_dist2 = __commonJS({
|
|
|
31264
31236
|
LOG2.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
|
|
31265
31237
|
}
|
|
31266
31238
|
}
|
|
31267
|
-
if (!promptText
|
|
31268
|
-
|
|
31269
|
-
|
|
31270
|
-
${data.explanation || ""}
|
|
31271
|
-
|
|
31272
|
-
${data.message || ""}`.trim();
|
|
31273
|
-
}
|
|
31274
|
-
if (promptText) {
|
|
31275
|
-
await this.sendMessage(promptText);
|
|
31239
|
+
if (!promptText) {
|
|
31240
|
+
LOG2.warn("CLI", `[${this.cliType}] resolveAction skipped: provider script did not supply a prompt`);
|
|
31241
|
+
return;
|
|
31276
31242
|
}
|
|
31243
|
+
await this.sendMessage(promptText);
|
|
31277
31244
|
}
|
|
31278
31245
|
async sendMessage(text) {
|
|
31279
31246
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
@@ -31291,9 +31258,7 @@ ${data.message || ""}`.trim();
|
|
|
31291
31258
|
}
|
|
31292
31259
|
if (!this.ready) {
|
|
31293
31260
|
this.resolveStartupState("send_precheck");
|
|
31294
|
-
|
|
31295
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
31296
|
-
if (hasPrompt && this.currentStatus === "idle") {
|
|
31261
|
+
if (this.runDetectStatus(this.recentOutputBuffer) === "idle" && this.currentStatus === "idle") {
|
|
31297
31262
|
this.ready = true;
|
|
31298
31263
|
this.startupParseGate = false;
|
|
31299
31264
|
LOG2.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
@@ -31399,7 +31364,10 @@ ${data.message || ""}`.trim();
|
|
|
31399
31364
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
31400
31365
|
const screenText2 = this.terminalScreen.getText();
|
|
31401
31366
|
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
31402
|
-
|
|
31367
|
+
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
31368
|
+
if (liveApproval) return;
|
|
31369
|
+
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
31370
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
31403
31371
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
31404
31372
|
LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
31405
31373
|
this.recordTrace("submit_write", {
|
|
@@ -31436,6 +31404,10 @@ ${data.message || ""}`.trim();
|
|
|
31436
31404
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
31437
31405
|
const screenText = this.terminalScreen.getText();
|
|
31438
31406
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
31407
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
31408
|
+
if (liveApproval) return;
|
|
31409
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
31410
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
31439
31411
|
LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
31440
31412
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
31441
31413
|
this.recordTrace("submit_write", {
|
|
@@ -31567,44 +31539,9 @@ ${data.message || ""}`.trim();
|
|
|
31567
31539
|
}
|
|
31568
31540
|
shutdown() {
|
|
31569
31541
|
this.clearIdleFinishCandidate("shutdown");
|
|
31570
|
-
|
|
31571
|
-
clearTimeout(this.settleTimer);
|
|
31572
|
-
this.settleTimer = null;
|
|
31573
|
-
}
|
|
31574
|
-
if (this.approvalExitTimeout) {
|
|
31575
|
-
clearTimeout(this.approvalExitTimeout);
|
|
31576
|
-
this.approvalExitTimeout = null;
|
|
31577
|
-
}
|
|
31578
|
-
if (this.submitRetryTimer) {
|
|
31579
|
-
clearTimeout(this.submitRetryTimer);
|
|
31580
|
-
this.submitRetryTimer = null;
|
|
31581
|
-
}
|
|
31582
|
-
if (this.finishRetryTimer) {
|
|
31583
|
-
clearTimeout(this.finishRetryTimer);
|
|
31584
|
-
this.finishRetryTimer = null;
|
|
31585
|
-
}
|
|
31586
|
-
if (this.responseTimeout) {
|
|
31587
|
-
clearTimeout(this.responseTimeout);
|
|
31588
|
-
this.responseTimeout = null;
|
|
31589
|
-
}
|
|
31590
|
-
if (this.idleTimeout) {
|
|
31591
|
-
clearTimeout(this.idleTimeout);
|
|
31592
|
-
this.idleTimeout = null;
|
|
31593
|
-
}
|
|
31594
|
-
if (this.pendingScriptStatusTimer) {
|
|
31595
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
31596
|
-
this.pendingScriptStatusTimer = null;
|
|
31597
|
-
}
|
|
31598
|
-
if (this.pendingOutputParseTimer) {
|
|
31599
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
31600
|
-
this.pendingOutputParseTimer = null;
|
|
31601
|
-
}
|
|
31542
|
+
this.clearAllTimers();
|
|
31602
31543
|
this.pendingOutputParseBuffer = "";
|
|
31603
31544
|
this.pendingTerminalQueryTail = "";
|
|
31604
|
-
if (this.ptyOutputFlushTimer) {
|
|
31605
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
31606
|
-
this.ptyOutputFlushTimer = null;
|
|
31607
|
-
}
|
|
31608
31545
|
this.ptyOutputBuffer = "";
|
|
31609
31546
|
this.finishRetryCount = 0;
|
|
31610
31547
|
if (this.ptyProcess) {
|
|
@@ -31625,44 +31562,9 @@ ${data.message || ""}`.trim();
|
|
|
31625
31562
|
}
|
|
31626
31563
|
detach() {
|
|
31627
31564
|
this.clearIdleFinishCandidate("detach");
|
|
31628
|
-
|
|
31629
|
-
clearTimeout(this.settleTimer);
|
|
31630
|
-
this.settleTimer = null;
|
|
31631
|
-
}
|
|
31632
|
-
if (this.approvalExitTimeout) {
|
|
31633
|
-
clearTimeout(this.approvalExitTimeout);
|
|
31634
|
-
this.approvalExitTimeout = null;
|
|
31635
|
-
}
|
|
31636
|
-
if (this.submitRetryTimer) {
|
|
31637
|
-
clearTimeout(this.submitRetryTimer);
|
|
31638
|
-
this.submitRetryTimer = null;
|
|
31639
|
-
}
|
|
31640
|
-
if (this.finishRetryTimer) {
|
|
31641
|
-
clearTimeout(this.finishRetryTimer);
|
|
31642
|
-
this.finishRetryTimer = null;
|
|
31643
|
-
}
|
|
31644
|
-
if (this.responseTimeout) {
|
|
31645
|
-
clearTimeout(this.responseTimeout);
|
|
31646
|
-
this.responseTimeout = null;
|
|
31647
|
-
}
|
|
31648
|
-
if (this.idleTimeout) {
|
|
31649
|
-
clearTimeout(this.idleTimeout);
|
|
31650
|
-
this.idleTimeout = null;
|
|
31651
|
-
}
|
|
31652
|
-
if (this.pendingScriptStatusTimer) {
|
|
31653
|
-
clearTimeout(this.pendingScriptStatusTimer);
|
|
31654
|
-
this.pendingScriptStatusTimer = null;
|
|
31655
|
-
}
|
|
31656
|
-
if (this.pendingOutputParseTimer) {
|
|
31657
|
-
clearTimeout(this.pendingOutputParseTimer);
|
|
31658
|
-
this.pendingOutputParseTimer = null;
|
|
31659
|
-
}
|
|
31565
|
+
this.clearAllTimers();
|
|
31660
31566
|
this.pendingOutputParseBuffer = "";
|
|
31661
31567
|
this.pendingTerminalQueryTail = "";
|
|
31662
|
-
if (this.ptyOutputFlushTimer) {
|
|
31663
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
31664
|
-
this.ptyOutputFlushTimer = null;
|
|
31665
|
-
}
|
|
31666
31568
|
this.ptyOutputBuffer = "";
|
|
31667
31569
|
this.finishRetryCount = 0;
|
|
31668
31570
|
if (this.ptyProcess) {
|
|
@@ -31724,8 +31626,7 @@ ${data.message || ""}`.trim();
|
|
|
31724
31626
|
this.ptyProcess?.write(data);
|
|
31725
31627
|
}
|
|
31726
31628
|
resolveModal(buttonIndex) {
|
|
31727
|
-
|
|
31728
|
-
let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
31629
|
+
let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
31729
31630
|
if (!modal && typeof this.cliScripts?.parseOutput === "function") {
|
|
31730
31631
|
try {
|
|
31731
31632
|
const parsed = this.getScriptParsedStatus();
|
|
@@ -31756,12 +31657,7 @@ ${data.message || ""}`.trim();
|
|
|
31756
31657
|
}
|
|
31757
31658
|
this.setStatus("generating", "approval_resolved");
|
|
31758
31659
|
this.onStatusChange?.();
|
|
31759
|
-
|
|
31760
|
-
if (startupTrustModal && buttonIndex in this.approvalKeys) {
|
|
31761
|
-
this.ptyProcess.write(`${this.approvalKeys[buttonIndex]}\r`);
|
|
31762
|
-
} else if (this.shouldResolveModalWithEnter(modal, buttonIndex)) {
|
|
31763
|
-
this.ptyProcess.write("\r");
|
|
31764
|
-
} else if (buttonIndex in this.approvalKeys) {
|
|
31660
|
+
if (buttonIndex in this.approvalKeys) {
|
|
31765
31661
|
this.ptyProcess.write(this.approvalKeys[buttonIndex]);
|
|
31766
31662
|
} else {
|
|
31767
31663
|
const DOWN = "\x1B[B";
|
|
@@ -31781,7 +31677,7 @@ ${data.message || ""}`.trim();
|
|
|
31781
31677
|
}
|
|
31782
31678
|
getDebugState() {
|
|
31783
31679
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
31784
|
-
const startupModal = this.startupParseGate ? this.
|
|
31680
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
31785
31681
|
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
31786
31682
|
const effectiveReady = this.ready || !!startupModal;
|
|
31787
31683
|
return {
|
|
@@ -39030,25 +38926,23 @@ ${effect.notification.body || ""}`.trim();
|
|
|
39030
38926
|
const effectiveModal = statusModal || surfacedModal;
|
|
39031
38927
|
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
39032
38928
|
LOG2.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"}`);
|
|
39033
|
-
if (
|
|
38929
|
+
if (!effectiveModal) {
|
|
39034
38930
|
return { success: false, error: "Not in approval state" };
|
|
39035
38931
|
}
|
|
39036
|
-
const buttons = effectiveModal
|
|
38932
|
+
const buttons = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
|
|
39037
38933
|
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
39038
|
-
if (buttonIndex < 0) {
|
|
38934
|
+
if (buttonIndex < 0 && button) {
|
|
39039
38935
|
const btnLower = button.toLowerCase();
|
|
39040
38936
|
buttonIndex = buttons.findIndex((b2) => b2.toLowerCase().includes(btnLower));
|
|
39041
38937
|
}
|
|
38938
|
+
if (buttonIndex < 0 && (action === "reject" || action === "deny")) {
|
|
38939
|
+
buttonIndex = buttons.findIndex((b2) => /deny|reject|no/i.test(b2));
|
|
38940
|
+
}
|
|
38941
|
+
if (buttonIndex < 0 && (action === "always" || /always/i.test(button))) {
|
|
38942
|
+
buttonIndex = buttons.findIndex((b2) => /always/i.test(b2));
|
|
38943
|
+
}
|
|
39042
38944
|
if (buttonIndex < 0) {
|
|
39043
|
-
|
|
39044
|
-
buttonIndex = buttons.findIndex((b2) => /deny|reject|no/i.test(b2));
|
|
39045
|
-
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
39046
|
-
} else if (action === "always" || /always/i.test(button)) {
|
|
39047
|
-
buttonIndex = buttons.findIndex((b2) => /always/i.test(b2));
|
|
39048
|
-
if (buttonIndex < 0) buttonIndex = 1;
|
|
39049
|
-
} else {
|
|
39050
|
-
buttonIndex = 0;
|
|
39051
|
-
}
|
|
38945
|
+
return { success: false, error: "Approval action did not match any visible button" };
|
|
39052
38946
|
}
|
|
39053
38947
|
if (typeof adapter.resolveModal === "function") {
|
|
39054
38948
|
adapter.resolveModal(buttonIndex);
|