adhdev 0.9.22 → 0.9.24

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
@@ -7356,13 +7356,40 @@ function shouldCollapseReadChatReplayDuplicate(message) {
7356
7356
  const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
7357
7357
  return role === "assistant" || role === "system";
7358
7358
  }
7359
+ function normalizeReadChatReplayText(message) {
7360
+ return flattenContent(message?.content || "").replace(/\s+/g, " ").trim();
7361
+ }
7362
+ function isStableReadChatAssistantAnswer(message) {
7363
+ if (!message) return false;
7364
+ const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
7365
+ const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
7366
+ if (role !== "assistant") return false;
7367
+ if (kind && kind !== "standard") return false;
7368
+ const content = normalizeReadChatReplayText(message);
7369
+ if (content.length < 160) return false;
7370
+ if (/^(bash|shell|terminal) command\b/i.test(content)) return false;
7371
+ return true;
7372
+ }
7373
+ function isReplayedAssistantAnswerAfterStableAnswer(message, stableAnswer) {
7374
+ if (!message || !stableAnswer) return false;
7375
+ const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
7376
+ const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
7377
+ if (role !== "assistant") return false;
7378
+ if (kind && kind !== "standard") return false;
7379
+ const content = normalizeReadChatReplayText(message);
7380
+ const stableContent = normalizeReadChatReplayText(stableAnswer);
7381
+ if (content.length < 80 || stableContent.length < 80) return false;
7382
+ return content === stableContent || content.startsWith(stableContent) || stableContent.startsWith(content);
7383
+ }
7359
7384
  function collapseReplayDuplicatesFromReadChat(messages) {
7360
7385
  const collapsed = [];
7361
7386
  const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
7387
+ let stableAssistantAnswerInCurrentTurn = null;
7362
7388
  for (const message of messages) {
7363
7389
  const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
7364
7390
  if (role === "user") {
7365
7391
  replaySignaturesInCurrentTurn.clear();
7392
+ stableAssistantAnswerInCurrentTurn = null;
7366
7393
  }
7367
7394
  const signature = buildReadChatReplayCollapseSignature(message);
7368
7395
  const previous = collapsed[collapsed.length - 1];
@@ -7370,11 +7397,15 @@ function collapseReplayDuplicatesFromReadChat(messages) {
7370
7397
  if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
7371
7398
  if (previousSignature === signature) continue;
7372
7399
  if (replaySignaturesInCurrentTurn.has(signature)) continue;
7400
+ if (isReplayedAssistantAnswerAfterStableAnswer(message, stableAssistantAnswerInCurrentTurn)) continue;
7373
7401
  }
7374
7402
  collapsed.push(message);
7375
7403
  if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
7376
7404
  replaySignaturesInCurrentTurn.add(signature);
7377
7405
  }
7406
+ if (isStableReadChatAssistantAnswer(message)) {
7407
+ stableAssistantAnswerInCurrentTurn = message;
7408
+ }
7378
7409
  }
7379
7410
  return collapsed;
7380
7411
  }
