@adhdev/daemon-core 0.9.82-rc.134 → 0.9.82-rc.136

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.
@@ -56,6 +56,7 @@ export interface CliAdapter {
56
56
  clearHistory?(): void;
57
57
  resolveAction?(data: unknown): Promise<void>;
58
58
  resolveModal?(buttonIndex: number): void;
59
+ isApprovalRecentlyResolved?(): boolean;
59
60
  setOnPtyData?(callback: (data: string) => void): void;
60
61
  writeRaw?(data: string): void;
61
62
  resize?(cols: number, rows: number): void;
@@ -237,6 +237,8 @@ export declare class ProviderCliAdapter implements CliAdapter {
237
237
  isReady(): boolean;
238
238
  writeRaw(data: string): Promise<void>;
239
239
  resolveModal(buttonIndex: number): void;
240
+ /** Returns true if an approval was resolved within the adapter's cooldown window. */
241
+ isApprovalRecentlyResolved(): boolean;
240
242
  resize(cols: number, rows: number): void;
241
243
  private getParsedDebugState;
242
244
  getDebugState(): Record<string, any>;
@@ -16,6 +16,8 @@ export declare function buildCliParseInput(options: {
16
16
  recentOutputBuffer: string;
17
17
  terminalScreenText: string;
18
18
  workingDir?: string;
19
+ providerSessionId?: string;
20
+ historySessionId?: string;
19
21
  baseMessages: CliChatMessage[];
20
22
  partialResponse: string;
21
23
  isWaitingForResponse?: boolean;
@@ -126,6 +126,8 @@ export interface CliScriptInput {
126
126
  screenText: string;
127
127
  workspace?: string;
128
128
  workingDir?: string;
129
+ providerSessionId?: string;
130
+ historySessionId?: string;
129
131
  screen: CliScreenSnapshot;
130
132
  bufferScreen: CliScreenSnapshot;
131
133
  recentScreen: CliScreenSnapshot;
package/dist/index.js CHANGED
@@ -4518,6 +4518,8 @@ function buildCliParseInput(options) {
4518
4518
  recentOutputBuffer,
4519
4519
  terminalScreenText,
4520
4520
  workingDir,
4521
+ providerSessionId,
4522
+ historySessionId,
4521
4523
  baseMessages,
4522
4524
  partialResponse,
4523
4525
  isWaitingForResponse,
@@ -4535,6 +4537,8 @@ function buildCliParseInput(options) {
4535
4537
  screenText,
4536
4538
  workspace: workingDir,
4537
4539
  workingDir,
4540
+ providerSessionId,
4541
+ historySessionId,
4538
4542
  screen: buildCliScreenSnapshot(screenText),
4539
4543
  bufferScreen: buildCliScreenSnapshot(buffer),
4540
4544
  recentScreen: buildCliScreenSnapshot(recentBuffer),
@@ -6090,6 +6094,8 @@ ${lastSnapshot}`;
6090
6094
  recentOutputBuffer: this.recentOutputBuffer,
6091
6095
  terminalScreenText: parseScreenText,
6092
6096
  workingDir: this.workingDir,
6097
+ providerSessionId: this.providerSessionId || void 0,
6098
+ historySessionId: this.providerSessionId || void 0,
6093
6099
  baseMessages: [],
6094
6100
  partialResponse: this.responseBuffer,
6095
6101
  isWaitingForResponse: this.isWaitingForResponse,
@@ -6314,6 +6320,8 @@ ${lastSnapshot}`;
6314
6320
  recentOutputBuffer: this.recentOutputBuffer,
6315
6321
  terminalScreenText: this.getParseScreenText(this.terminalScreen.getText()),
6316
6322
  workingDir: this.workingDir,
6323
+ providerSessionId: this.providerSessionId || void 0,
6324
+ historySessionId: this.providerSessionId || void 0,
6317
6325
  baseMessages: [],
6318
6326
  partialResponse: this.responseBuffer,
6319
6327
  isWaitingForResponse: this.isWaitingForResponse,
@@ -6871,6 +6879,10 @@ ${lastSnapshot}`;
6871
6879
  return this.ptyProcess.getMetadata();
6872
6880
  }
6873
6881
  updateRuntimeMeta(meta, replace = false) {
6882
+ const nextProviderSessionId = typeof meta?.providerSessionId === "string" ? meta.providerSessionId.trim() : "";
6883
+ if (nextProviderSessionId) {
6884
+ this.providerSessionId = nextProviderSessionId;
6885
+ }
6874
6886
  if (!this.ptyProcess || typeof this.ptyProcess.updateMeta !== "function") return;
6875
6887
  this.ptyProcess.updateMeta(meta, replace);
6876
6888
  }
@@ -7038,6 +7050,9 @@ ${lastSnapshot}`;
7038
7050
  await this.writeToPty(data);
7039
7051
  }
7040
7052
  resolveModal(buttonIndex) {
7053
+ if (this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown) {
7054
+ return;
7055
+ }
7041
7056
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
7042
7057
  if (!modal && typeof this.cliScripts?.parseSession === "function") {
7043
7058
  try {
@@ -7079,6 +7094,10 @@ ${lastSnapshot}`;
7079
7094
  this.ptyProcess.write(keys);
7080
7095
  }
7081
7096
  }
7097
+ /** Returns true if an approval was resolved within the adapter's cooldown window. */
7098
+ isApprovalRecentlyResolved() {
7099
+ return !!(this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown);
7100
+ }
7082
7101
  resize(cols, rows) {
7083
7102
  if (this.ptyProcess) {
7084
7103
  try {
@@ -15100,6 +15119,19 @@ function formatAutoApprovalMessage(modalMessage, buttonLabel) {
15100
15119
  if (cleanMessage) lines.push(cleanMessage);
15101
15120
  return lines.join("\n");
15102
15121
  }
15122
+ function looksLikeActiveApprovalPromptText(content) {
15123
+ const text = content.trim();
15124
+ if (!text || text.length > 2e3) return false;
15125
+ const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text) || /this command requires approval/i.test(text) || /quick safety check/i.test(text) || /is this a project you trust/i.test(text);
15126
+ const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text) || /^\s*1[.)]\s+yes\b/im.test(text);
15127
+ if (hasApprovalQuestion && hasNumberedChoices) return true;
15128
+ const lastLines = text.split(/\r?\n/).slice(-12).join("\n");
15129
+ const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines) || /yes.*always allow/i.test(lastLines);
15130
+ const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
15131
+ if (hasDontAskAgain && hasNoOption) return true;
15132
+ if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
15133
+ return false;
15134
+ }
15103
15135
 
15104
15136
  // src/providers/ide-provider-instance.ts
15105
15137
  async function withTimeout(promise, timeoutMs, label) {
@@ -19109,6 +19141,10 @@ async function handleResolveAction(h, args) {
19109
19141
  if (buttonIndex < 0) {
19110
19142
  return { success: false, error: "Approval action did not match any visible button" };
19111
19143
  }
19144
+ if (typeof adapter.isApprovalRecentlyResolved === "function" && adapter.isApprovalRecentlyResolved()) {
19145
+ LOG.info("Command", `[resolveAction] CLI PTY \u2192 stale_prompt (already resolved within cooldown)`);
19146
+ return { success: true, stalePrompt: true, buttonIndex, button: buttons[buttonIndex] ?? button };
19147
+ }
19112
19148
  if (typeof adapter.resolveModal === "function") {
19113
19149
  adapter.resolveModal(buttonIndex);
19114
19150
  } else {
@@ -20913,6 +20949,9 @@ var CliProviderInstance = class {
20913
20949
  this.launchMode = options?.launchMode || "new";
20914
20950
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
20915
20951
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
20952
+ if (this.providerSessionId) {
20953
+ this.adapter.updateRuntimeMeta({ providerSessionId: this.providerSessionId });
20954
+ }
20916
20955
  this.monitor = new StatusMonitor();
20917
20956
  this.historyWriter = new ChatHistoryWriter();
20918
20957
  }
@@ -21306,7 +21345,9 @@ var CliProviderInstance = class {
21306
21345
  const lastVisible = visibleMessages[visibleMessages.length - 1];
21307
21346
  const role = typeof lastVisible?.role === "string" ? lastVisible.role.trim().toLowerCase() : "";
21308
21347
  const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
21309
- return role === "assistant" && !!content;
21348
+ if (role !== "assistant" || !content) return false;
21349
+ if (looksLikeActiveApprovalPromptText(content)) return false;
21350
+ return true;
21310
21351
  }
21311
21352
  buildCompletedFinalizationDiagnostic(args) {
21312
21353
  let parsed = null;
@@ -21394,6 +21435,16 @@ var CliProviderInstance = class {
21394
21435
  }
21395
21436
  if (parsed?.activeModal || parsed?.modal) return { reason: "parsed_modal_active", terminal: true };
21396
21437
  if (!this.completionHasFinalAssistantMessage(parsed?.messages)) return { reason: "missing_final_assistant" };
21438
+ try {
21439
+ const screenText = typeof this.adapter.getScreenText === "function" ? String(this.adapter.getScreenText() || "") : "";
21440
+ if (screenText) {
21441
+ const tailLines = screenText.split(/\r?\n/).slice(-16).join("\n");
21442
+ if (looksLikeActiveApprovalPromptText(tailLines)) {
21443
+ return { reason: "screen_shows_approval_prompt", terminal: false };
21444
+ }
21445
+ }
21446
+ } catch {
21447
+ }
21397
21448
  return null;
21398
21449
  }
21399
21450
  scheduleCompletedDebounceFlush(delayMs) {
@@ -23700,7 +23751,9 @@ var DaemonCliManager = class {
23700
23751
  providerSessionId,
23701
23752
  attachExisting
23702
23753
  );
23703
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
23754
+ const adapter = new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
23755
+ if (providerSessionId) adapter.updateRuntimeMeta({ providerSessionId });
23756
+ return adapter;
23704
23757
  }
23705
23758
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
23706
23759
  }