@adhdev/daemon-core 0.9.82-rc.110 → 0.9.82-rc.112

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.
@@ -5,6 +5,7 @@ export interface ChatTailSubscriptionCursor {
5
5
  export type SessionChatTailCommandResult = Partial<Omit<ReadChatSyncResult, 'activeModal'>> & {
6
6
  success?: boolean;
7
7
  activeModal?: unknown;
8
+ messagesTail?: unknown;
8
9
  };
9
10
  export interface PrepareSessionChatTailUpdateInput {
10
11
  key: string;
@@ -80,6 +80,8 @@ export declare class ProviderCliAdapter implements CliAdapter {
80
80
  private pendingOutboundQueue;
81
81
  private pendingOutboundFlushTimer;
82
82
  private pendingOutboundFlushInFlight;
83
+ private providerErrorRetryTimer;
84
+ private providerErrorRetryKey;
83
85
  private resizeSuppressUntil;
84
86
  private statusHistory;
85
87
  private cliScripts;
@@ -168,6 +170,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
168
170
  private applyWaitingApproval;
169
171
  private applyGenerating;
170
172
  private applyError;
173
+ private maybeScheduleProviderErrorRetry;
171
174
  private applyIdle;
172
175
  private finishResponse;
173
176
  private maybeCommitVisibleIdleTranscript;
package/dist/index.js CHANGED
@@ -4651,6 +4651,8 @@ var init_provider_cli_adapter = __esm({
4651
4651
  pendingOutboundQueue = [];
4652
4652
  pendingOutboundFlushTimer = null;
4653
4653
  pendingOutboundFlushInFlight = false;
4654
+ providerErrorRetryTimer = null;
4655
+ providerErrorRetryKey = "";
4654
4656
  // Resize redraw suppression
4655
4657
  resizeSuppressUntil = 0;
4656
4658
  // Debug: status transition history
@@ -5257,6 +5259,11 @@ ${lastSnapshot}`;
5257
5259
  clearTimeout(this.ptyOutputFlushTimer);
5258
5260
  this.ptyOutputFlushTimer = null;
5259
5261
  }
5262
+ if (this.providerErrorRetryTimer) {
5263
+ clearTimeout(this.providerErrorRetryTimer);
5264
+ this.providerErrorRetryTimer = null;
5265
+ }
5266
+ this.providerErrorRetryKey = "";
5260
5267
  }
5261
5268
  clearStaleIdleResponseGuard(reason) {
5262
5269
  const blockingModal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
@@ -5406,6 +5413,7 @@ ${lastSnapshot}`;
5406
5413
  return;
5407
5414
  }
5408
5415
  if (status === "error") {
5416
+ if (this.maybeScheduleProviderErrorRetry(ctx, session)) return;
5409
5417
  this.applyError(ctx, session);
5410
5418
  return;
5411
5419
  }
@@ -5592,6 +5600,63 @@ ${lastSnapshot}`;
5592
5600
  });
5593
5601
  this.onStatusChange?.();
5594
5602
  }
5603
+ maybeScheduleProviderErrorRetry(ctx, session) {
5604
+ const retryPrompt = typeof session.retryPrompt === "string" ? String(session.retryPrompt).trim() : "";
5605
+ const retryDelayMs = typeof session.retryDelayMs === "number" ? Number(session.retryDelayMs) : NaN;
5606
+ if (!retryPrompt || !Number.isFinite(retryDelayMs) || retryDelayMs < 0) return false;
5607
+ if (!this.ptyProcess) return false;
5608
+ const retryAttempt = typeof session.retryAttempt === "number" ? Number(session.retryAttempt) : 0;
5609
+ const retryMaxAttempts = typeof session.retryMaxAttempts === "number" ? Number(session.retryMaxAttempts) : 0;
5610
+ const errorReason = typeof session.errorReason === "string" && session.errorReason.trim() ? session.errorReason.trim() : "provider_error";
5611
+ const retryKey = `${errorReason}:${retryAttempt}:${retryPrompt}`;
5612
+ if (this.providerErrorRetryTimer && this.providerErrorRetryKey === retryKey) return true;
5613
+ if (this.providerErrorRetryTimer) clearTimeout(this.providerErrorRetryTimer);
5614
+ this.providerErrorRetryKey = retryKey;
5615
+ this.clearIdleFinishCandidate("provider_error_retry");
5616
+ if (this.idleTimeout) {
5617
+ clearTimeout(this.idleTimeout);
5618
+ this.idleTimeout = null;
5619
+ }
5620
+ if (this.approvalExitTimeout) {
5621
+ clearTimeout(this.approvalExitTimeout);
5622
+ this.approvalExitTimeout = null;
5623
+ }
5624
+ this.providerErrorMessage = typeof session.errorMessage === "string" && session.errorMessage.trim() ? session.errorMessage.trim() : "Provider reported an error";
5625
+ this.providerErrorReason = errorReason;
5626
+ this.activeModal = null;
5627
+ this.responseSettleIgnoreUntil = Date.now() + retryDelayMs + this.timeouts.outputSettle + 400;
5628
+ this.setStatus("generating", "provider_error_retry_scheduled");
5629
+ this.recordTrace("provider_error_retry_scheduled", {
5630
+ retryPrompt,
5631
+ retryDelayMs,
5632
+ retryAttempt,
5633
+ retryMaxAttempts,
5634
+ errorReason,
5635
+ parsedStatus: ctx.parsedStatus || ctx.status
5636
+ });
5637
+ this.onStatusChange?.();
5638
+ this.providerErrorRetryTimer = setTimeout(() => {
5639
+ this.providerErrorRetryTimer = null;
5640
+ this.providerErrorRetryKey = "";
5641
+ if (!this.ptyProcess) return;
5642
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
5643
+ this.submitRetryUsed = false;
5644
+ this.recordTrace("provider_error_retry_write", {
5645
+ retryPrompt,
5646
+ retryAttempt,
5647
+ retryMaxAttempts,
5648
+ errorReason
5649
+ });
5650
+ this.ptyProcess.write(`${retryPrompt}\r`);
5651
+ if (this.settleTimer) clearTimeout(this.settleTimer);
5652
+ this.settleTimer = setTimeout(() => {
5653
+ this.settleTimer = null;
5654
+ this.settledBuffer = this.recentOutputBuffer;
5655
+ this.evaluateSettled();
5656
+ }, this.timeouts.outputSettle + 150);
5657
+ }, retryDelayMs);
5658
+ return true;
5659
+ }
5595
5660
  applyIdle(ctx, now) {
5596
5661
  const { modal, lastParsedAssistant, prevStatus } = ctx;
5597
5662
  if (prevStatus === "waiting_approval") {
@@ -8734,11 +8799,17 @@ function buildSessionReadStateKey(sessionId, providerSessionId) {
8734
8799
  }
8735
8800
  function getSessionSeenAt(state, sessionId, providerSessionId) {
8736
8801
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
8737
- return state.sessionReads?.[providerKey] || state.sessionReads?.[sessionId] || 0;
8802
+ return Math.max(state.sessionReads?.[providerKey] || 0, state.sessionReads?.[sessionId] || 0);
8738
8803
  }
8739
8804
  function getSessionSeenMarker(state, sessionId, providerSessionId) {
8740
8805
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
8741
- return state.sessionReadMarkers?.[providerKey] || state.sessionReadMarkers?.[sessionId] || "";
8806
+ const providerSeenAt = state.sessionReads?.[providerKey] || 0;
8807
+ const sessionSeenAt = state.sessionReads?.[sessionId] || 0;
8808
+ const providerMarker = state.sessionReadMarkers?.[providerKey] || "";
8809
+ const sessionMarker = state.sessionReadMarkers?.[sessionId] || "";
8810
+ if (sessionSeenAt > providerSeenAt && sessionMarker) return sessionMarker;
8811
+ if (providerSeenAt > sessionSeenAt && providerMarker) return providerMarker;
8812
+ return providerMarker || sessionMarker;
8742
8813
  }
8743
8814
  function getSessionNotificationDismissal(state, sessionId, providerSessionId) {
8744
8815
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
@@ -17130,7 +17201,20 @@ async function handleChatHistory(h, args) {
17130
17201
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
17131
17202
  }
17132
17203
  const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
17133
- const result = readProviderChatHistory(agentStr, {
17204
+ const exactNativeHistoryScope = Boolean(
17205
+ typeof args?.targetSessionId === "string" && args.targetSessionId.trim() || typeof args?.historySessionId === "string" && args.historySessionId.trim() || typeof args?.providerSessionId === "string" && args.providerSessionId.trim()
17206
+ );
17207
+ const result = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory) ? readCliProviderNativeHistory(agentStr, {
17208
+ canonicalHistory: provider?.canonicalHistory,
17209
+ historySessionId,
17210
+ workspace,
17211
+ offset: offset || 0,
17212
+ limit: limit || 30,
17213
+ excludeRecentCount,
17214
+ historyBehavior: provider?.historyBehavior,
17215
+ scripts: provider?.scripts,
17216
+ exactSessionScoped: exactNativeHistoryScope
17217
+ }) : readProviderChatHistory(agentStr, {
17134
17218
  canonicalHistory: provider?.canonicalHistory,
17135
17219
  historySessionId,
17136
17220
  workspace,
@@ -17140,6 +17224,26 @@ async function handleChatHistory(h, args) {
17140
17224
  historyBehavior: provider?.historyBehavior,
17141
17225
  scripts: provider?.scripts
17142
17226
  });
17227
+ if (supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory)) {
17228
+ const lookup = result.lookup === "workspace" ? "workspace" : "session";
17229
+ const messages = Array.isArray(result.messages) ? normalizeNativeHistoryMessages(agentStr, result.messages) : [];
17230
+ const historyProviderSessionId = typeof result?.providerSessionId === "string" ? result.providerSessionId : readHistorySessionIdFromMessages(messages) || historySessionId;
17231
+ const safeMapping = hasSafeNativeHistoryMapping({
17232
+ historySessionId: lookup === "workspace" ? void 0 : historySessionId,
17233
+ providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId,
17234
+ workspace,
17235
+ nativeMessages: messages
17236
+ });
17237
+ if (result.source === "provider-native" && messages.length > 0 && !safeMapping) {
17238
+ return {
17239
+ success: true,
17240
+ messages: [],
17241
+ hasMore: false,
17242
+ source: "native-unavailable",
17243
+ agent: agentStr
17244
+ };
17245
+ }
17246
+ }
17143
17247
  return { success: true, ...result, agent: agentStr };
17144
17248
  } catch (e) {
17145
17249
  return { success: false, error: e.message };
@@ -19771,6 +19875,16 @@ function normalizeProviderSessionId(provider, providerSessionId) {
19771
19875
  }
19772
19876
 
19773
19877
  // src/providers/cli-provider-instance.ts
19878
+ function isIdleStatus(value) {
19879
+ const status = typeof value === "string" ? value.trim().toLowerCase() : "";
19880
+ return !status || status === "idle" || status === "ready";
19881
+ }
19882
+ function getMessageTime(message) {
19883
+ if (!message || typeof message !== "object") return 0;
19884
+ const record = message;
19885
+ const value = Number(record.receivedAt ?? record.timestamp ?? 0);
19886
+ return Number.isFinite(value) ? value : 0;
19887
+ }
19774
19888
  var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
19775
19889
  var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
19776
19890
  var IMAGE_MIME_EXTENSIONS = {
@@ -20032,7 +20146,7 @@ var CliProviderInstance = class {
20032
20146
  await this.adapter.spawn();
20033
20147
  await this.enforceFreshSessionLaunchIfNeeded();
20034
20148
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
20035
- if (this.providerSessionId) {
20149
+ if (this.providerSessionId && this.shouldHydrateExistingProviderHistory()) {
20036
20150
  this.restorePersistedHistoryFromCurrentSession();
20037
20151
  }
20038
20152
  if (this.providerSessionId && this.launchMode === "resume") {
@@ -20114,28 +20228,37 @@ var CliProviderInstance = class {
20114
20228
  this.provider,
20115
20229
  typeof adapterStatus?.providerSessionId === "string" ? adapterStatus.providerSessionId : ""
20116
20230
  );
20117
- if (adapterProviderSessionId) {
20118
- this.promoteProviderSessionId(adapterProviderSessionId);
20119
- }
20120
20231
  const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
20121
20232
  const visibleStatus = parseErrorMessage || parsedStatus?.status === "error" ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
20233
+ const runtime = this.adapter.getRuntimeMetadata();
20234
+ this.maybeAppendRuntimeRecoveryMessage(runtime);
20235
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
20122
20236
  const parsedProviderSessionId = normalizeProviderSessionId(
20123
20237
  this.provider,
20124
20238
  typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId : ""
20125
20239
  );
20126
- if (parsedProviderSessionId) {
20240
+ const suppressFreshLaunchStartupReplay = this.shouldSuppressFreshLaunchStartupReplay(
20241
+ parsedMessages,
20242
+ parsedStatus,
20243
+ adapterStatus,
20244
+ parsedProviderSessionId
20245
+ );
20246
+ if (adapterProviderSessionId && !suppressFreshLaunchStartupReplay) {
20247
+ this.promoteProviderSessionId(adapterProviderSessionId);
20248
+ }
20249
+ if (parsedProviderSessionId && !suppressFreshLaunchStartupReplay) {
20127
20250
  this.promoteProviderSessionId(parsedProviderSessionId);
20128
20251
  }
20129
- const runtime = this.adapter.getRuntimeMetadata();
20130
- this.maybeAppendRuntimeRecoveryMessage(runtime);
20252
+ if (suppressFreshLaunchStartupReplay) {
20253
+ parsedMessages = [];
20254
+ }
20131
20255
  const activeChatId = this.providerSessionId || runtime?.runtimeId || this.instanceId;
20132
- let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
20133
20256
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
20134
20257
  if (historyMessageCount !== null) {
20135
20258
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
20136
20259
  }
20137
20260
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
20138
- const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
20261
+ const canonicalBackedHistory = this.shouldHydrateExistingProviderHistory() ? this.syncCanonicalSavedHistoryIfNeeded() : false;
20139
20262
  const statusMessages = canonicalBackedHistory && this.lastPersistedHistoryMessages.length > 0 ? this.lastPersistedHistoryMessages.map((message) => ({
20140
20263
  role: message.role,
20141
20264
  content: message.content,
@@ -20178,7 +20301,10 @@ var CliProviderInstance = class {
20178
20301
  this.lastPersistedHistoryMessages = normalizedMessagesToSave;
20179
20302
  }
20180
20303
  }
20181
- this.applyProviderResponse(parsedStatus, { phase: "immediate" });
20304
+ this.applyProviderResponse(
20305
+ suppressFreshLaunchStartupReplay && parsedStatus && typeof parsedStatus === "object" ? { ...parsedStatus, providerSessionId: void 0 } : parsedStatus,
20306
+ { phase: "immediate" }
20307
+ );
20182
20308
  const surface = resolveProviderStateSurface({
20183
20309
  summaryMetadata: this.summaryMetadata,
20184
20310
  controlValues: this.controlValues
@@ -20930,7 +21056,9 @@ ${effect.notification.body || ""}`.trim();
20930
21056
  this.providerSessionId = nextSessionId;
20931
21057
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
20932
21058
  this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
20933
- this.restorePersistedHistoryFromCurrentSession();
21059
+ if (this.shouldHydrateExistingProviderHistory()) {
21060
+ this.restorePersistedHistoryFromCurrentSession();
21061
+ }
20934
21062
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
20935
21063
  this.onProviderSessionResolved?.({
20936
21064
  instanceId: this.instanceId,
@@ -20942,6 +21070,18 @@ ${effect.notification.body || ""}`.trim();
20942
21070
  });
20943
21071
  LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
20944
21072
  }
21073
+ shouldHydrateExistingProviderHistory() {
21074
+ return this.launchMode === "resume" || this.launchMode === "manual";
21075
+ }
21076
+ shouldSuppressFreshLaunchStartupReplay(parsedMessages, parsedStatus, adapterStatus, parsedProviderSessionId = "") {
21077
+ if (this.launchMode !== "new") return false;
21078
+ if (this.providerSessionId) return false;
21079
+ if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return false;
21080
+ if (!isIdleStatus(adapterStatus?.status) || !isIdleStatus(parsedStatus?.status)) return false;
21081
+ if (parsedProviderSessionId) return true;
21082
+ const newestMessageAt = parsedMessages.reduce((newest, message) => Math.max(newest, getMessageTime(message)), 0);
21083
+ return newestMessageAt === 0;
21084
+ }
20945
21085
  syncCanonicalSavedHistoryIfNeeded() {
20946
21086
  if (!this.providerSessionId) return false;
20947
21087
  const canonicalHistory = this.provider.canonicalHistory;
@@ -31525,7 +31665,8 @@ function prepareSessionChatTailUpdate(input) {
31525
31665
  update: null
31526
31666
  };
31527
31667
  }
31528
- const fullMessages = normalizeChatMessages(Array.isArray(result.messages) ? result.messages : []);
31668
+ const rawMessages = Array.isArray(result.messages) ? result.messages : Array.isArray(result.messagesTail) ? result.messagesTail : [];
31669
+ const fullMessages = normalizeChatMessages(rawMessages);
31529
31670
  const messages = fullMessages;
31530
31671
  const title = typeof result.title === "string" ? result.title : void 0;
31531
31672
  const activeModal = normalizeChatTailActiveModal(result.activeModal);