@@ -13591,8 +13622,10 @@ var init_provider_cli_adapter = __esm({
13591
13622
  if (buttonIndex in this.approvalKeys) {
13592
13623
  this.ptyProcess.write(this.approvalKeys[buttonIndex]);
13593
13624
  } else {
13625
+ const buttonCount = Array.isArray(modal?.buttons) ? modal.buttons.length : 0;
13626
+ const clampedIndex = buttonCount > 0 ? Math.min(Math.max(0, buttonIndex), buttonCount - 1) : Math.max(0, buttonIndex);
13594
13627
  const DOWN = "\x1B[B";
13595
- const keys = DOWN.repeat(Math.max(0, buttonIndex)) + "\r";
13628
+ const keys = DOWN.repeat(clampedIndex) + "\r";
13596
13629
  this.ptyProcess.write(keys);
13597
13630
  }
13598
13631
  }
@@ -13966,6 +13999,12 @@ var init_cli_provider_instance = __esm({
13966
13999
  if (historyMessageCount !== null) {
13967
14000
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
13968
14001
  }
14002
+ const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
14003
+ const isActiveNonIdle = adapterStatus.status !== "idle";
14004
+ const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
14005
+ if (shouldApplyCommittedFloor) {
14006
+ parsedMessages = normalizeChatMessages(committedMessages);
14007
+ }
13969
14008
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
13970
14009
  const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
13971
14010
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
@@ -45377,8 +45416,8 @@ var init_session_host_transport = __esm({
45377
45416
  }
45378
45417
  try {
45379
45418
  await this.client.close();
45380
- } catch {
45381
- if (destroy) throw new Error(`Failed to close session host client: ${this.options.runtimeId}`);
45419
+ } catch (err) {
45420
+ if (destroy) throw err instanceof Error ? err : new Error(`Failed to close session host client: ${this.options.runtimeId}`);
45382
45421
  }
45383
45422
  }
45384
45423
  };
@@ -46934,7 +46973,7 @@ var init_screenshot_sender = __esm({
46934
46973
  });
46935
46974
  let sentAny = false;
46936
46975
  for (const peer of peers.values()) {
46937
- if (peer.state !== "connected" || !peer.dataChannel) continue;
46976
+ if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
46938
46977
  try {
46939
46978
  peer.dataChannel.sendMessage(payload);
46940
46979
  sentAny = true;
@@ -46951,7 +46990,7 @@ var init_screenshot_sender = __esm({
46951
46990
  });
46952
46991
  let sentAny = false;
46953
46992
  for (const peer of peers.values()) {
46954
- if (peer.state !== "connected" || !peer.dataChannel) continue;
46993
+ if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
46955
46994
  try {
46956
46995
  peer.dataChannel.sendMessage(payload);
46957
46996
  sentAny = true;
@@ -46961,7 +47000,7 @@ var init_screenshot_sender = __esm({
46961
47000
  return sentAny;
46962
47001
  }
46963
47002
  sendTopicUpdateToPeer(peer, update) {
46964
- if (!peer?.dataChannel || peer.state !== "connected") return false;
47003
+ if (!peer?.dataChannel || peer.state !== "connected" || !peer.dataChannel.isOpen()) return false;
46965
47004
  try {
46966
47005
  peer.dataChannel.sendMessage(JSON.stringify({
46967
47006
  type: "topic_update",
@@ -46977,7 +47016,7 @@ var init_screenshot_sender = __esm({
46977
47016
  const msg = JSON.stringify({ type: "session_output", sessionId, data });
46978
47017
  let sentAny = false;
46979
47018
  for (const peer of peers.values()) {
46980
- if (peer.state !== "connected" || !peer.dataChannel) continue;
47019
+ if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
46981
47020
  try {
46982
47021
  peer.dataChannel.sendMessage(msg);
46983
47022
  sentAny = true;
@@ -47503,7 +47542,7 @@ ${e?.stack || ""}`);
47503
47542
  }
47504
47543
  get isConnected() {
47505
47544
  for (const peer of this.peers.values()) {
47506
- if (peer.state === "connected" && peer.dataChannel) return true;
47545
+ if (peer.state === "connected" && peer.dataChannel?.isOpen()) return true;
47507
47546
  }
47508
47547
  return false;
47509
47548
  }
@@ -47681,7 +47720,22 @@ ${e?.stack || ""}`);
47681
47720
  if (!update) return;
47682
47721
  this.screenshotSender.sendTopicUpdateToPeer(peer, update);
47683
47722
  } catch (error48) {
47684
- log(`chat_tail flush skipped: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
47723
+ log(`chat_tail flush error: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
47724
+ const errorUpdate = {
47725
+ topic: "session.chat_tail",
47726
+ key: subscription.key,
47727
+ sessionId: subscription.params.targetSessionId,
47728
+ seq: subscription.seq,
47729
+ timestamp: Date.now(),
47730
+ syncMode: "noop",
47731
+ messages: [],
47732
+ status: "",
47733
+ replaceFrom: 0,
47734
+ totalMessages: 0,
47735
+ lastMessageSignature: "",
47736
+ error: error48?.message || "chat_tail build failed"
47737
+ };
47738
+ this.screenshotSender.sendTopicUpdateToPeer(peer, errorUpdate);
47685
47739
  }
47686
47740
  }, { concurrency: 4 });
47687
47741
  }
@@ -55680,7 +55734,7 @@ var init_adhdev_daemon = __esm({
55680
55734
  init_version();
55681
55735
  init_src();
55682
55736
  init_runtime_defaults();
55683
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.22" });
55737
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.24" });
55684
55738
  AdhdevDaemon = class _AdhdevDaemon {
55685
55739
  localHttpServer = null;
55686
55740
  localWss = null;
@@ -55694,6 +55748,8 @@ var init_adhdev_daemon = __esm({
55694
55748
  pendingP2PChatFlush = false;
55695
55749
  pendingP2PChatFlushOnlyActive = true;
55696
55750
  hotP2PChatSessionIds = /* @__PURE__ */ new Set();
55751
+ hotChatSnapshotCache = null;
55752
+ static HOT_CHAT_SNAPSHOT_CACHE_TTL_MS = 1500;
55697
55753
  components = null;
55698
55754
  sessionHostEndpoint = null;
55699
55755
  sessionHostController = null;
@@ -55875,8 +55931,17 @@ var init_adhdev_daemon = __esm({
55875
55931
  profile: "live"
55876
55932
  });
55877
55933
  }
55934
+ invalidateHotChatSnapshotCache() {
55935
+ this.hotChatSnapshotCache = null;
55936
+ }
55878
55937
  getHotChatSessionIdsForP2PFlush() {
55879
- const sessions = this.buildLiveStatusSnapshot().sessions || [];
55938
+ const now = Date.now();
55939
+ const cached2 = this.hotChatSnapshotCache;
55940
+ const sessions = cached2 && now - cached2.builtAt < _AdhdevDaemon.HOT_CHAT_SNAPSHOT_CACHE_TTL_MS ? cached2.sessions : (() => {
55941
+ const built = this.buildLiveStatusSnapshot().sessions || [];
55942
+ this.hotChatSnapshotCache = { sessions: built, builtAt: now };
55943
+ return built;
55944
+ })();
55880
55945
  const hotSessions = classifyHotChatSessionsForSubscriptionFlush(
55881
55946
  sessions,
55882
55947
  this.hotP2PChatSessionIds
@@ -56108,6 +56173,7 @@ ${err?.stack || ""}`);
56108
56173
  }
56109
56174
  }),
56110
56175
  onStatusChange: () => {
56176
+ this.invalidateHotChatSnapshotCache();
56111
56177
  this.statusReporter?.onStatusChange();
56112
56178
  void this.flushP2PChatSubscriptions({ onlyActive: true });
56113
56179
  },
@@ -56137,6 +56203,7 @@ ${err?.stack || ""}`);
56137
56203
  statusInstanceId: instanceId,
56138
56204
  statusVersion: pkgVersion,
56139
56205
  onStatusChange: () => {
56206
+ this.invalidateHotChatSnapshotCache();
56140
56207
  this.statusReporter?.onStatusChange();
56141
56208
  void this.flushP2PChatSubscriptions({ onlyActive: true });
56142
56209
  },