@adhdev/daemon-standalone 0.9.82-rc.121 → 0.9.82-rc.122

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
@@ -24713,7 +24713,7 @@ Follow these recovery rules:
24713
24713
  if (!REFINE_TERMINAL_EVENTS.has(event.event)) return false;
24714
24714
  const jobId = readRefineJobId(event);
24715
24715
  if (!jobId) return false;
24716
- return getPendingMeshCoordinatorEvents(event.meshId).some(
24716
+ return readPendingMeshCoordinatorEventsFromDisk(event.meshId).some(
24717
24717
  (pending) => pending.event === event.event && readRefineJobId(pending) === jobId
24718
24718
  );
24719
24719
  }
@@ -24738,12 +24738,91 @@ Follow these recovery rules:
24738
24738
  function hasPendingCoordinatorEventDuplicate(event) {
24739
24739
  const fingerprint = buildPendingEventFingerprint(event);
24740
24740
  if (!fingerprint.trim()) return false;
24741
- return getPendingMeshCoordinatorEvents(event.meshId).some((pending) => buildPendingEventFingerprint(pending) === fingerprint);
24741
+ return readPendingMeshCoordinatorEventsFromDisk(event.meshId).some((pending) => buildPendingEventFingerprint(pending) === fingerprint);
24742
24742
  }
