@adhdev/daemon-standalone 0.9.82-rc.92 → 0.9.82-rc.94

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 CHANGED
@@ -26803,6 +26803,9 @@ Next step: ${nextStep}`;
26803
26803
  idleFinishCandidate = null;
26804
26804
  finishRetryTimer = null;
26805
26805
  finishRetryCount = 0;
26806
+ pendingOutboundQueue = [];
26807
+ pendingOutboundFlushTimer = null;
26808
+ pendingOutboundFlushInFlight = false;
26806
26809
  // Resize redraw suppression
26807
26810
  resizeSuppressUntil = 0;
26808
26811
  // Debug: status transition history
@@ -27823,6 +27826,7 @@ ${lastSnapshot}`;
27823
27826
  this.activeModal = null;
27824
27827
  this.setStatus("idle", "response_finished");
27825
27828
  this.onStatusChange?.();
27829
+ this.schedulePendingOutboundFlush();
27826
27830
  }
27827
27831
  maybeCommitVisibleIdleTranscript(session, parsedMessages) {
27828
27832
  const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
@@ -27843,6 +27847,7 @@ ${lastSnapshot}`;
27843
27847
  this.activeModal = null;
27844
27848
  this.setStatus("idle", "script_idle_commit");
27845
27849
  this.onStatusChange?.();
27850
+ this.schedulePendingOutboundFlush();
27846
27851
  this.recordTrace("script_idle_commit", {
27847
27852
  messageCount: parsedMessages.length,
27848
27853
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
@@ -28025,6 +28030,14 @@ ${lastSnapshot}`;
28025
28030
  messages: [],
28026
28031
  workingDir: this.workingDir,
28027
28032
  activeModal: effectiveModal,
28033
+ pendingOutboundCount: this.pendingOutboundQueue.length,
28034
+ pendingOutboundMessages: this.pendingOutboundQueue.map((message) => ({
28035
+ id: message.id,
28036
+ role: message.role,
28037
+ content: message.content,
28038
+ queuedAt: message.queuedAt,
28039
+ source: message.source
28040
+ })),
28028
28041
  errorMessage: this.parseErrorMessage || void 0,
28029
28042
  errorReason: this.parseErrorMessage ? "parse_error" : void 0,
28030
28043
  ...bufferState ? { bufferState } : {}
@@ -28039,7 +28052,7 @@ ${lastSnapshot}`;
28039
28052
  const parseScreenText = this.getParseScreenText(screenText);
28040
28053
  const cached2 = this.parsedStatusCache;
28041
28054
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
28042
- if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === parseScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
28055
+ if (!this.providerOwnsTranscript() && cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === parseScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
28043
28056
  return cached2.result;
28044
28057
  }
28045
28058
  const parsed = this.runParseSession();
@@ -28321,6 +28334,90 @@ ${lastSnapshot}`;
28321
28334
  ), 50);
28322
28335
  }
