@adhdev/daemon-standalone 0.9.6 → 0.9.7
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 -486
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/index-BSO1MqUY.css +1 -0
- package/public/assets/index-BVPX5EsL.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,14 @@ 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
|
|
30487
|
-
const
|
|
30488
|
-
const scriptStatus = startupModal ? "waiting_approval" : parsedModal && parsedTranscript?.status === "waiting_approval" ? "waiting_approval" : rawScriptStatus;
|
|
30509
|
+
const modal = this.runParseApproval(tail) || parsedModal;
|
|
30510
|
+
const scriptStatus = this.runDetectStatus(tail);
|
|
30489
30511
|
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
30490
30512
|
committedMessages: this.committedMessages,
|
|
30491
30513
|
scope: this.currentTurnScope,
|
|
@@ -30540,15 +30562,44 @@ var require_dist2 = __commonJS({
|
|
|
30540
30562
|
}
|
|
30541
30563
|
if (!scriptStatus) return;
|
|
30542
30564
|
const prevStatus = this.currentStatus;
|
|
30543
|
-
const
|
|
30565
|
+
const ctx = { now, screenText, modal, scriptStatus, parsedTranscript, parsedMessages, lastParsedAssistant, parsedShowsLiveAssistantProgress, prevStatus };
|
|
30566
|
+
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
30567
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
30568
|
+
LOG2.info(
|
|
30569
|
+
"CLI",
|
|
30570
|
+
`[${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)}`
|
|
30571
|
+
);
|
|
30572
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedTranscript?.status === "idle" && !!lastParsedAssistant);
|
|
30573
|
+
if (shouldHoldGenerating) {
|
|
30574
|
+
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
30575
|
+
return;
|
|
30576
|
+
}
|
|
30577
|
+
if (scriptStatus === "waiting_approval") {
|
|
30578
|
+
this.applyWaitingApproval(ctx);
|
|
30579
|
+
return;
|
|
30580
|
+
}
|
|
30581
|
+
if (scriptStatus === "generating") {
|
|
30582
|
+
this.applyGenerating(ctx);
|
|
30583
|
+
return;
|
|
30584
|
+
}
|
|
30585
|
+
if (scriptStatus === "idle") {
|
|
30586
|
+
this.applyIdle(ctx, now);
|
|
30587
|
+
}
|
|
30588
|
+
}
|
|
30589
|
+
// Returns false if the caller should bail out (debounce pending).
|
|
30590
|
+
applyPendingScriptStatusDebounce(ctx) {
|
|
30591
|
+
const { now, scriptStatus, prevStatus } = ctx;
|
|
30592
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (scriptStatus === "generating" || scriptStatus === "waiting_approval");
|
|
30593
|
+
if (!shouldDebounce) {
|
|
30544
30594
|
this.pendingScriptStatus = null;
|
|
30545
30595
|
this.pendingScriptStatusSince = 0;
|
|
30546
30596
|
if (this.pendingScriptStatusTimer) {
|
|
30547
30597
|
clearTimeout(this.pendingScriptStatusTimer);
|
|
30548
30598
|
this.pendingScriptStatusTimer = null;
|
|
30549
30599
|
}
|
|
30550
|
-
|
|
30551
|
-
|
|
30600
|
+
return true;
|
|
30601
|
+
}
|
|
30602
|
+
const armPending = (delayMs) => {
|
|
30552
30603
|
if (this.pendingScriptStatusTimer) clearTimeout(this.pendingScriptStatusTimer);
|
|
30553
30604
|
this.pendingScriptStatusTimer = setTimeout(() => {
|
|
30554
30605
|
this.pendingScriptStatusTimer = null;
|
|
@@ -30556,200 +30607,187 @@ var require_dist2 = __commonJS({
|
|
|
30556
30607
|
this.evaluateSettled();
|
|
30557
30608
|
}, delayMs);
|
|
30558
30609
|
};
|
|
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
|
-
);
|
|
30610
|
+
if (this.pendingScriptStatus !== scriptStatus) {
|
|
30611
|
+
this.pendingScriptStatus = scriptStatus;
|
|
30612
|
+
this.pendingScriptStatusSince = now;
|
|
30613
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
30614
|
+
return false;
|
|
30584
30615
|
}
|
|
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;
|
|
30616
|
+
const elapsed = now - this.pendingScriptStatusSince;
|
|
30617
|
+
if (elapsed < _ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
30618
|
+
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
30619
|
+
return false;
|
|
30612
30620
|
}
|
|
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
|
-
|
|
30621
|
+
return true;
|
|
30622
|
+
}
|
|
30623
|
+
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
30624
|
+
const { scriptStatus } = ctx;
|
|
30625
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
30626
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
30627
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30628
|
+
this.idleTimeout = setTimeout(() => {
|
|
30629
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30630
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30631
|
+
this.finishResponse();
|
|
30632
|
+
}
|
|
30633
|
+
}, this.timeouts.generatingIdle);
|
|
30634
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
30635
|
+
scriptStatus,
|
|
30636
|
+
recentInteractiveActivity,
|
|
30637
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
30638
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
30639
|
+
holdMs: this.getStatusActivityHoldMs(),
|
|
30640
|
+
...buildCliTraceParseSnapshot({
|
|
30641
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
30642
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30643
|
+
responseBuffer: this.responseBuffer,
|
|
30644
|
+
partialResponse: this.responseBuffer,
|
|
30645
|
+
scope: this.currentTurnScope
|
|
30646
|
+
})
|
|
30647
|
+
});
|
|
30648
|
+
this.onStatusChange?.();
|
|
30649
|
+
}
|
|
30650
|
+
applyWaitingApproval(ctx) {
|
|
30651
|
+
const { modal } = ctx;
|
|
30652
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
30653
|
+
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
30654
|
+
if (inCooldown && !modal) {
|
|
30655
|
+
if (this.approvalExitTimeout) {
|
|
30656
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30657
|
+
this.approvalExitTimeout = null;
|
|
30637
30658
|
}
|
|
30638
|
-
|
|
30639
|
-
|
|
30640
|
-
this.setStatus("
|
|
30641
|
-
this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
|
|
30659
|
+
this.activeModal = null;
|
|
30660
|
+
if (this.isWaitingForResponse) {
|
|
30661
|
+
this.setStatus("generating", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
30642
30662
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30643
|
-
this.
|
|
30644
|
-
|
|
30645
|
-
|
|
30663
|
+
this.idleTimeout = setTimeout(() => {
|
|
30664
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30665
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30666
|
+
this.finishResponse();
|
|
30667
|
+
}
|
|
30668
|
+
}, this.timeouts.generatingIdle);
|
|
30669
|
+
} else {
|
|
30670
|
+
this.setStatus("idle", inCooldown ? "approval_cooldown_ignore" : "approval_prompt_gone");
|
|
30646
30671
|
}
|
|
30672
|
+
this.onStatusChange?.();
|
|
30673
|
+
return;
|
|
30647
30674
|
}
|
|
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) {
|
|
30675
|
+
if (!inCooldown) {
|
|
30676
|
+
if (!modal) {
|
|
30677
|
+
LOG2.warn("CLI", `[${this.cliType}] detectStatus reported waiting_approval without parseApproval modal; ignoring non-actionable approval state`);
|
|
30654
30678
|
return;
|
|
30655
30679
|
}
|
|
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");
|
|
30680
|
+
this.isWaitingForResponse = true;
|
|
30681
|
+
this.setStatus("waiting_approval", "script_detect");
|
|
30682
|
+
this.activeModal = modal;
|
|
30669
30683
|
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);
|
|
30684
|
+
this.armApprovalExitTimeout();
|
|
30676
30685
|
this.onStatusChange?.();
|
|
30686
|
+
}
|
|
30687
|
+
}
|
|
30688
|
+
applyGenerating(ctx) {
|
|
30689
|
+
const { screenText, modal, parsedShowsLiveAssistantProgress, prevStatus } = ctx;
|
|
30690
|
+
this.clearIdleFinishCandidate("generating");
|
|
30691
|
+
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
30692
|
+
const noActiveTurn = !this.currentTurnScope;
|
|
30693
|
+
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));
|
|
30694
|
+
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
30677
30695
|
return;
|
|
30678
30696
|
}
|
|
30679
|
-
if (
|
|
30680
|
-
if (
|
|
30681
|
-
|
|
30682
|
-
|
|
30683
|
-
this.approvalExitTimeout = null;
|
|
30684
|
-
}
|
|
30685
|
-
this.activeModal = null;
|
|
30686
|
-
this.lastApprovalResolvedAt = Date.now();
|
|
30697
|
+
if (prevStatus === "waiting_approval") {
|
|
30698
|
+
if (this.approvalExitTimeout) {
|
|
30699
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30700
|
+
this.approvalExitTimeout = null;
|
|
30687
30701
|
}
|
|
30702
|
+
this.activeModal = null;
|
|
30703
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
30704
|
+
}
|
|
30705
|
+
if (!this.isWaitingForResponse) {
|
|
30706
|
+
this.isWaitingForResponse = true;
|
|
30707
|
+
this.responseBuffer = "";
|
|
30708
|
+
}
|
|
30709
|
+
this.setStatus("generating", "script_detect");
|
|
30710
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30711
|
+
this.idleTimeout = setTimeout(() => {
|
|
30688
30712
|
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") {
|
|
30713
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30714
|
+
this.finishResponse();
|
|
30715
|
+
}
|
|
30716
|
+
}, this.timeouts.generatingIdle);
|
|
30717
|
+
this.onStatusChange?.();
|
|
30718
|
+
}
|
|
30719
|
+
applyIdle(ctx, now) {
|
|
30720
|
+
const { screenText, modal, lastParsedAssistant, prevStatus } = ctx;
|
|
30721
|
+
if (prevStatus === "waiting_approval") {
|
|
30722
|
+
if (this.approvalExitTimeout) {
|
|
30723
|
+
clearTimeout(this.approvalExitTimeout);
|
|
30724
|
+
this.approvalExitTimeout = null;
|
|
30725
|
+
}
|
|
30726
|
+
this.activeModal = null;
|
|
30727
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
30728
|
+
}
|
|
30729
|
+
if (!this.isWaitingForResponse) {
|
|
30730
|
+
if (prevStatus !== "idle") {
|
|
30748
30731
|
this.clearIdleFinishCandidate("idle_without_response");
|
|
30749
30732
|
this.setStatus("idle", "script_detect");
|
|
30750
30733
|
this.onStatusChange?.();
|
|
30751
30734
|
}
|
|
30735
|
+
return;
|
|
30736
|
+
}
|
|
30737
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
30738
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
30739
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
30740
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
30741
|
+
const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
|
|
30742
|
+
const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
|
|
30743
|
+
const idleReady = !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleFinishConfirmMs;
|
|
30744
|
+
const candidate = this.idleFinishCandidate;
|
|
30745
|
+
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
|
|
30746
|
+
this.recordTrace("idle_decision", {
|
|
30747
|
+
quietForMs,
|
|
30748
|
+
screenStableMs,
|
|
30749
|
+
hasAssistantTurn,
|
|
30750
|
+
assistantLength,
|
|
30751
|
+
hasModal: !!modal,
|
|
30752
|
+
idleQuietThresholdMs,
|
|
30753
|
+
idleStableThresholdMs: idleFinishConfirmMs,
|
|
30754
|
+
idleReady,
|
|
30755
|
+
idleFinishConfirmMs,
|
|
30756
|
+
idleFinishCandidate: candidate,
|
|
30757
|
+
candidateQuiet,
|
|
30758
|
+
canFinishImmediately: idleReady && candidateQuiet,
|
|
30759
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
30760
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
30761
|
+
...buildCliTraceParseSnapshot({
|
|
30762
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
30763
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
30764
|
+
responseBuffer: this.responseBuffer,
|
|
30765
|
+
partialResponse: this.responseBuffer,
|
|
30766
|
+
scope: this.currentTurnScope
|
|
30767
|
+
})
|
|
30768
|
+
});
|
|
30769
|
+
if (idleReady && candidateQuiet) {
|
|
30770
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
30771
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30772
|
+
this.finishResponse();
|
|
30773
|
+
return;
|
|
30752
30774
|
}
|
|
30775
|
+
if (idleReady) {
|
|
30776
|
+
if (!candidate) {
|
|
30777
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
30778
|
+
return;
|
|
30779
|
+
}
|
|
30780
|
+
} else {
|
|
30781
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
30782
|
+
}
|
|
30783
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
30784
|
+
this.idleTimeout = setTimeout(() => {
|
|
30785
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
30786
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
30787
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
30788
|
+
this.finishResponse();
|
|
30789
|
+
}
|
|
30790
|
+
}, this.timeouts.idleFinish);
|
|
30753
30791
|
}
|
|
30754
30792
|
finishResponse() {
|
|
30755
30793
|
if (this.submitPendingUntil > Date.now()) return;
|
|
@@ -30788,26 +30826,7 @@ var require_dist2 = __commonJS({
|
|
|
30788
30826
|
}, _ProviderCliAdapter.FINISH_RETRY_DELAY_MS);
|
|
30789
30827
|
return;
|
|
30790
30828
|
}
|
|
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
|
-
}
|
|
30829
|
+
this.clearAllTimers();
|
|
30811
30830
|
this.responseBuffer = "";
|
|
30812
30831
|
this.isWaitingForResponse = false;
|
|
30813
30832
|
this.responseSettleIgnoreUntil = 0;
|
|
@@ -30819,18 +30838,12 @@ var require_dist2 = __commonJS({
|
|
|
30819
30838
|
this.setStatus("idle", "response_finished");
|
|
30820
30839
|
this.onStatusChange?.();
|
|
30821
30840
|
}
|
|
30822
|
-
maybeCommitVisibleIdleTranscript(parsed
|
|
30841
|
+
maybeCommitVisibleIdleTranscript(parsed) {
|
|
30823
30842
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
30824
30843
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
30825
30844
|
if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
|
|
30826
30845
|
return false;
|
|
30827
30846
|
}
|
|
30828
|
-
if (options?.requireVisibleAssistantCandidate) {
|
|
30829
|
-
const candidateText = options.screenText || this.terminalScreen.getText() || "";
|
|
30830
|
-
if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
|
|
30831
|
-
return false;
|
|
30832
|
-
}
|
|
30833
|
-
}
|
|
30834
30847
|
const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
30835
30848
|
committedMessages: this.committedMessages,
|
|
30836
30849
|
scope: this.currentTurnScope,
|
|
@@ -30839,33 +30852,8 @@ var require_dist2 = __commonJS({
|
|
|
30839
30852
|
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
30840
30853
|
if (!visibleAssistant) return false;
|
|
30841
30854
|
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
|
-
}
|
|
30855
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
30856
|
+
this.clearAllTimers();
|
|
30869
30857
|
this.syncMessageViews();
|
|
30870
30858
|
this.responseBuffer = "";
|
|
30871
30859
|
this.isWaitingForResponse = false;
|
|
@@ -30895,13 +30883,7 @@ var require_dist2 = __commonJS({
|
|
|
30895
30883
|
scope: this.currentTurnScope,
|
|
30896
30884
|
lastOutputAt: this.lastOutputAt
|
|
30897
30885
|
});
|
|
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
|
-
}
|
|
30886
|
+
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
30905
30887
|
this.syncMessageViews();
|
|
30906
30888
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
30907
30889
|
if (this.currentTurnScope) {
|
|
@@ -30959,7 +30941,7 @@ var require_dist2 = __commonJS({
|
|
|
30959
30941
|
screen: buildCliScreenSnapshot(screenText),
|
|
30960
30942
|
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
30961
30943
|
});
|
|
30962
|
-
return
|
|
30944
|
+
return status;
|
|
30963
30945
|
} catch (e) {
|
|
30964
30946
|
LOG2.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
30965
30947
|
return null;
|
|
@@ -30999,23 +30981,21 @@ var require_dist2 = __commonJS({
|
|
|
30999
30981
|
if (!inApprovalCooldown) {
|
|
31000
30982
|
return parsed;
|
|
31001
30983
|
}
|
|
31002
|
-
const
|
|
31003
|
-
const visibleModal = this.runParseApproval(recentBuffer) || startupModal;
|
|
30984
|
+
const visibleModal = this.runParseApproval(recentBuffer);
|
|
31004
30985
|
if (visibleModal) {
|
|
31005
30986
|
return parsed;
|
|
31006
30987
|
}
|
|
31007
30988
|
const detectedStatus = this.runDetectStatus(recentBuffer);
|
|
31008
|
-
const
|
|
30989
|
+
const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
|
|
31009
30990
|
return {
|
|
31010
30991
|
...parsed,
|
|
31011
|
-
status:
|
|
30992
|
+
status: resolvedStatus,
|
|
31012
30993
|
activeModal: null
|
|
31013
30994
|
};
|
|
31014
30995
|
}
|
|
31015
30996
|
// ─── Public API (CliAdapter) ───────────────────
|
|
31016
30997
|
getStatus() {
|
|
31017
|
-
const
|
|
31018
|
-
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
30998
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
31019
30999
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
31020
31000
|
let effectiveModal = startupModal || this.activeModal;
|
|
31021
31001
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
@@ -31096,8 +31076,7 @@ var require_dist2 = __commonJS({
|
|
|
31096
31076
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
31097
31077
|
}));
|
|
31098
31078
|
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);
|
|
31079
|
+
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
31080
|
if (shouldAdoptParsedIdleReplay) {
|
|
31102
31081
|
this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
31103
31082
|
committedMessages: this.committedMessages,
|
|
@@ -31226,17 +31205,9 @@ var require_dist2 = __commonJS({
|
|
|
31226
31205
|
if (parsed && typeof parsed === "object") {
|
|
31227
31206
|
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
31228
31207
|
}
|
|
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
31208
|
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
|
-
}
|
|
31209
|
+
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
31210
|
+
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
31240
31211
|
}
|
|
31241
31212
|
this.parseErrorMessage = null;
|
|
31242
31213
|
return normalizedParsed;
|
|
@@ -31264,16 +31235,11 @@ var require_dist2 = __commonJS({
|
|
|
31264
31235
|
LOG2.warn("CLI", `[${this.cliType}] resolveAction error: ${e.message}`);
|
|
31265
31236
|
}
|
|
31266
31237
|
}
|
|
31267
|
-
if (!promptText
|
|
31268
|
-
|
|
31269
|
-
|
|
31270
|
-
${data.explanation || ""}
|
|
31271
|
-
|
|
31272
|
-
${data.message || ""}`.trim();
|
|
31273
|
-
}
|
|
31274
|
-
if (promptText) {
|
|
31275
|
-
await this.sendMessage(promptText);
|
|
31238
|
+
if (!promptText) {
|
|
31239
|
+
LOG2.warn("CLI", `[${this.cliType}] resolveAction skipped: provider script did not supply a prompt`);
|
|
31240
|
+
return;
|
|
31276
31241
|
}
|
|
31242
|
+
await this.sendMessage(promptText);
|
|
31277
31243
|
}
|
|
31278
31244
|
async sendMessage(text) {
|
|
31279
31245
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
@@ -31291,9 +31257,7 @@ ${data.message || ""}`.trim();
|
|
|
31291
31257
|
}
|
|
31292
31258
|
if (!this.ready) {
|
|
31293
31259
|
this.resolveStartupState("send_precheck");
|
|
31294
|
-
|
|
31295
|
-
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
31296
|
-
if (hasPrompt && this.currentStatus === "idle") {
|
|
31260
|
+
if (this.runDetectStatus(this.recentOutputBuffer) === "idle" && this.currentStatus === "idle") {
|
|
31297
31261
|
this.ready = true;
|
|
31298
31262
|
this.startupParseGate = false;
|
|
31299
31263
|
LOG2.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
@@ -31399,7 +31363,10 @@ ${data.message || ""}`.trim();
|
|
|
31399
31363
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
31400
31364
|
const screenText2 = this.terminalScreen.getText();
|
|
31401
31365
|
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
31402
|
-
|
|
31366
|
+
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
31367
|
+
if (liveApproval) return;
|
|
31368
|
+
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
31369
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
31403
31370
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
31404
31371
|
LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
31405
31372
|
this.recordTrace("submit_write", {
|
|
@@ -31436,6 +31403,10 @@ ${data.message || ""}`.trim();
|
|
|
31436
31403
|
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
31437
31404
|
const screenText = this.terminalScreen.getText();
|
|
31438
31405
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
31406
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
31407
|
+
if (liveApproval) return;
|
|
31408
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
31409
|
+
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
31439
31410
|
LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
31440
31411
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
31441
31412
|
this.recordTrace("submit_write", {
|
|
@@ -31567,44 +31538,9 @@ ${data.message || ""}`.trim();
|
|
|
31567
31538
|
}
|
|
31568
31539
|
shutdown() {
|
|
31569
31540
|
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
|
-
}
|
|
31541
|
+
this.clearAllTimers();
|
|
31602
31542
|
this.pendingOutputParseBuffer = "";
|
|
31603
31543
|
this.pendingTerminalQueryTail = "";
|
|
31604
|
-
if (this.ptyOutputFlushTimer) {
|
|
31605
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
31606
|
-
this.ptyOutputFlushTimer = null;
|
|
31607
|
-
}
|
|
31608
31544
|
this.ptyOutputBuffer = "";
|
|
31609
31545
|
this.finishRetryCount = 0;
|
|
31610
31546
|
if (this.ptyProcess) {
|
|
@@ -31625,44 +31561,9 @@ ${data.message || ""}`.trim();
|
|
|
31625
31561
|
}
|
|
31626
31562
|
detach() {
|
|
31627
31563
|
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
|
-
}
|
|
31564
|
+
this.clearAllTimers();
|
|
31660
31565
|
this.pendingOutputParseBuffer = "";
|
|
31661
31566
|
this.pendingTerminalQueryTail = "";
|
|
31662
|
-
if (this.ptyOutputFlushTimer) {
|
|
31663
|
-
clearTimeout(this.ptyOutputFlushTimer);
|
|
31664
|
-
this.ptyOutputFlushTimer = null;
|
|
31665
|
-
}
|
|
31666
31567
|
this.ptyOutputBuffer = "";
|
|
31667
31568
|
this.finishRetryCount = 0;
|
|
31668
31569
|
if (this.ptyProcess) {
|
|
@@ -31724,8 +31625,7 @@ ${data.message || ""}`.trim();
|
|
|
31724
31625
|
this.ptyProcess?.write(data);
|
|
31725
31626
|
}
|
|
31726
31627
|
resolveModal(buttonIndex) {
|
|
31727
|
-
|
|
31728
|
-
let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
31628
|
+
let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
31729
31629
|
if (!modal && typeof this.cliScripts?.parseOutput === "function") {
|
|
31730
31630
|
try {
|
|
31731
31631
|
const parsed = this.getScriptParsedStatus();
|
|
@@ -31756,12 +31656,7 @@ ${data.message || ""}`.trim();
|
|
|
31756
31656
|
}
|
|
31757
31657
|
this.setStatus("generating", "approval_resolved");
|
|
31758
31658
|
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) {
|
|
31659
|
+
if (buttonIndex in this.approvalKeys) {
|
|
31765
31660
|
this.ptyProcess.write(this.approvalKeys[buttonIndex]);
|
|
31766
31661
|
} else {
|
|
31767
31662
|
const DOWN = "\x1B[B";
|
|
@@ -31781,7 +31676,7 @@ ${data.message || ""}`.trim();
|
|
|
31781
31676
|
}
|
|
31782
31677
|
getDebugState() {
|
|
31783
31678
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
31784
|
-
const startupModal = this.startupParseGate ? this.
|
|
31679
|
+
const startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
31785
31680
|
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
31786
31681
|
const effectiveReady = this.ready || !!startupModal;
|
|
31787
31682
|
return {
|
|
@@ -39030,25 +38925,23 @@ ${effect.notification.body || ""}`.trim();
|
|
|
39030
38925
|
const effectiveModal = statusModal || surfacedModal;
|
|
39031
38926
|
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
39032
38927
|
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 (
|
|
38928
|
+
if (!effectiveModal) {
|
|
39034
38929
|
return { success: false, error: "Not in approval state" };
|
|
39035
38930
|
}
|
|
39036
|
-
const buttons = effectiveModal
|
|
38931
|
+
const buttons = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
|
|
39037
38932
|
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
39038
|
-
if (buttonIndex < 0) {
|
|
38933
|
+
if (buttonIndex < 0 && button) {
|
|
39039
38934
|
const btnLower = button.toLowerCase();
|
|
39040
38935
|
buttonIndex = buttons.findIndex((b2) => b2.toLowerCase().includes(btnLower));
|
|
39041
38936
|
}
|
|
38937
|
+
if (buttonIndex < 0 && (action === "reject" || action === "deny")) {
|
|
38938
|
+
buttonIndex = buttons.findIndex((b2) => /deny|reject|no/i.test(b2));
|
|
38939
|
+
}
|
|
38940
|
+
if (buttonIndex < 0 && (action === "always" || /always/i.test(button))) {
|
|
38941
|
+
buttonIndex = buttons.findIndex((b2) => /always/i.test(b2));
|
|
38942
|
+
}
|
|
39042
38943
|
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
|
-
}
|
|
38944
|
+
return { success: false, error: "Approval action did not match any visible button" };
|
|
39052
38945
|
}
|
|
39053
38946
|
if (typeof adapter.resolveModal === "function") {
|
|
39054
38947
|
adapter.resolveModal(buttonIndex);
|