@adhdev/daemon-core 0.9.82-rc.267 → 0.9.82-rc.269
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +3 -0
- package/dist/cli-adapters/terminal-backends/types.d.ts +9 -0
- package/dist/cli-adapters/terminal-screen.d.ts +2 -0
- package/dist/index.js +234 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +234 -33
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +24 -0
- package/dist/providers/spec/adapter.d.ts +7 -0
- package/dist/providers/spec/fsm-driver.d.ts +4 -0
- package/package.json +2 -2
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +28 -10
- package/src/cli-adapters/terminal-backends/types.ts +9 -0
- package/src/cli-adapters/terminal-screen.ts +5 -0
- package/src/commands/chat-commands.ts +9 -2
- package/src/config/chat-history.ts +134 -0
- package/src/providers/cli-provider-instance.ts +95 -13
- package/src/providers/spec/adapter.ts +10 -0
- package/src/providers/spec/fsm-driver.ts +31 -2
- package/src/providers/types/interactive-prompt.ts +23 -2
package/dist/index.mjs
CHANGED
|
@@ -260,10 +260,10 @@ function readInjected(value) {
|
|
|
260
260
|
}
|
|
261
261
|
function getDaemonBuildInfo() {
|
|
262
262
|
if (cached) return cached;
|
|
263
|
-
const commit = readInjected(true ? "
|
|
264
|
-
const commitShort = readInjected(true ? "
|
|
265
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
266
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
263
|
+
const commit = readInjected(true ? "025d8bef81a66e7b44a5ba5d5a04e063db46db4e" : void 0) ?? "unknown";
|
|
264
|
+
const commitShort = readInjected(true ? "025d8bef" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
265
|
+
const version = readInjected(true ? "0.9.82-rc.269" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
266
|
+
const builtAt = readInjected(true ? "2026-06-14T22:11:38.134Z" : void 0);
|
|
267
267
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
268
268
|
return cached;
|
|
269
269
|
}
|
|
@@ -9496,7 +9496,7 @@ var init_ghostty_vt_backend = __esm({
|
|
|
9496
9496
|
"@adhdev/ghostty-vt-node"
|
|
9497
9497
|
];
|
|
9498
9498
|
cachedBindingError = null;
|
|
9499
|
-
GhosttyVtTerminalBackend = class {
|
|
9499
|
+
GhosttyVtTerminalBackend = class _GhosttyVtTerminalBackend {
|
|
9500
9500
|
kind = "ghostty-vt";
|
|
9501
9501
|
terminal;
|
|
9502
9502
|
rows;
|
|
@@ -9518,17 +9518,30 @@ var init_ghostty_vt_backend = __esm({
|
|
|
9518
9518
|
if (!data || this.disposed) return;
|
|
9519
9519
|
this.terminal.write(data);
|
|
9520
9520
|
}
|
|
9521
|
+
formatLines() {
|
|
9522
|
+
const raw = this.terminal.formatPlainText({ trim: false }) || "";
|
|
9523
|
+
if (!raw) return [];
|
|
9524
|
+
return raw.split("\n").map((row) => row.replace(/\s+$/, ""));
|
|
9525
|
+
}
|
|
9526
|
+
static trimBlankEnds(lines) {
|
|
9527
|
+
let first = 0;
|
|
9528
|
+
let last = lines.length;
|
|
9529
|
+
while (first < last && !lines[first]) first += 1;
|
|
9530
|
+
while (last > first && !lines[last - 1]) last -= 1;
|
|
9531
|
+
return lines.slice(first, last).join("\n");
|
|
9532
|
+
}
|
|
9521
9533
|
getText() {
|
|
9522
9534
|
if (this.disposed) return "";
|
|
9523
|
-
const
|
|
9524
|
-
if (
|
|
9525
|
-
const lines = raw.split("\n").map((row) => row.replace(/\s+$/, ""));
|
|
9535
|
+
const lines = this.formatLines();
|
|
9536
|
+
if (lines.length === 0) return "";
|
|
9526
9537
|
const viewport = lines.length > this.rows ? lines.slice(-this.rows) : lines;
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9538
|
+
return _GhosttyVtTerminalBackend.trimBlankEnds(viewport);
|
|
9539
|
+
}
|
|
9540
|
+
getTextWithScrollback() {
|
|
9541
|
+
if (this.disposed) return "";
|
|
9542
|
+
const lines = this.formatLines();
|
|
9543
|
+
if (lines.length === 0) return "";
|
|
9544
|
+
return _GhosttyVtTerminalBackend.trimBlankEnds(lines);
|
|
9532
9545
|
}
|
|
9533
9546
|
getCursorPosition() {
|
|
9534
9547
|
if (this.disposed) return { col: 0, row: 0 };
|
|
@@ -9581,6 +9594,10 @@ var init_terminal_screen = __esm({
|
|
|
9581
9594
|
getText() {
|
|
9582
9595
|
return this.terminal.getText();
|
|
9583
9596
|
}
|
|
9597
|
+
/** Full buffer including scrollback history (see backend doc). */
|
|
9598
|
+
getTextWithScrollback() {
|
|
9599
|
+
return this.terminal.getTextWithScrollback();
|
|
9600
|
+
}
|
|
9584
9601
|
getCursorPosition() {
|
|
9585
9602
|
return this.terminal.getCursorPosition();
|
|
9586
9603
|
}
|
|
@@ -14716,11 +14733,22 @@ function buildClaudeInteractiveTuiAnswerSteps(prompt, response) {
|
|
|
14716
14733
|
if (response.promptId !== prompt.promptId) throw new Error("Interactive prompt response does not match active prompt");
|
|
14717
14734
|
const steps = [];
|
|
14718
14735
|
for (const question of prompt.questions) {
|
|
14719
|
-
if (question.multiSelect) throw new Error("Claude TUI multi-select prompts are not supported yet");
|
|
14720
14736
|
const answer = response.answers[question.questionId];
|
|
14721
14737
|
if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
|
|
14722
14738
|
const freeformText = answer.freeformText?.trim() ?? "";
|
|
14723
|
-
if (
|
|
14739
|
+
if (question.multiSelect) {
|
|
14740
|
+
const labels = answer.selectedLabels;
|
|
14741
|
+
if (labels.length === 0) {
|
|
14742
|
+
throw new Error(`Expected at least one selected label for ${question.questionId}`);
|
|
14743
|
+
}
|
|
14744
|
+
for (const label of labels) {
|
|
14745
|
+
const selectedIndex = question.options.findIndex((option) => option.label === label);
|
|
14746
|
+
if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${label}`);
|
|
14747
|
+
steps.push(String(selectedIndex + 1));
|
|
14748
|
+
steps.push(" ");
|
|
14749
|
+
}
|
|
14750
|
+
steps.push("\r");
|
|
14751
|
+
} else if (freeformText) {
|
|
14724
14752
|
const typeOptionIndex = question.options.findIndex((o) => /^Type something\.?$/i.test(o.label));
|
|
14725
14753
|
const optionNumber = typeOptionIndex >= 0 ? typeOptionIndex + 1 : question.options.length;
|
|
14726
14754
|
steps.push(String(optionNumber));
|
|
@@ -19897,6 +19925,24 @@ var savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
|
19897
19925
|
var savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
19898
19926
|
var savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
19899
19927
|
var savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
19928
|
+
var BOUNDED_TAIL_CACHE_MAX_ENTRIES = 64;
|
|
19929
|
+
var boundedTailReadCache = /* @__PURE__ */ new Map();
|
|
19930
|
+
function readBoundedTailCache(key, signature) {
|
|
19931
|
+
const cached2 = boundedTailReadCache.get(key);
|
|
19932
|
+
if (!cached2 || cached2.signature !== signature) return null;
|
|
19933
|
+
boundedTailReadCache.delete(key);
|
|
19934
|
+
boundedTailReadCache.set(key, cached2);
|
|
19935
|
+
return cached2.result;
|
|
19936
|
+
}
|
|
19937
|
+
function writeBoundedTailCache(key, signature, result) {
|
|
19938
|
+
boundedTailReadCache.delete(key);
|
|
19939
|
+
boundedTailReadCache.set(key, { signature, result });
|
|
19940
|
+
while (boundedTailReadCache.size > BOUNDED_TAIL_CACHE_MAX_ENTRIES) {
|
|
19941
|
+
const oldest = boundedTailReadCache.keys().next().value;
|
|
19942
|
+
if (oldest === void 0) break;
|
|
19943
|
+
boundedTailReadCache.delete(oldest);
|
|
19944
|
+
}
|
|
19945
|
+
}
|
|
19900
19946
|
function normalizeHistoryComparable(text) {
|
|
19901
19947
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
19902
19948
|
}
|
|
@@ -20781,12 +20827,73 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
20781
20827
|
const sliced = collapsed.slice(startInclusive, endExclusive);
|
|
20782
20828
|
return { messages: sliced, hasMore: startInclusive > 0 };
|
|
20783
20829
|
}
|
|
20830
|
+
var BOUNDED_TAIL_MAX_LIMIT = 5e3;
|
|
20831
|
+
var BOUNDED_TAIL_SLACK = 50;
|
|
20832
|
+
function isBoundedTailRequest(limit, offset, excludeRecentCount) {
|
|
20833
|
+
const numericLimit = Number(limit);
|
|
20834
|
+
if (!Number.isFinite(numericLimit) || numericLimit <= 0) return false;
|
|
20835
|
+
if (numericLimit > BOUNDED_TAIL_MAX_LIMIT) return false;
|
|
20836
|
+
const numericOffset = Number(offset);
|
|
20837
|
+
const numericExclude = Number(excludeRecentCount);
|
|
20838
|
+
if (!Number.isFinite(numericOffset) || !Number.isFinite(numericExclude)) return false;
|
|
20839
|
+
return true;
|
|
20840
|
+
}
|
|
20841
|
+
function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
20842
|
+
const collected = [];
|
|
20843
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20844
|
+
let readAllFiles = true;
|
|
20845
|
+
for (let f = 0; f < files.length; f++) {
|
|
20846
|
+
const filePath = path12.join(dir, files[f]);
|
|
20847
|
+
let content;
|
|
20848
|
+
try {
|
|
20849
|
+
content = fs5.readFileSync(filePath, "utf-8");
|
|
20850
|
+
} catch {
|
|
20851
|
+
continue;
|
|
20852
|
+
}
|
|
20853
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
20854
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
20855
|
+
try {
|
|
20856
|
+
const parsed = JSON.parse(lines[i]);
|
|
20857
|
+
const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
|
|
20858
|
+
if (!sanitizedMessage) continue;
|
|
20859
|
+
const hash = buildHistoryMessageHash(agentType, sanitizedMessage);
|
|
20860
|
+
if (seen.has(hash)) continue;
|
|
20861
|
+
seen.add(hash);
|
|
20862
|
+
collected.push(sanitizedMessage);
|
|
20863
|
+
} catch {
|
|
20864
|
+
}
|
|
20865
|
+
}
|
|
20866
|
+
if (collected.length >= needed && f < files.length - 1) {
|
|
20867
|
+
readAllFiles = false;
|
|
20868
|
+
break;
|
|
20869
|
+
}
|
|
20870
|
+
}
|
|
20871
|
+
collected.reverse();
|
|
20872
|
+
return { records: collected, readAllFiles };
|
|
20873
|
+
}
|
|
20784
20874
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
20785
20875
|
try {
|
|
20786
20876
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
20787
20877
|
const dir = path12.join(HISTORY_DIR, sanitized);
|
|
20788
20878
|
if (!fs5.existsSync(dir)) return { messages: [], hasMore: false };
|
|
20789
20879
|
const files = listHistoryFiles(dir, historySessionId);
|
|
20880
|
+
const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
|
|
20881
|
+
if (bounded) {
|
|
20882
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
20883
|
+
const cacheKey = `${sanitized}\0${historySessionId || ""}\0${offset}\0${limit}\0${excludeRecentCount}\0${historyBehavior?.collapseConsecutiveAssistantTurns ? "1" : "0"}`;
|
|
20884
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
20885
|
+
const cached2 = readBoundedTailCache(cacheKey, signature);
|
|
20886
|
+
if (cached2) return cached2;
|
|
20887
|
+
const numericLimit = Math.max(1, Number(limit));
|
|
20888
|
+
const numericOffset = Math.max(0, Number(offset));
|
|
20889
|
+
const numericExclude = Math.max(0, Number(excludeRecentCount));
|
|
20890
|
+
const needed = numericLimit + numericOffset + numericExclude + Math.max(BOUNDED_TAIL_SLACK, numericLimit);
|
|
20891
|
+
const { records, readAllFiles } = readBoundedTailRecords(agentType, dir, files, needed);
|
|
20892
|
+
const result = pageHistoryRecords(agentType, records, offset, limit, excludeRecentCount, historyBehavior);
|
|
20893
|
+
const boundedResult = readAllFiles ? result : { messages: result.messages, hasMore: true };
|
|
20894
|
+
writeBoundedTailCache(cacheKey, signature, boundedResult);
|
|
20895
|
+
return boundedResult;
|
|
20896
|
+
}
|
|
20790
20897
|
const allMessages = [];
|
|
20791
20898
|
const seen = /* @__PURE__ */ new Set();
|
|
20792
20899
|
for (const file of files) {
|
|
@@ -23996,6 +24103,7 @@ var CHAT_SOURCE_REGISTRY = new ChatSourceRegistry();
|
|
|
23996
24103
|
// src/commands/chat-commands.ts
|
|
23997
24104
|
var RECENT_SEND_WINDOW_MS = 1200;
|
|
23998
24105
|
var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
|
|
24106
|
+
var HOT_TAIL_MIN_LIMIT = 60;
|
|
23999
24107
|
var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
|
|
24000
24108
|
var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli", "antigravity-cli"]);
|
|
24001
24109
|
var warnedLegacyNativeAllowlistHits = /* @__PURE__ */ new Set();
|
|
@@ -24538,7 +24646,7 @@ function readExactRuntimeMirrorMessages(args) {
|
|
|
24538
24646
|
const history = readChatHistory(
|
|
24539
24647
|
args.providerType,
|
|
24540
24648
|
0,
|
|
24541
|
-
Math.max(args.tailLimit || 0,
|
|
24649
|
+
Math.max(args.tailLimit || 0, HOT_TAIL_MIN_LIMIT),
|
|
24542
24650
|
targetSessionId,
|
|
24543
24651
|
0,
|
|
24544
24652
|
args.historyBehavior
|
|
@@ -25431,7 +25539,7 @@ async function handleReadChat(h, args) {
|
|
|
25431
25539
|
const nativeHistoryLimit = Math.max(
|
|
25432
25540
|
normalizeReadChatTailLimit(args) || 0,
|
|
25433
25541
|
returnedMessages.length,
|
|
25434
|
-
|
|
25542
|
+
HOT_TAIL_MIN_LIMIT
|
|
25435
25543
|
);
|
|
25436
25544
|
const nativeHistorySessionId = supportsNative ? resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId) : void 0;
|
|
25437
25545
|
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
@@ -28894,6 +29002,15 @@ var TerminalAdapter = class {
|
|
|
28894
29002
|
snapshot() {
|
|
28895
29003
|
return this.lastScreen || this.computeScreen();
|
|
28896
29004
|
}
|
|
29005
|
+
/**
|
|
29006
|
+
* Full-buffer snapshot including scrollback history. Unlike snapshot()
|
|
29007
|
+
* (visible viewport only), this survives a tall prompt whose top has
|
|
29008
|
+
* scrolled off-screen — used for content-pattern extraction (modal
|
|
29009
|
+
* buttons / approval anchors), NOT for cursor-relative conditions.
|
|
29010
|
+
*/
|
|
29011
|
+
snapshotWithScrollback() {
|
|
29012
|
+
return this.screen.getTextWithScrollback();
|
|
29013
|
+
}
|
|
28897
29014
|
getCursorPosition() {
|
|
28898
29015
|
const pos = this.screen.getCursorPosition();
|
|
28899
29016
|
return { row: pos.row, col: pos.col };
|
|
@@ -29068,6 +29185,18 @@ var FsmDriver = class {
|
|
|
29068
29185
|
getScreen() {
|
|
29069
29186
|
return this.adapter.snapshot();
|
|
29070
29187
|
}
|
|
29188
|
+
/** Scrollback-inclusive screen as line array — used only for modal/button
|
|
29189
|
+
* content extraction so a tall prompt's off-screen anchors stay matchable.
|
|
29190
|
+
* Falls back to the viewport snapshot if scrollback read is unavailable. */
|
|
29191
|
+
scrollbackLines() {
|
|
29192
|
+
let screen = "";
|
|
29193
|
+
try {
|
|
29194
|
+
screen = this.adapter.snapshotWithScrollback();
|
|
29195
|
+
} catch {
|
|
29196
|
+
}
|
|
29197
|
+
if (!screen) screen = this.adapter.snapshot();
|
|
29198
|
+
return screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
29199
|
+
}
|
|
29071
29200
|
getSpecPath() {
|
|
29072
29201
|
return this.opts.specPath;
|
|
29073
29202
|
}
|
|
@@ -29249,9 +29378,12 @@ var FsmDriver = class {
|
|
|
29249
29378
|
const screen = this.adapter.snapshot();
|
|
29250
29379
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
29251
29380
|
const sections = resolveSections(this.spec.sections ?? {}, lines);
|
|
29252
|
-
const
|
|
29381
|
+
const modalLines = state.modal ? this.scrollbackLines() : lines;
|
|
29382
|
+
const modalSections = state.modal ? resolveSections(this.spec.sections ?? {}, modalLines) : sections;
|
|
29383
|
+
const modalFullScreen = modalLines.join("\n");
|
|
29384
|
+
const modal = this.deriveModal(state, modalSections, modalFullScreen);
|
|
29253
29385
|
const controls = this.deriveControls(state.id);
|
|
29254
|
-
const title = modal?.title ?? this.deriveTitle(state,
|
|
29386
|
+
const title = modal?.title ?? this.deriveTitle(state, modalSections, modalFullScreen);
|
|
29255
29387
|
const next = {
|
|
29256
29388
|
// status is derived from the FSM state itself (statusForState), NOT from
|
|
29257
29389
|
// whether a modal was parsed this frame. A modal state whose buttons briefly
|
|
@@ -31122,7 +31254,7 @@ async function waitForCliAdapterReady(adapter, options) {
|
|
|
31122
31254
|
}
|
|
31123
31255
|
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
31124
31256
|
}
|
|
31125
|
-
var CliProviderInstance = class {
|
|
31257
|
+
var CliProviderInstance = class _CliProviderInstance {
|
|
31126
31258
|
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
|
|
31127
31259
|
this.provider = provider;
|
|
31128
31260
|
this.workingDir = workingDir;
|
|
@@ -31142,6 +31274,18 @@ var CliProviderInstance = class {
|
|
|
31142
31274
|
}
|
|
31143
31275
|
type;
|
|
31144
31276
|
category = "cli";
|
|
31277
|
+
/**
|
|
31278
|
+
* Quiet period an approval modal's signature must be stable before
|
|
31279
|
+
* auto-approve sends the approve key. Guards against firing on a prompt
|
|
31280
|
+
* that is still streaming into the PTY (the "resolves too fast" symptom):
|
|
31281
|
+
* while the modal text/buttons are still changing, every frame yields a
|
|
31282
|
+
* new signature and the settle clock restarts. Once the prompt finishes
|
|
31283
|
+
* rendering the signature holds and the key is sent after this window.
|
|
31284
|
+
* Bounded + small so genuine approvals stay timely. The FSM is already
|
|
31285
|
+
* authoritative over the `waiting_approval` state; this only delays the
|
|
31286
|
+
* keystroke until the modal *content* has settled.
|
|
31287
|
+
*/
|
|
31288
|
+
static AUTO_APPROVE_SETTLE_MS = 600;
|
|
31145
31289
|
adapter;
|
|
31146
31290
|
context = null;
|
|
31147
31291
|
events = [];
|
|
@@ -31155,6 +31299,14 @@ var CliProviderInstance = class {
|
|
|
31155
31299
|
autoApproveBusy = false;
|
|
31156
31300
|
autoApproveBusyTimer = null;
|
|
31157
31301
|
lastAutoApprovalSignature = "";
|
|
31302
|
+
// Settle gate: the approval modal's signature + the wall-clock when this
|
|
31303
|
+
// exact signature was first observed. Auto-approve only fires once the
|
|
31304
|
+
// SAME signature has been stable for AUTO_APPROVE_SETTLE_MS, so a prompt
|
|
31305
|
+
// still streaming into the PTY (its buttons/message changing frame to
|
|
31306
|
+
// frame) keeps resetting the timer and is never approved half-rendered.
|
|
31307
|
+
pendingAutoApprovalSignature = "";
|
|
31308
|
+
pendingAutoApprovalSince = 0;
|
|
31309
|
+
autoApproveSettleTimer = null;
|
|
31158
31310
|
controlValues = {};
|
|
31159
31311
|
summaryMetadata = void 0;
|
|
31160
31312
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -31589,6 +31741,14 @@ var CliProviderInstance = class {
|
|
|
31589
31741
|
dispose() {
|
|
31590
31742
|
this.adapter.shutdown();
|
|
31591
31743
|
this.monitor.reset();
|
|
31744
|
+
if (this.autoApproveSettleTimer) {
|
|
31745
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
31746
|
+
this.autoApproveSettleTimer = null;
|
|
31747
|
+
}
|
|
31748
|
+
if (this.autoApproveBusyTimer) {
|
|
31749
|
+
clearTimeout(this.autoApproveBusyTimer);
|
|
31750
|
+
this.autoApproveBusyTimer = null;
|
|
31751
|
+
}
|
|
31592
31752
|
this.appliedEffectKeys.clear();
|
|
31593
31753
|
try {
|
|
31594
31754
|
this.cachedSqliteDb?.close();
|
|
@@ -31939,6 +32099,12 @@ var CliProviderInstance = class {
|
|
|
31939
32099
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
31940
32100
|
if (!autoApproveActive) {
|
|
31941
32101
|
this.lastAutoApprovalSignature = "";
|
|
32102
|
+
this.pendingAutoApprovalSignature = "";
|
|
32103
|
+
this.pendingAutoApprovalSince = 0;
|
|
32104
|
+
if (this.autoApproveSettleTimer) {
|
|
32105
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
32106
|
+
this.autoApproveSettleTimer = null;
|
|
32107
|
+
}
|
|
31942
32108
|
return autoApproveActive;
|
|
31943
32109
|
}
|
|
31944
32110
|
const modal = adapterStatus.activeModal;
|
|
@@ -31957,22 +32123,57 @@ var CliProviderInstance = class {
|
|
|
31957
32123
|
buttons.join("|"),
|
|
31958
32124
|
buttonIndex
|
|
31959
32125
|
].join("::");
|
|
31960
|
-
if (
|
|
31961
|
-
|
|
31962
|
-
|
|
31963
|
-
|
|
31964
|
-
this.
|
|
31965
|
-
|
|
31966
|
-
|
|
31967
|
-
|
|
31968
|
-
|
|
31969
|
-
this.
|
|
31970
|
-
setTimeout(() => {
|
|
31971
|
-
this.
|
|
31972
|
-
|
|
32126
|
+
if (this.autoApproveBusy && signature === this.lastAutoApprovalSignature) {
|
|
32127
|
+
return autoApproveActive;
|
|
32128
|
+
}
|
|
32129
|
+
if (signature !== this.pendingAutoApprovalSignature) {
|
|
32130
|
+
this.pendingAutoApprovalSignature = signature;
|
|
32131
|
+
this.pendingAutoApprovalSince = now;
|
|
32132
|
+
}
|
|
32133
|
+
const settledForMs = now - this.pendingAutoApprovalSince;
|
|
32134
|
+
if (settledForMs < _CliProviderInstance.AUTO_APPROVE_SETTLE_MS) {
|
|
32135
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
32136
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
32137
|
+
this.autoApproveSettleTimer = null;
|
|
32138
|
+
this.recheckAutoApproveSettled();
|
|
32139
|
+
}, _CliProviderInstance.AUTO_APPROVE_SETTLE_MS - settledForMs + 20);
|
|
32140
|
+
return autoApproveActive;
|
|
32141
|
+
}
|
|
32142
|
+
if (this.autoApproveSettleTimer) {
|
|
32143
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
32144
|
+
this.autoApproveSettleTimer = null;
|
|
31973
32145
|
}
|
|
32146
|
+
this.autoApproveBusy = true;
|
|
32147
|
+
this.lastAutoApprovalSignature = signature;
|
|
32148
|
+
this.pendingAutoApprovalSignature = "";
|
|
32149
|
+
this.pendingAutoApprovalSince = 0;
|
|
32150
|
+
if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
|
|
32151
|
+
this.autoApproveBusyTimer = setTimeout(() => {
|
|
32152
|
+
this.autoApproveBusy = false;
|
|
32153
|
+
this.autoApproveBusyTimer = null;
|
|
32154
|
+
this.lastAutoApprovalSignature = "";
|
|
32155
|
+
}, 5e3);
|
|
32156
|
+
this.recordAutoApproval(modal?.message, buttonLabel, now);
|
|
32157
|
+
setTimeout(() => {
|
|
32158
|
+
this.adapter.resolveModal(buttonIndex);
|
|
32159
|
+
}, 0);
|
|
31974
32160
|
return autoApproveActive;
|
|
31975
32161
|
}
|
|
32162
|
+
/**
|
|
32163
|
+
* Re-drive the auto-approve check after the settle quiet window elapses.
|
|
32164
|
+
* The PTY may have gone silent once the approval prompt finished painting,
|
|
32165
|
+
* so no status-change frame is guaranteed to re-enter maybeAutoApproveStatus
|
|
32166
|
+
* — this timer-driven re-check picks up the now-settled modal and fires.
|
|
32167
|
+
* Deliberately lighter than detectStatusTransition(): it only re-evaluates
|
|
32168
|
+
* the approval decision; the next real PTY frame refreshes visible status.
|
|
32169
|
+
*/
|
|
32170
|
+
recheckAutoApproveSettled() {
|
|
32171
|
+
try {
|
|
32172
|
+
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
32173
|
+
this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
32174
|
+
} catch {
|
|
32175
|
+
}
|
|
32176
|
+
}
|
|
31976
32177
|
detectStatusTransition() {
|
|
31977
32178
|
const now = Date.now();
|
|
31978
32179
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|