28323
28336
  async sendMessage(text) {
28337
+ await this.sendMessageNow(text, true);
28338
+ }
28339
+ enqueuePendingOutboundMessage(text, reason) {
28340
+ const content = String(text || "");
28341
+ const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
28342
+ if (duplicate) {
28343
+ this.recordTrace("send_message_queued_duplicate_suppressed", {
28344
+ reason,
28345
+ queueLength: this.pendingOutboundQueue.length,
28346
+ text: summarizeCliTraceText(content, 500)
28347
+ });
28348
+ return;
28349
+ }
28350
+ const queuedAt = Date.now();
28351
+ const message = {
28352
+ id: `${queuedAt}:${this.pendingOutboundQueue.length}:${Math.random().toString(36).slice(2, 10)}`,
28353
+ role: "user",
28354
+ content,
28355
+ queuedAt,
28356
+ source: "sendMessage"
28357
+ };
28358
+ this.pendingOutboundQueue.push(message);
28359
+ this.recordTrace("send_message_queued", {
28360
+ reason,
28361
+ queueLength: this.pendingOutboundQueue.length,
28362
+ queuedAt,
28363
+ text: summarizeCliTraceText(content, 500)
28364
+ });
28365
+ LOG2.info("CLI", `[${this.cliType}] queued outbound message while busy (${reason}); queue=${this.pendingOutboundQueue.length}`);
28366
+ this.onStatusChange?.();
28367
+ }
28368
+ shouldQueuePendingOutboundMessage(parsedStatusBeforeSend = null) {
28369
+ if (this.provider.allowInputDuringGeneration === true) return null;
28370
+ if (this.hasActionableApproval()) return null;
28371
+ const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
28372
+ if (parsedSessionStatus === "idle" && this.parsedStatusHasFinalAssistantMessage(parsedStatusBeforeSend)) return null;
28373
+ if (this.currentStatus === "generating") return "current_status_generating";
28374
+ if (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating") {
28375
+ const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
28376
+ const parsedHasActionableModal = Boolean(
28377
+ parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
28378
+ );
28379
+ const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
28380
+ return terminalLooksIdle ? null : `parsed_status_${parsedSessionStatus}`;
28381
+ }
28382
+ if (this.isWaitingForResponse && this.currentTurnScope) return "active_turn_in_progress";
28383
+ return null;
28384
+ }
28385
+ schedulePendingOutboundFlush(delayMs = 0) {
28386
+ if (this.pendingOutboundFlushTimer) clearTimeout(this.pendingOutboundFlushTimer);
28387
+ this.pendingOutboundFlushTimer = setTimeout(() => {
28388
+ this.pendingOutboundFlushTimer = null;
28389
+ void this.flushPendingOutboundQueue();
28390
+ }, Math.max(0, delayMs));
28391
+ }
28392
+ async flushPendingOutboundQueue() {
28393
+ if (this.pendingOutboundFlushInFlight || this.pendingOutboundQueue.length === 0) return;
28394
+ if (this.currentStatus !== "idle" || this.isWaitingForResponse || this.hasActionableApproval()) return;
28395
+ this.pendingOutboundFlushInFlight = true;
28396
+ try {
28397
+ while (this.pendingOutboundQueue.length > 0) {
28398
+ if (this.currentStatus !== "idle" || this.isWaitingForResponse || this.hasActionableApproval()) break;
28399
+ const next = this.pendingOutboundQueue[0];
28400
+ this.recordTrace("send_message_queue_flush", {
28401
+ id: next.id,
28402
+ queuedAt: next.queuedAt,
28403
+ queueLength: this.pendingOutboundQueue.length,
28404
+ text: summarizeCliTraceText(next.content, 500)
28405
+ });
28406
+ try {
28407
+ await this.sendMessageNow(next.content, false);
28408
+ this.pendingOutboundQueue.shift();
28409
+ this.onStatusChange?.();
28410
+ } catch (error48) {
28411
+ LOG2.warn("CLI", `[${this.cliType}] queued outbound flush failed: ${error48?.message || error48}`);
28412
+ this.schedulePendingOutboundFlush(1e3);
28413
+ break;
28414
+ }
28415
+ }
28416
+ } finally {
28417
+ this.pendingOutboundFlushInFlight = false;
28418
+ }
28419
+ }
28420
+ async sendMessageNow(text, allowQueue) {
28324
28421
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
28325
28422
  const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
28326
28423
  const allowInterventionPrompt = allowInputDuringGeneration && this.isWaitingForResponse && !this.hasActionableApproval();
@@ -28331,6 +28428,18 @@ ${lastSnapshot}`;
28331
28428
  await new Promise((resolve16) => setTimeout(resolve16, 50));
28332
28429
  }
28333
28430
  }
28431
+ const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
28432
+ try {
28433
+ return this.getScriptParsedStatus?.() || null;
28434
+ } catch {
28435
+ return null;
28436
+ }
28437
+ })() : null;
28438
+ const queueReason = this.shouldQueuePendingOutboundMessage(parsedStatusBeforeSend);
28439
+ if (allowQueue && queueReason) {
28440
+ this.enqueuePendingOutboundMessage(text, queueReason);
28441
+ return;
28442
+ }
28334
28443
  if (!allowInterventionPrompt) {
28335
28444
  await this.waitForInteractivePrompt();
28336
28445
  }
@@ -28343,13 +28452,6 @@ ${lastSnapshot}`;
28343
28452
  }
28344
28453
  }
28345
28454
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
28346
- const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
28347
- try {
28348
- return this.getScriptParsedStatus?.() || null;
28349
- } catch {
28350
- return null;
28351
- }
28352
- })() : null;
28353
28455
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
28354
28456
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
28355
28457
  const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
@@ -28358,11 +28460,19 @@ ${lastSnapshot}`;
28358
28460
  );
28359
28461
  const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
28360
28462
  if (!terminalLooksIdle) {
28463
+ if (allowQueue) {
28464
+ this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`);
28465
+ return;
28466
+ }
28361
28467
  throw new Error(`${this.cliName} is still processing the previous prompt`);
28362
28468
  }
28363
28469
  }
28364
28470
  if (this.isWaitingForResponse && !allowInputDuringGeneration) {
28365
28471
  if (!this.clearStaleIdleResponseGuard("send_message_guard") && !this.clearParsedIdleResponseGuard("send_message_parsed_idle_guard", parsedStatusBeforeSend)) {
28472
+ if (allowQueue) {
28473
+ this.enqueuePendingOutboundMessage(text, "waiting_for_response");
28474
+ return;
28475
+ }
28366
28476
  throw new Error(`${this.cliName} is still processing the previous prompt`);
28367
28477
  }
28368
28478
  }