24743
24743
  function getPendingEventsPath(meshId) {
24744
24744
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
24745
24745
  return (0, import_path7.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
24746
24746
  }
24747
+ function readPendingMeshCoordinatorEventsFromDisk(meshId) {
24748
+ if (!meshId) return [];
24749
+ const path28 = getPendingEventsPath(meshId);
24750
+ if (!(0, import_fs8.existsSync)(path28)) return [];
24751
+ try {
24752
+ const raw = (0, import_fs8.readFileSync)(path28, "utf-8");
24753
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
24754
+ try {
24755
+ return [JSON.parse(line)];
24756
+ } catch {
24757
+ return [];
24758
+ }
24759
+ });
24760
+ } catch {
24761
+ return [];
24762
+ }
24763
+ }
24764
+ function refineTerminalEventFromLedger(meshId, pending) {
24765
+ const acceptedJobIds = new Set(
24766
+ pending.filter((event) => event.event === "refine:accepted").map((event) => readRefineJobId(event)).filter(Boolean)
24767
+ );
24768
+ if (acceptedJobIds.size === 0) return [];
24769
+ const existingTerminalJobIds = new Set(
24770
+ pending.filter((event) => REFINE_TERMINAL_EVENTS.has(event.event)).map((event) => `${event.event}:${readRefineJobId(event)}`).filter((value) => !value.endsWith(":"))
24771
+ );
24772
+ const backfilled = [];
24773
+ const entries = readLedgerEntries(meshId);
24774
+ for (let i = entries.length - 1; i >= 0; i--) {
24775
+ const entry = entries[i];
24776
+ if (entry.kind !== "task_completed" && entry.kind !== "task_failed") continue;
24777
+ const payload = readRecord2(entry.payload);
24778
+ if (payload?.source !== "refine_mesh_node_async_job") continue;
24779
+ const refineJob = readRecord2(payload.refineJob);
24780
+ const jobId = readNonEmptyString2(refineJob?.jobId);
24781
+ if (!jobId || !acceptedJobIds.has(jobId)) continue;
24782
+ const eventName = entry.kind === "task_completed" ? "refine:completed" : "refine:failed";
24783
+ if (existingTerminalJobIds.has(`${eventName}:${jobId}`)) continue;
24784
+ existingTerminalJobIds.add(`${eventName}:${jobId}`);
24785
+ const result = readRecord2(payload.result);
24786
+ const metadataEvent = {
24787
+ source: "refine_mesh_node_async_job",
24788
+ jobId,
24789
+ interactionId: readNonEmptyString2(refineJob?.interactionId),
24790
+ meshId,
24791
+ nodeId: readNonEmptyString2(refineJob?.nodeId) || entry.nodeId,
24792
+ targetDaemonId: readNonEmptyString2(refineJob?.targetDaemonId),
24793
+ workspace: readNonEmptyString2(refineJob?.workspace),
24794
+ status: eventName === "refine:completed" ? "completed" : "failed",
24795
+ startedAt: readNonEmptyString2(refineJob?.startedAt),
24796
+ completedAt: readNonEmptyString2(refineJob?.completedAt) || entry.timestamp,
24797
+ retryOfJobId: readNonEmptyString2(refineJob?.retryOfJobId) || readNonEmptyString2(payload.retryOfJobId),
24798
+ ...result ? { result } : {}
24799
+ };
24800
+ backfilled.push({
24801
+ event: eventName,
24802
+ meshId,
24803
+ nodeLabel: readNonEmptyString2(refineJob?.nodeId) || entry.nodeId || "refine job",
24804
+ nodeId: readNonEmptyString2(refineJob?.nodeId) || entry.nodeId,
24805
+ workspace: readNonEmptyString2(refineJob?.workspace),
24806
+ metadataEvent,
24807
+ coordinatorMessage: buildMeshSystemMessage({
24808
+ event: eventName,
24809
+ nodeLabel: readNonEmptyString2(refineJob?.nodeId) || entry.nodeId || "refine job",
24810
+ metadataEvent
24811
+ }),
24812
+ queuedAt: Date.now()
24813
+ });
24814
+ }
24815
+ return backfilled.reverse();
24816
+ }
24817
+ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
24818
+ const backfilled = refineTerminalEventFromLedger(meshId, events);
24819
+ if (backfilled.length === 0) return events;
24820
+ const terminalJobIds = new Set(backfilled.map((event) => readRefineJobId(event)).filter(Boolean));
24821
+ return [
24822
+ ...events.filter((event) => !(event.event === "refine:accepted" && terminalJobIds.has(readRefineJobId(event)))),
24823
+ ...backfilled
24824
+ ];
24825
+ }
24747
24826
  function queuePendingMeshCoordinatorEvent(event) {
24748
24827
  try {
24749
24828
  if (hasPendingRefineTerminalEventDuplicate(event)) {
@@ -24766,38 +24845,19 @@ Follow these recovery rules:
24766
24845
  const path28 = getPendingEventsPath(meshId);
24767
24846
  if (!(0, import_fs8.existsSync)(path28)) return [];
24768
24847
  try {
24769
- const raw = (0, import_fs8.readFileSync)(path28, "utf-8");
24848
+ const parsed = readPendingMeshCoordinatorEventsFromDisk(meshId);
24770
24849
  try {
24771
24850
  (0, import_fs8.unlinkSync)(path28);
24772
24851
  } catch {
24773
24852
  }
24774
- return raw.split("\n").filter(Boolean).flatMap((line) => {
24775
- try {
24776
- return [JSON.parse(line)];
24777
- } catch {
24778
- return [];
24779
- }
24780
- });
24853
+ return reconcilePendingMeshCoordinatorEvents(meshId, parsed);
24781
24854
  } catch {
24782
24855
  return [];
24783
24856
  }
24784
24857
  }
24785
24858
  function getPendingMeshCoordinatorEvents(meshId) {
24786
24859
  if (!meshId) return [];
24787
- const path28 = getPendingEventsPath(meshId);
24788
- if (!(0, import_fs8.existsSync)(path28)) return [];
24789
- try {
24790
- const raw = (0, import_fs8.readFileSync)(path28, "utf-8");
24791
- return raw.split("\n").filter(Boolean).flatMap((line) => {
24792
- try {
24793
- return [JSON.parse(line)];
24794
- } catch {
24795
- return [];
24796
- }
24797
- });
24798
- } catch {
24799
- return [];
24800
- }
24860
+ return reconcilePendingMeshCoordinatorEvents(meshId, readPendingMeshCoordinatorEventsFromDisk(meshId));
24801
24861
  }
24802
24862
  function clearPendingMeshCoordinatorEvents(meshId) {
24803
24863
  if (!meshId) return;
@@ -24902,6 +24962,62 @@ Follow these recovery rules:
24902
24962
  recentCompletionFingerprints.set(fingerprint, now);
24903
24963
  return false;
24904
24964
  }
24965
+ function findRecentTerminalLedgerEvidence(args) {
24966
+ if (!args.sessionId && !args.nodeId) return null;
24967
+ const entries = readLedgerEntries(args.meshId);
24968
+ for (let i = entries.length - 1; i >= 0; i--) {
24969
+ const entry = entries[i];
24970
+ if (entry.kind !== "task_completed" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") continue;
24971
+ if (args.sessionId && entry.sessionId === args.sessionId) {
24972
+ return { kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
24973
+ }
24974
+ if (!args.sessionId && args.nodeId && entry.nodeId === args.nodeId) {
24975
+ return { kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
24976
+ }
24977
+ }
24978
+ return null;
24979
+ }
24980
+ function buildLongGeneratingCompletionReconciliation(args) {
24981
+ const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24982
+ const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
24983
+ const providerType = readNonEmptyString2(args.metadataEvent.providerType);
24984
+ const providerSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
24985
+ const workerResult = readWorkerResultMetadata(args.metadataEvent);
24986
+ const completionDiagnostic = readRecord2(args.metadataEvent.completionDiagnostic);
24987
+ const finalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
24988
+ const status = readNonEmptyString2(args.metadataEvent.status).toLowerCase();
24989
+ const explicitCompletionEvidence = Boolean(
24990
+ finalSummary || workerResult || completionDiagnostic?.finalAssistantPresent === true || status === "idle" || status === "ready" || status === "completed"
24991
+ );
24992
+ if (explicitCompletionEvidence) {
24993
+ return {
24994
+ ...args.metadataEvent,
24995
+ targetSessionId: sessionId,
24996
+ providerType,
24997
+ providerSessionId,
24998
+ finalSummary,
24999
+ source: "long_generating_reconciliation",
25000
+ reconciledFromEvent: "monitor:long_generating",
25001
+ timestamp: args.metadataEvent.timestamp ?? Date.now(),
25002
+ completionDiagnostic: {
25003
+ ...completionDiagnostic || {},
25004
+ reconciliationReason: "provider_completion_evidence"
25005
+ }
25006
+ };
25007
+ }
25008
+ const terminal = findRecentTerminalLedgerEvidence({
25009
+ meshId: args.meshId,
25010
+ sessionId: sessionId || void 0,
25011
+ nodeId: nodeId || void 0
25012
+ });
25013
+ if (!terminal) return null;
25014
+ return {
25015
+ ...args.metadataEvent,
25016
+ source: "long_generating_terminal_ledger_suppression",
25017
+ terminalLedgerKind: terminal.kind,
25018
+ terminalLedgerAt: terminal.timestamp
25019
+ };
25020
+ }
24905
25021
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
24906
25022
  const task = claimNextTask(meshId, nodeId, sessionId);
24907
25023
  if (!task) {
@@ -24995,6 +25111,9 @@ Follow these recovery rules:
24995
25111
  function nodeHasActiveAssignment(meshId, nodeId) {
24996
25112
  return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
24997
25113
  }
25114
+ function sessionHasActiveAssignment(meshId, sessionId) {
25115
+ return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedSessionId === sessionId);
25116
+ }
24998
25117
  function liveSessionCountForNode(components, meshId, nodeId) {
24999
25118
  return components.instanceManager.getByCategory("cli").filter((inst) => {
25000
25119
  const state = inst.getState();
@@ -25205,6 +25324,9 @@ Follow these recovery rules:
25205
25324
  function buildMeshSystemMessage(args) {
25206
25325
  const metadata = formatCompletionMetadata(args.metadataEvent);
25207
25326
  if (args.event === "agent:generating_completed") {
25327
+ if (args.metadataEvent.source === "long_generating_reconciliation") {
25328
+ return `[System] ${args.nodeLabel} already has completion evidence${metadata}. The long-generating monitor reconciled the terminal handoff and marked the session complete; wait for the queued completion event/status refresh before doing any manual transcript check.`;
25329
+ }
25208
25330
  return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path; use mesh_read_chat once to review its final progress, but do not poll repeatedly.`;
25209
25331
  }
25210
25332
  if (args.event === "agent:waiting_approval") {
@@ -25242,7 +25364,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25242
25364
  return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
25243
25365
  }
25244
25366
  if (args.event === "monitor:long_generating") {
25245
- return `[System] ${args.nodeLabel} has been generating for a long time${metadata}. Use mesh_read_chat once for a status check, but do not poll repeatedly.`;
25367
+ return `[System] ${args.nodeLabel} is still reported as generating after a long interval${metadata}. Wait for pendingCoordinatorEvents or a completion/status event; if the user explicitly asks for status, make one bounded status check and then wait again.`;
25246
25368
  }
25247
25369
  if (args.event === "refine:accepted") {
25248
25370
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
@@ -25320,12 +25442,54 @@ Next step: ${nextStep}`;
25320
25442
  LOG2.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
25321
25443
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
25322
25444
  }
25445
+ if (args.event === "monitor:long_generating") {
25446
+ const reconciledCompletion = buildLongGeneratingCompletionReconciliation({
25447
+ meshId: args.meshId,
25448
+ nodeId: args.nodeId,
25449
+ nodeLabel: args.nodeLabel,
25450
+ metadataEvent: args.metadataEvent,
25451
+ sourceInstanceId: args.sourceInstanceId
25452
+ });
25453
+ if (reconciledCompletion?.source === "long_generating_reconciliation") {
25454
+ LOG2.info("MeshEvents", `Reconciled long-generating monitor to completion for session ${eventSessionId || "(unknown session)"}`);
25455
+ return injectMeshSystemMessage(components, {
25456
+ ...args,
25457
+ event: "agent:generating_completed",
25458
+ metadataEvent: reconciledCompletion
25459
+ });
25460
+ }
25461
+ if (reconciledCompletion?.source === "long_generating_terminal_ledger_suppression") {
25462
+ LOG2.info("MeshEvents", `Suppressed long-generating monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
25463
+ return {
25464
+ success: true,
25465
+ forwarded: 0,
25466
+ suppressed: true,
25467
+ terminalLedgerEvidence: true,
25468
+ terminalLedgerKind: reconciledCompletion.terminalLedgerKind
25469
+ };
25470
+ }
25471
+ }
25323
25472
  if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
25324
25473
  LOG2.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
25325
25474
  return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
25326
25475
  }
25327
25476
  const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
25328
25477
  if (args.event === "agent:generating_completed" && eventSessionId) {
25478
+ const terminal = findRecentTerminalLedgerEvidence({
25479
+ meshId: args.meshId,
25480
+ sessionId: eventSessionId,
25481
+ nodeId: eventNodeId || void 0
25482
+ });
25483
+ if (terminal?.kind === "task_completed" && !sessionHasActiveAssignment(args.meshId, eventSessionId)) {
25484
+ const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
25485
+ const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
25486
+ const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
25487
+ const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
25488
+ if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "long_generating_reconciliation") {
25489
+ LOG2.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
25490
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
25491
+ }
25492
+ }
25329
25493
  const duplicateCompletion = isDuplicateMeshCompletionEvent({
25330
25494
  meshId: args.meshId,
25331
25495
  event: args.event,
@@ -25602,6 +25766,10 @@ Next step: ${nextStep}`;
25602
25766
  completedAt: readNonEmptyString2(payload.completedAt),
25603
25767
  retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
25604
25768
  ...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
25769
+ ...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
25770
+ ...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
25771
+ ...payload.meshWorkerResult && typeof payload.meshWorkerResult === "object" && !Array.isArray(payload.meshWorkerResult) ? { meshWorkerResult: payload.meshWorkerResult } : {},
25772
+ ...payload.structuredResult && typeof payload.structuredResult === "object" && !Array.isArray(payload.structuredResult) ? { structuredResult: payload.structuredResult } : {},
25605
25773
  ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
25606
25774
  intentional: payload.intentional === true,
25607
25775
  intentionalStop: payload.intentionalStop === true,
@@ -28509,9 +28677,27 @@ ${lastSnapshot}`;
28509
28677
  nextScreenChangeAt
28510
28678
  ), 50);
28511
28679
  }
28512
- async sendMessage(text) {
28680
+ async sendMessage(text, options = {}) {
28681
+ if (options.force === true) {
28682
+ await this.forceSendMessage(text);
28683
+ return;
28684
+ }
28513
28685
  await this.sendMessageNow(text, true);
28514
28686
  }
28687
+ async forceSendMessage(text) {
28688
+ if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
28689
+ const content = String(text || "");
28690
+ if (!content.trim()) return;
28691
+ this.recordTrace("force_send_message", {
28692
+ text: summarizeCliTraceText(content, 500),
28693
+ status: this.currentStatus,
28694
+ isWaitingForResponse: this.isWaitingForResponse,
28695
+ queueLength: this.pendingOutboundQueue.length
28696
+ });
28697
+ LOG2.info("CLI", `[${this.cliType}] force-sending prompt while status=${this.currentStatus}`);
28698
+ await this.writeToPty(content + this.sendKey);
28699
+ this.onStatusChange?.();
28700
+ }
28515
28701
  enqueuePendingOutboundMessage(text, reason) {
28516
28702
  const content = String(text || "");
28517
28703
  const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
@@ -40144,8 +40330,18 @@ ${effect.notification.body || ""}`.trim();
40144
40330
  assertTextOnlyInput(provider, input);
40145
40331
  if (!text) return { success: false, error: "text required for PTY send" };
40146
40332
  await waitOnceForFreshHermesCliStart(adapter, _log);
40147
- await adapter.sendMessage(text);
40148
- return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
40333
+ const forceSend = args?.force === true || args?.forceSend === true;
40334
+ if (forceSend && typeof adapter.forceSendMessage === "function") {
40335
+ await adapter.forceSendMessage(text);
40336
+ } else if (forceSend) {
40337
+ await adapter.sendMessage(text, { force: true });
40338
+ } else {
40339
+ await adapter.sendMessage(text);
40340
+ }
40341
+ return {
40342
+ ..._logSendSuccess(`${transport}-adapter`, adapter.cliType),
40343
+ ...forceSend ? { forceSent: true } : {}
40344
+ };
40149
40345
  } catch (e) {
40150
40346
  return { success: false, error: `${transport} send failed: ${e.message}` };
40151
40347
  }
@@ -42474,6 +42670,7 @@ ${effect.notification.body || ""}`.trim();
42474
42670
  lastApprovalEventAt = 0;
42475
42671
  autoApproveBusy = false;
42476
42672
  autoApproveBusyTimer = null;
42673
+ lastAutoApprovalSignature = "";
42477
42674
  controlValues = {};
42478
42675
  summaryMetadata = void 0;
42479
42676
  appliedEffectKeys = /* @__PURE__ */ new Set();
@@ -42983,15 +43180,26 @@ ${effect.notification.body || ""}`.trim();
42983
43180
  }
42984
43181
  maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
42985
43182
  const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
42986
- if (autoApproveActive && !this.autoApproveBusy) {
43183
+ if (!autoApproveActive) {
43184
+ this.lastAutoApprovalSignature = "";
43185
+ return autoApproveActive;
43186
+ }
43187
+ const modal = adapterStatus.activeModal;
43188
+ const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(modal?.buttons, this.provider);
43189
+ const signature = [
43190
+ typeof modal?.message === "string" ? modal.message.trim() : "",
43191
+ Array.isArray(modal?.buttons) ? modal.buttons.join("|") : "",
43192
+ buttonIndex
43193
+ ].join("::");
43194
+ if (!this.autoApproveBusy || signature !== this.lastAutoApprovalSignature) {
42987
43195
  this.autoApproveBusy = true;
43196
+ this.lastAutoApprovalSignature = signature;
42988
43197
  if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
42989
43198
  this.autoApproveBusyTimer = setTimeout(() => {
42990
43199
  this.autoApproveBusy = false;
42991
43200
  this.autoApproveBusyTimer = null;
43201
+ this.lastAutoApprovalSignature = "";
42992
43202
  }, 2e3);
42993
- const modal = adapterStatus.activeModal;
42994
- const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(modal?.buttons, this.provider);
42995
43203
  this.recordAutoApproval(modal?.message, buttonLabel, now);
42996
43204
  setTimeout(() => {
42997
43205
  this.adapter.resolveModal(buttonIndex);
@@ -43133,7 +43341,26 @@ ${effect.notification.body || ""}`.trim();
43133
43341
  });
43134
43342
  const agentKey = `${this.type}:cli`;
43135
43343
  const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint);
43344
+ const monitorParsedStatus = parsedStatus;
43136
43345
  for (const me of monitorEvents) {
43346
+ if (me.type === "monitor:long_generating" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
43347
+ this.pushEvent({
43348
+ event: "agent:generating_completed",
43349
+ chatTitle,
43350
+ duration: this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : void 0,
43351
+ timestamp: me.timestamp,
43352
+ finalSummary: extractFinalSummaryFromMessages(monitorParsedStatus?.messages),
43353
+ completionDiagnostic: {
43354
+ providerType: this.type,
43355
+ sessionId: this.instanceId,
43356
+ providerSessionId: this.providerSessionId || null,
43357
+ reconciliationReason: "long_generating_monitor_final_summary",
43358
+ finalAssistantPresent: true
43359
+ }
43360
+ });
43361
+ this.generatingStartedAt = 0;
43362
+ continue;
43363
+ }
43137
43364
  this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
43138
43365
  }
43139
43366
  }
@@ -45727,11 +45954,19 @@ Run 'adhdev doctor' for detailed diagnostics.`
45727
45954
  }
45728
45955
  const message = input.textFallback;
45729
45956
  if (!message) throw new Error("message required for send_chat");
45730
- await adapter.sendMessage(message);
45957
+ const forceSend = args?.force === true || args?.forceSend === true;
45958
+ if (forceSend && typeof adapter.forceSendMessage === "function") {
45959
+ await adapter.forceSendMessage(message);
45960
+ } else if (forceSend) {
45961
+ await adapter.sendMessage(message, { force: true });
45962
+ } else {
45963
+ await adapter.sendMessage(message);
45964
+ }
45731
45965
  return {
45732
45966
  success: true,
45733
45967
  status: BUSY_AGENT_STATUSES.has(currentStatus) ? currentStatus : "generating",
45734
- ...BUSY_AGENT_STATUSES.has(currentStatus) ? { queued: true, queuedReason: "agent_runtime_busy" } : {}
45968
+ ...BUSY_AGENT_STATUSES.has(currentStatus) ? { queued: true, queuedReason: "agent_runtime_busy" } : {},
45969
+ ...forceSend ? { forceSent: true, queued: false } : {}
45735
45970
  };
45736
45971
  } else if (action === "clear_history") {
45737
45972
  if (typeof adapter.clearHistory === "function") adapter.clearHistory();