@@ -28597,6 +28707,12 @@ ${lastSnapshot}`;
28597
28707
  this.pendingTerminalQueryTail = "";
28598
28708
  this.ptyOutputChunks = [];
28599
28709
  this.finishRetryCount = 0;
28710
+ if (this.pendingOutboundFlushTimer) {
28711
+ clearTimeout(this.pendingOutboundFlushTimer);
28712
+ this.pendingOutboundFlushTimer = null;
28713
+ }
28714
+ this.pendingOutboundQueue = [];
28715
+ this.pendingOutboundFlushInFlight = false;
28600
28716
  if (this.ptyProcess) {
28601
28717
  this.ptyProcess.write("");
28602
28718
  setTimeout(() => {
@@ -28620,6 +28736,12 @@ ${lastSnapshot}`;
28620
28736
  this.pendingTerminalQueryTail = "";
28621
28737
  this.ptyOutputChunks = [];
28622
28738
  this.finishRetryCount = 0;
28739
+ if (this.pendingOutboundFlushTimer) {
28740
+ clearTimeout(this.pendingOutboundFlushTimer);
28741
+ this.pendingOutboundFlushTimer = null;
28742
+ }
28743
+ this.pendingOutboundQueue = [];
28744
+ this.pendingOutboundFlushInFlight = false;
28623
28745
  if (this.ptyProcess) {
28624
28746
  try {
28625
28747
  if (typeof this.ptyProcess.detach === "function") {
@@ -28659,6 +28781,12 @@ ${lastSnapshot}`;
28659
28781
  this.finishRetryTimer = null;
28660
28782
  }
28661
28783
  this.finishRetryCount = 0;
28784
+ if (this.pendingOutboundFlushTimer) {
28785
+ clearTimeout(this.pendingOutboundFlushTimer);
28786
+ this.pendingOutboundFlushTimer = null;
28787
+ }
28788
+ this.pendingOutboundQueue = [];
28789
+ this.pendingOutboundFlushInFlight = false;
28662
28790
  this.resetTerminalScreen();
28663
28791
  this.ptyProcess?.clearBuffer?.();
28664
28792
  this.onStatusChange?.();
@@ -28785,6 +28913,14 @@ ${lastSnapshot}`;
28785
28913
  rawBufferPreview: this.accumulatedRawBuffer.slice(-1e3),
28786
28914
  sanitizedRawPreview: sanitizeTerminalText(this.accumulatedRawBuffer).slice(-1e3),
28787
28915
  responseBuffer: this.responseBuffer.slice(-1e3),
28916
+ pendingOutboundQueue: this.pendingOutboundQueue.map((message) => ({
28917
+ id: message.id,
28918
+ role: message.role,
28919
+ content: message.content,
28920
+ queuedAt: message.queuedAt,
28921
+ source: message.source
28922
+ })),
28923
+ pendingOutboundCount: this.pendingOutboundQueue.length,
28788
28924
  lastOutputAt: this.lastOutputAt,
28789
28925
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
28790
28926
  lastScreenChangeAt: this.lastScreenChangeAt,
@@ -38018,7 +38154,7 @@ ${effect.notification.body || ""}`.trim();
38018
38154
  var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
38019
38155
  var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
38020
38156
  var CLI_NATIVE_HISTORY_FRESH_MS = 5 * 6e4;
38021
- var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli"]);
38157
+ var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli"]);
38022
38158
  var recentSendByTarget = /* @__PURE__ */ new Map();
38023
38159
  function getCurrentProviderType(h, fallback = "") {
38024
38160
  return h.currentSession?.providerType || h.currentProviderType || fallback;
@@ -44868,18 +45004,6 @@ Run 'adhdev doctor' for detailed diagnostics.`
44868
45004
  } else if (currentStatus === "starting") {
44869
45005
  currentStatus = getEffectiveAgentSendStatus(adapter);
44870
45006
  }
44871
- if (BUSY_AGENT_STATUSES.has(currentStatus)) {
44872
- return {
44873
- success: false,
44874
- code: "agent_runtime_busy",
44875
- reason: "agent_runtime_busy",
44876
- retryable: true,
44877
- retryRecommended: true,
44878
- status: currentStatus,
44879
- targetSessionId: args?.targetSessionId,
44880
- error: `CLI agent '${agentType}' is currently ${currentStatus}; retry after the current turn finishes.`
44881
- };
44882
- }
44883
45007
  const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
44884
45008
  const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
44885
45009
  if (provider?.category === "acp") {
@@ -44890,7 +45014,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
44890
45014
  const message = input.textFallback;
44891
45015
  if (!message) throw new Error("message required for send_chat");
44892
45016
  await adapter.sendMessage(message);
44893
- return { success: true, status: "generating" };
45017
+ return {
45018
+ success: true,
45019
+ status: BUSY_AGENT_STATUSES.has(currentStatus) ? currentStatus : "generating",
45020
+ ...BUSY_AGENT_STATUSES.has(currentStatus) ? { queued: true, queuedReason: "agent_runtime_busy" } : {}
45021
+ };
44894
45022
  } else if (action === "clear_history") {
44895
45023
  if (typeof adapter.clearHistory === "function") adapter.clearHistory();
44896
45024
  return { success: true, cleared: true };