adhdev 0.8.35 → 0.8.36

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
@@ -67,6 +67,7 @@ function normalizeConfig(raw) {
67
67
  const parsed = isPlainObject(raw) ? raw : {};
68
68
  return {
69
69
  serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
70
+ allowServerApiProxy: asBoolean(parsed.allowServerApiProxy, DEFAULT_CONFIG.allowServerApiProxy ?? false),
70
71
  selectedIde: asNullableString(parsed.selectedIde),
71
72
  configuredIdes: asStringArray(parsed.configuredIdes),
72
73
  installedExtensions: asStringArray(parsed.installedExtensions),
@@ -215,6 +216,7 @@ var init_config = __esm({
215
216
  import_crypto = require("crypto");
216
217
  DEFAULT_CONFIG = {
217
218
  serverUrl: "https://api.adhf.dev",
219
+ allowServerApiProxy: false,
218
220
  selectedIde: null,
219
221
  configuredIdes: [],
220
222
  installedExtensions: [],
@@ -4500,19 +4502,20 @@ function normalizeMessageTime(message) {
4500
4502
  }
4501
4503
  return msg;
4502
4504
  }
4503
- function trimMessagesForStatus(messages) {
4505
+ function trimMessagesForStatus(messages, options) {
4506
+ if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];
4504
4507
  if (!Array.isArray(messages) || messages.length === 0) return [];
4505
- const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
4508
+ const recent = messages.slice(-options.messageLimit);
4506
4509
  const kept = [];
4507
4510
  let totalBytes = 0;
4508
4511
  for (let i = recent.length - 1; i >= 0; i -= 1) {
4509
- let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT));
4512
+ let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));
4510
4513
  let size = estimateBytes(normalized);
4511
- if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
4512
- normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT));
4514
+ if (size > options.totalBytesLimit) {
4515
+ normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));
4513
4516
  size = estimateBytes(normalized);
4514
4517
  }
4515
- if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
4518
+ if (kept.length > 0 && totalBytes + size > options.totalBytesLimit) {
4516
4519
  continue;
4517
4520
  }
4518
4521
  kept.push(normalized);
@@ -4542,22 +4545,26 @@ function isManagedStatusWorking(status) {
4542
4545
  function isManagedStatusWaiting(status, opts) {
4543
4546
  return normalizeManagedStatus(status, opts) === "waiting_approval";
4544
4547
  }
4545
- function normalizeActiveChatData(activeChat) {
4548
+ function normalizeActiveChatData(activeChat, options = FULL_STATUS_ACTIVE_CHAT_OPTIONS) {
4546
4549
  if (!activeChat) return activeChat;
4550
+ const resolvedOptions = {
4551
+ ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,
4552
+ ...options
4553
+ };
4547
4554
  return {
4548
4555
  ...activeChat,
4549
4556
  status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
4550
- messages: trimMessagesForStatus(activeChat.messages),
4551
- activeModal: activeChat.activeModal ? {
4557
+ messages: trimMessagesForStatus(activeChat.messages, resolvedOptions),
4558
+ activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {
4552
4559
  message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
4553
4560
  buttons: (activeChat.activeModal.buttons || []).map(
4554
4561
  (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
4555
4562
  )
4556
- } : activeChat.activeModal,
4557
- inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
4563
+ } : null,
4564
+ inputContent: resolvedOptions.includeInputContent && activeChat.inputContent ? truncateString(activeChat.inputContent, 2 * 1024) : void 0
4558
4565
  };
4559
4566
  }
4560
- var WORKING_STATUSES, STATUS_ACTIVE_CHAT_MESSAGE_LIMIT, STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT, STATUS_ACTIVE_CHAT_STRING_LIMIT, STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT, STATUS_INPUT_CONTENT_LIMIT, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT;
4567
+ var WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT;
4561
4568
  var init_normalize = __esm({
4562
4569
  "../../oss/packages/daemon-core/src/status/normalize.ts"() {
4563
4570
  "use strict";
@@ -4569,17 +4576,43 @@ var init_normalize = __esm({
4569
4576
  "thinking",
4570
4577
  "active"
4571
4578
  ]);
4572
- STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
4573
- STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
4574
- STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
4575
- STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
4576
- STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
4579
+ FULL_STATUS_ACTIVE_CHAT_OPTIONS = {
4580
+ includeMessages: true,
4581
+ includeInputContent: true,
4582
+ includeActiveModal: true,
4583
+ messageLimit: 60,
4584
+ totalBytesLimit: 96 * 1024,
4585
+ stringLimit: 4 * 1024,
4586
+ fallbackStringLimit: 1024
4587
+ };
4588
+ LIVE_STATUS_ACTIVE_CHAT_OPTIONS = {
4589
+ includeMessages: false,
4590
+ includeInputContent: false,
4591
+ includeActiveModal: false,
4592
+ messageLimit: 0,
4593
+ totalBytesLimit: 0,
4594
+ stringLimit: 512,
4595
+ fallbackStringLimit: 256
4596
+ };
4577
4597
  STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
4578
4598
  STATUS_MODAL_BUTTON_LIMIT = 120;
4579
4599
  }
4580
4600
  });
4581
4601
 
4582
4602
  // ../../oss/packages/daemon-core/src/status/builders.ts
4603
+ function getActiveChatOptions(profile) {
4604
+ if (profile === "full") return {};
4605
+ return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
4606
+ }
4607
+ function shouldIncludeSessionControls(profile) {
4608
+ return profile !== "live";
4609
+ }
4610
+ function shouldIncludeSessionMetadata(profile) {
4611
+ return profile !== "live";
4612
+ }
4613
+ function shouldIncludeRuntimeMetadata(profile) {
4614
+ return profile !== "live";
4615
+ }
4583
4616
  function findCdpManager(cdpManagers, key) {
4584
4617
  const exact = cdpManagers.get(key);
4585
4618
  if (exact) return exact;
@@ -4645,74 +4678,88 @@ function buildFallbackControls(providerControls, serverModel, serverMode, acpCon
4645
4678
  }
4646
4679
  return controls;
4647
4680
  }
4648
- function buildIdeWorkspaceSession(state, cdpManagers) {
4649
- const activeChat = normalizeActiveChatData(state.activeChat);
4681
+ function buildIdeWorkspaceSession(state, cdpManagers, options) {
4682
+ const profile = options.profile || "full";
4683
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
4684
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
4685
+ const includeSessionControls = shouldIncludeSessionControls(profile);
4650
4686
  const title = activeChat?.title || state.name;
4651
4687
  return {
4652
4688
  id: state.instanceId || state.type,
4653
4689
  parentId: null,
4654
4690
  providerType: state.type,
4655
- providerName: state.name,
4691
+ ...includeSessionMetadata && { providerName: state.name },
4656
4692
  kind: "workspace",
4657
4693
  transport: "cdp-page",
4658
4694
  status: normalizeManagedStatus(activeChat?.status || state.status, {
4659
4695
  activeModal: activeChat?.activeModal || null
4660
4696
  }),
4661
4697
  title,
4662
- workspace: state.workspace || null,
4698
+ ...includeSessionMetadata && { workspace: state.workspace || null },
4663
4699
  activeChat,
4664
- capabilities: IDE_SESSION_CAPABILITIES,
4700
+ ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
4665
4701
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
4666
4702
  currentModel: state.currentModel,
4667
4703
  currentPlan: state.currentPlan,
4668
4704
  currentAutoApprove: state.currentAutoApprove,
4669
- controlValues: state.controlValues,
4670
- providerControls: buildFallbackControls(
4671
- state.providerControls,
4672
- state.currentModel,
4673
- state.currentPlan
4674
- ),
4705
+ ...includeSessionControls && {
4706
+ controlValues: state.controlValues,
4707
+ providerControls: buildFallbackControls(
4708
+ state.providerControls,
4709
+ state.currentModel,
4710
+ state.currentPlan
4711
+ )
4712
+ },
4675
4713
  errorMessage: state.errorMessage,
4676
4714
  errorReason: state.errorReason,
4677
4715
  lastUpdated: state.lastUpdated
4678
4716
  };
4679
4717
  }
4680
- function buildExtensionAgentSession(parent, ext) {
4681
- const activeChat = normalizeActiveChatData(ext.activeChat);
4718
+ function buildExtensionAgentSession(parent, ext, options) {
4719
+ const profile = options.profile || "full";
4720
+ const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
4721
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
4722
+ const includeSessionControls = shouldIncludeSessionControls(profile);
4682
4723
  return {
4683
4724
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
4684
4725
  parentId: parent.instanceId || parent.type,
4685
4726
  providerType: ext.type,
4686
- providerName: ext.name,
4727
+ ...includeSessionMetadata && { providerName: ext.name },
4687
4728
  kind: "agent",
4688
4729
  transport: "cdp-webview",
4689
4730
  status: normalizeManagedStatus(activeChat?.status || ext.status, {
4690
4731
  activeModal: activeChat?.activeModal || null
4691
4732
  }),
4692
4733
  title: activeChat?.title || ext.name,
4693
- workspace: parent.workspace || null,
4734
+ ...includeSessionMetadata && { workspace: parent.workspace || null },
4694
4735
  activeChat,
4695
- capabilities: EXTENSION_SESSION_CAPABILITIES,
4736
+ ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
4696
4737
  currentModel: ext.currentModel,
4697
4738
  currentPlan: ext.currentPlan,
4698
- controlValues: ext.controlValues,
4699
- providerControls: buildFallbackControls(
4700
- ext.providerControls,
4701
- ext.currentModel,
4702
- ext.currentPlan
4703
- ),
4739
+ ...includeSessionControls && {
4740
+ controlValues: ext.controlValues,
4741
+ providerControls: buildFallbackControls(
4742
+ ext.providerControls,
4743
+ ext.currentModel,
4744
+ ext.currentPlan
4745
+ )
4746
+ },
4704
4747
  errorMessage: ext.errorMessage,
4705
4748
  errorReason: ext.errorReason,
4706
4749
  lastUpdated: ext.lastUpdated
4707
4750
  };
4708
4751
  }
4709
- function buildCliSession(state) {
4710
- const activeChat = normalizeActiveChatData(state.activeChat);
4752
+ function buildCliSession(state, options) {
4753
+ const profile = options.profile || "full";
4754
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
4755
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
4756
+ const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
4757
+ const includeSessionControls = shouldIncludeSessionControls(profile);
4711
4758
  return {
4712
4759
  id: state.instanceId,
4713
4760
  parentId: null,
4714
4761
  providerType: state.type,
4715
- providerName: state.name,
4762
+ ...includeSessionMetadata && { providerName: state.name },
4716
4763
  providerSessionId: state.providerSessionId,
4717
4764
  kind: "agent",
4718
4765
  transport: "pty",
@@ -4720,74 +4767,85 @@ function buildCliSession(state) {
4720
4767
  activeModal: activeChat?.activeModal || null
4721
4768
  }),
4722
4769
  title: activeChat?.title || state.name,
4723
- workspace: state.workspace || null,
4724
- runtimeKey: state.runtime?.runtimeKey,
4725
- runtimeDisplayName: state.runtime?.displayName,
4726
- runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
4727
- runtimeWriteOwner: state.runtime?.writeOwner || null,
4728
- runtimeAttachedClients: state.runtime?.attachedClients || [],
4770
+ ...includeSessionMetadata && { workspace: state.workspace || null },
4771
+ ...includeRuntimeMetadata && {
4772
+ runtimeKey: state.runtime?.runtimeKey,
4773
+ runtimeDisplayName: state.runtime?.displayName,
4774
+ runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
4775
+ runtimeWriteOwner: state.runtime?.writeOwner || null,
4776
+ runtimeAttachedClients: state.runtime?.attachedClients || []
4777
+ },
4729
4778
  mode: state.mode,
4730
4779
  resume: state.resume,
4731
4780
  activeChat,
4732
- capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
4733
- controlValues: state.controlValues,
4734
- providerControls: buildFallbackControls(
4735
- state.providerControls
4736
- ),
4781
+ ...includeSessionMetadata && {
4782
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
4783
+ },
4784
+ ...includeSessionControls && {
4785
+ controlValues: state.controlValues,
4786
+ providerControls: buildFallbackControls(
4787
+ state.providerControls
4788
+ )
4789
+ },
4737
4790
  errorMessage: state.errorMessage,
4738
4791
  errorReason: state.errorReason,
4739
4792
  lastUpdated: state.lastUpdated
4740
4793
  };
4741
4794
  }
4742
- function buildAcpSession(state) {
4743
- const activeChat = normalizeActiveChatData(state.activeChat);
4795
+ function buildAcpSession(state, options) {
4796
+ const profile = options.profile || "full";
4797
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
4798
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
4799
+ const includeSessionControls = shouldIncludeSessionControls(profile);
4744
4800
  return {
4745
4801
  id: state.instanceId,
4746
4802
  parentId: null,
4747
4803
  providerType: state.type,
4748
- providerName: state.name,
4804
+ ...includeSessionMetadata && { providerName: state.name },
4749
4805
  kind: "agent",
4750
4806
  transport: "acp",
4751
4807
  status: normalizeManagedStatus(activeChat?.status || state.status, {
4752
4808
  activeModal: activeChat?.activeModal || null
4753
4809
  }),
4754
4810
  title: activeChat?.title || state.name,
4755
- workspace: state.workspace || null,
4811
+ ...includeSessionMetadata && { workspace: state.workspace || null },
4756
4812
  activeChat,
4757
- capabilities: ACP_SESSION_CAPABILITIES,
4813
+ ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
4758
4814
  currentModel: state.currentModel,
4759
4815
  currentPlan: state.currentPlan,
4760
- acpConfigOptions: state.acpConfigOptions,
4761
- acpModes: state.acpModes,
4762
- controlValues: state.controlValues,
4763
- providerControls: buildFallbackControls(
4764
- state.providerControls,
4765
- state.currentModel,
4766
- state.currentPlan,
4767
- state.acpConfigOptions,
4768
- state.acpModes
4769
- ),
4816
+ ...includeSessionControls && {
4817
+ acpConfigOptions: state.acpConfigOptions,
4818
+ acpModes: state.acpModes,
4819
+ controlValues: state.controlValues,
4820
+ providerControls: buildFallbackControls(
4821
+ state.providerControls,
4822
+ state.currentModel,
4823
+ state.currentPlan,
4824
+ state.acpConfigOptions,
4825
+ state.acpModes
4826
+ )
4827
+ },
4770
4828
  errorMessage: state.errorMessage,
4771
4829
  errorReason: state.errorReason,
4772
4830
  lastUpdated: state.lastUpdated
4773
4831
  };
4774
4832
  }
4775
- function buildSessionEntries(allStates, cdpManagers) {
4833
+ function buildSessionEntries(allStates, cdpManagers, options = {}) {
4776
4834
  const sessions = [];
4777
4835
  const ideStates = allStates.filter((s) => s.category === "ide");
4778
4836
  const cliStates = allStates.filter((s) => s.category === "cli");
4779
4837
  const acpStates = allStates.filter((s) => s.category === "acp");
4780
4838
  for (const state of ideStates) {
4781
- sessions.push(buildIdeWorkspaceSession(state, cdpManagers));
4839
+ sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
4782
4840
  for (const ext of state.extensions) {
4783
- sessions.push(buildExtensionAgentSession(state, ext));
4841
+ sessions.push(buildExtensionAgentSession(state, ext, options));
4784
4842
  }
4785
4843
  }
4786
4844
  for (const state of cliStates) {
4787
- sessions.push(buildCliSession(state));
4845
+ sessions.push(buildCliSession(state, options));
4788
4846
  }
4789
4847
  for (const state of acpStates) {
4790
- sessions.push(buildAcpSession(state));
4848
+ sessions.push(buildAcpSession(state, options));
4791
4849
  }
4792
4850
  const extensionParentIds = new Set(
4793
4851
  sessions.filter((session) => session.transport === "cdp-webview" && !!session.parentId).map((session) => session.parentId)
@@ -4899,7 +4957,31 @@ var init_reconcile = __esm({
4899
4957
  }
4900
4958
  });
4901
4959
 
4960
+ // ../../oss/packages/daemon-core/src/providers/contracts.ts
4961
+ function flattenContent(content) {
4962
+ if (typeof content === "string") return content;
4963
+ return content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
4964
+ }
4965
+ var init_contracts = __esm({
4966
+ "../../oss/packages/daemon-core/src/providers/contracts.ts"() {
4967
+ "use strict";
4968
+ }
4969
+ });
4970
+
4902
4971
  // ../../oss/packages/daemon-core/src/commands/chat-commands.ts
4972
+ function hashSignatureParts(parts) {
4973
+ let hash2 = 2166136261;
4974
+ for (const part of parts) {
4975
+ const text = String(part || "");
4976
+ for (let i = 0; i < text.length; i += 1) {
4977
+ hash2 ^= text.charCodeAt(i);
4978
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
4979
+ }
4980
+ hash2 ^= 255;
4981
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
4982
+ }
4983
+ return hash2.toString(16).padStart(8, "0");
4984
+ }
4903
4985
  function getCurrentProviderType(h, fallback = "") {
4904
4986
  return h.currentSession?.providerType || h.currentProviderType || fallback;
4905
4987
  }
@@ -4973,6 +5055,134 @@ function parseMaybeJson(value) {
4973
5055
  return value;
4974
5056
  }
4975
5057
  }
5058
+ function getChatMessageSignature(message) {
5059
+ if (!message) return "";
5060
+ let content = "";
5061
+ try {
5062
+ content = JSON.stringify(message.content ?? "");
5063
+ } catch {
5064
+ content = String(message.content ?? "");
5065
+ }
5066
+ return hashSignatureParts([
5067
+ String(message.id || ""),
5068
+ String(message.index ?? ""),
5069
+ String(message.role || ""),
5070
+ String(message.receivedAt ?? message.timestamp ?? ""),
5071
+ content
5072
+ ]);
5073
+ }
5074
+ function normalizeReadChatCursor(args) {
5075
+ const knownMessageCount = Math.max(0, Number(args?.knownMessageCount || 0));
5076
+ const lastMessageSignature = typeof args?.lastMessageSignature === "string" ? args.lastMessageSignature : "";
5077
+ const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
5078
+ return { knownMessageCount, lastMessageSignature, tailLimit };
5079
+ }
5080
+ function normalizeReadChatMessages(payload) {
5081
+ const messages = Array.isArray(payload.messages) ? payload.messages : [];
5082
+ return messages;
5083
+ }
5084
+ function deriveHistoryDedupKey(message) {
5085
+ const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
5086
+ if (unitKey) return `read_chat:${unitKey}`;
5087
+ const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
5088
+ if (!turnKey) return void 0;
5089
+ let content = "";
5090
+ try {
5091
+ content = JSON.stringify(message.content ?? "");
5092
+ } catch {
5093
+ content = String(message.content ?? "");
5094
+ }
5095
+ return `read_chat:${turnKey}:${String(message.role || "").toLowerCase()}:${content}`;
5096
+ }
5097
+ function toHistoryPersistedMessages(messages) {
5098
+ return messages.map((message) => ({
5099
+ role: message.role,
5100
+ content: flattenContent(message.content),
5101
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : void 0,
5102
+ kind: typeof message.kind === "string" ? message.kind : void 0,
5103
+ senderName: typeof message.senderName === "string" ? message.senderName : void 0,
5104
+ historyDedupKey: deriveHistoryDedupKey(message)
5105
+ }));
5106
+ }
5107
+ function computeReadChatSync(messages, cursor) {
5108
+ const totalMessages = messages.length;
5109
+ const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
5110
+ const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
5111
+ if (!knownMessageCount || !knownSignature) {
5112
+ return {
5113
+ syncMode: "full",
5114
+ replaceFrom: 0,
5115
+ messages,
5116
+ totalMessages,
5117
+ lastMessageSignature
5118
+ };
5119
+ }
5120
+ if (knownMessageCount > totalMessages) {
5121
+ return {
5122
+ syncMode: "full",
5123
+ replaceFrom: 0,
5124
+ messages,
5125
+ totalMessages,
5126
+ lastMessageSignature
5127
+ };
5128
+ }
5129
+ if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
5130
+ return {
5131
+ syncMode: "noop",
5132
+ replaceFrom: totalMessages,
5133
+ messages: [],
5134
+ totalMessages,
5135
+ lastMessageSignature
5136
+ };
5137
+ }
5138
+ if (knownMessageCount < totalMessages) {
5139
+ const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
5140
+ if (anchorSignature === knownSignature) {
5141
+ return {
5142
+ syncMode: "append",
5143
+ replaceFrom: knownMessageCount,
5144
+ messages: messages.slice(knownMessageCount),
5145
+ totalMessages,
5146
+ lastMessageSignature
5147
+ };
5148
+ }
5149
+ }
5150
+ const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
5151
+ return {
5152
+ syncMode: replaceFrom === 0 ? "full" : "replace_tail",
5153
+ replaceFrom,
5154
+ messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
5155
+ totalMessages,
5156
+ lastMessageSignature
5157
+ };
5158
+ }
5159
+ function buildReadChatCommandResult(payload, args) {
5160
+ const messages = normalizeReadChatMessages(payload);
5161
+ const cursor = normalizeReadChatCursor(args);
5162
+ if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
5163
+ const tailMessages = messages.slice(-cursor.tailLimit);
5164
+ const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
5165
+ return {
5166
+ success: true,
5167
+ ...payload,
5168
+ messages: tailMessages,
5169
+ syncMode: "full",
5170
+ replaceFrom: 0,
5171
+ totalMessages: messages.length,
5172
+ lastMessageSignature
5173
+ };
5174
+ }
5175
+ const sync = computeReadChatSync(messages, cursor);
5176
+ return {
5177
+ success: true,
5178
+ ...payload,
5179
+ messages: sync.messages,
5180
+ syncMode: sync.syncMode,
5181
+ replaceFrom: sync.replaceFrom,
5182
+ totalMessages: sync.totalMessages,
5183
+ lastMessageSignature: sync.lastMessageSignature
5184
+ };
5185
+ }
4976
5186
  function didProviderConfirmSend(result) {
4977
5187
  const parsed = parseMaybeJson(result);
4978
5188
  if (parsed === true) return true;
@@ -5046,12 +5256,11 @@ async function handleReadChat(h, args) {
5046
5256
  _log(`${transport} adapter: ${adapter.cliType}`);
5047
5257
  const status = adapter.getStatus();
5048
5258
  if (status) {
5049
- return {
5050
- success: true,
5259
+ return buildReadChatCommandResult({
5051
5260
  messages: status.messages || [],
5052
5261
  status: status.status,
5053
5262
  activeModal: status.activeModal
5054
- };
5263
+ }, args);
5055
5264
  }
5056
5265
  }
5057
5266
  return { success: false, error: `${transport} adapter not found` };
@@ -5071,12 +5280,12 @@ async function handleReadChat(h, args) {
5071
5280
  _log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
5072
5281
  h.historyWriter.appendNewMessages(
5073
5282
  provider?.type || "unknown_extension",
5074
- parsed.messages || [],
5283
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
5075
5284
  parsed.title,
5076
5285
  args?.targetSessionId,
5077
5286
  historySessionId
5078
5287
  );
5079
- return { success: true, ...parsed };
5288
+ return buildReadChatCommandResult(parsed, args);
5080
5289
  }
5081
5290
  }
5082
5291
  } catch (e) {
@@ -5088,21 +5297,25 @@ async function handleReadChat(h, args) {
5088
5297
  if (cdp2 && parentSessionId) {
5089
5298
  const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
5090
5299
  if (stream?.agentType !== provider?.type) {
5091
- return { success: true, messages: [], status: "idle" };
5300
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
5092
5301
  }
5093
5302
  if (stream) {
5094
5303
  h.historyWriter.appendNewMessages(
5095
5304
  stream.agentType,
5096
- stream.messages || [],
5305
+ toHistoryPersistedMessages(stream.messages || []),
5097
5306
  void 0,
5098
5307
  args?.targetSessionId,
5099
5308
  historySessionId
5100
5309
  );
5101
- return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
5310
+ return buildReadChatCommandResult({
5311
+ messages: stream.messages || [],
5312
+ status: stream.status,
5313
+ agentType: stream.agentType
5314
+ }, args);
5102
5315
  }
5103
5316
  }
5104
5317
  }
5105
- return { success: true, messages: [], status: "idle" };
5318
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
5106
5319
  }
5107
5320
  const cdp = h.getCdp();
5108
5321
  if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
@@ -5124,18 +5337,18 @@ async function handleReadChat(h, args) {
5124
5337
  _log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
5125
5338
  h.historyWriter.appendNewMessages(
5126
5339
  provider?.type || getCurrentProviderType(h, "unknown_webview"),
5127
- parsed.messages || [],
5340
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
5128
5341
  parsed.title,
5129
5342
  args?.targetSessionId,
5130
5343
  historySessionId
5131
5344
  );
5132
- return { success: true, ...parsed };
5345
+ return buildReadChatCommandResult(parsed, args);
5133
5346
  }
5134
5347
  }
5135
5348
  } catch (e) {
5136
5349
  _log(`Webview readChat error: ${e.message}`);
5137
5350
  }
5138
- return { success: true, messages: [], status: "idle" };
5351
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
5139
5352
  }
5140
5353
  const script = h.getProviderScript("readChat") || h.getProviderScript("read_chat");
5141
5354
  if (script) {
@@ -5152,18 +5365,18 @@ async function handleReadChat(h, args) {
5152
5365
  _log(`OK: ${parsed.messages?.length} msgs`);
5153
5366
  h.historyWriter.appendNewMessages(
5154
5367
  provider?.type || getCurrentProviderType(h, "unknown_ide"),
5155
- parsed.messages || [],
5368
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
5156
5369
  parsed.title,
5157
5370
  args?.targetSessionId,
5158
5371
  historySessionId
5159
5372
  );
5160
- return { success: true, ...parsed };
5373
+ return buildReadChatCommandResult(parsed, args);
5161
5374
  }
5162
5375
  } catch (e) {
5163
5376
  LOG.info("Command", `[read_chat] Script error: ${e.message}`);
5164
5377
  }
5165
5378
  }
5166
- return { success: true, messages: [], status: "idle" };
5379
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
5167
5380
  }
5168
5381
  async function handleSendChat(h, args) {
5169
5382
  const text = args?.text || args?.message;
@@ -5814,6 +6027,7 @@ var RECENT_SEND_WINDOW_MS, recentSendByTarget;
5814
6027
  var init_chat_commands = __esm({
5815
6028
  "../../oss/packages/daemon-core/src/commands/chat-commands.ts"() {
5816
6029
  "use strict";
6030
+ init_contracts();
5817
6031
  init_chat_history();
5818
6032
  init_logger();
5819
6033
  RECENT_SEND_WINDOW_MS = 1200;
@@ -6299,21 +6513,21 @@ function applyProviderPatch(h, args, payload) {
6299
6513
  });
6300
6514
  }
6301
6515
  async function executeProviderScript(h, args, scriptName) {
6302
- const { agentType, ideType } = args || {};
6303
- if (!agentType) return { success: false, error: "agentType is required" };
6516
+ const resolvedProviderType = h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
6517
+ if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
6304
6518
  const loader = h.ctx.providerLoader;
6305
6519
  if (!loader) return { success: false, error: "ProviderLoader not initialized" };
6306
- const provider = loader.resolve(agentType);
6307
- if (!provider) return { success: false, error: `Provider not found: ${agentType}` };
6520
+ const provider = loader.resolve(resolvedProviderType);
6521
+ if (!provider) return { success: false, error: `Provider not found: ${resolvedProviderType}` };
6308
6522
  const webviewScriptName = `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`;
6309
6523
  const hasWebviewScript = provider.category === "ide" && !!provider.scripts?.[webviewScriptName];
6310
6524
  const actualScriptName = hasWebviewScript ? webviewScriptName : scriptName;
6311
6525
  if (!provider.scripts?.[actualScriptName]) {
6312
- return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
6526
+ return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
6313
6527
  }
6314
6528
  const normalizedArgs = normalizeProviderScriptArgs(args);
6315
6529
  if (provider.category === "cli") {
6316
- const adapter = h.getCliAdapter(args?.targetSessionId || agentType);
6530
+ const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
6317
6531
  if (!adapter?.invokeScript) {
6318
6532
  return { success: false, error: `CLI adapter does not support script '${actualScriptName}'` };
6319
6533
  }
@@ -6338,7 +6552,7 @@ async function executeProviderScript(h, args, scriptName) {
6338
6552
  const scriptFn = provider.scripts[actualScriptName];
6339
6553
  const scriptCode = scriptFn(normalizedArgs);
6340
6554
  if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
6341
- const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
6555
+ const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
6342
6556
  LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
6343
6557
  const cdp = h.getCdp(cdpKey);
6344
6558
  if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
@@ -6346,7 +6560,7 @@ async function executeProviderScript(h, args, scriptName) {
6346
6560
  let result;
6347
6561
  if (provider.category === "extension") {
6348
6562
  const runtimeSessionId = h.currentSession?.sessionId || args?.targetSessionId;
6349
- if (!runtimeSessionId) return { success: false, error: `No target session found for ${agentType}` };
6563
+ if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
6350
6564
  const parentSessionId = h.currentSession?.parentSessionId;
6351
6565
  if (parentSessionId) {
6352
6566
  await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
@@ -6375,7 +6589,7 @@ async function executeProviderScript(h, args, scriptName) {
6375
6589
  }
6376
6590
  } else {
6377
6591
  if (!targetSessionId) {
6378
- return { success: false, error: `No active session found for ${agentType}` };
6592
+ return { success: false, error: `No active session found for ${resolvedProviderType}` };
6379
6593
  }
6380
6594
  result = await cdp.evaluateInSessionFrame(targetSessionId, scriptCode);
6381
6595
  }
@@ -26834,17 +27048,6 @@ var init_acp = __esm({
26834
27048
  }
26835
27049
  });
26836
27050
 
26837
- // ../../oss/packages/daemon-core/src/providers/contracts.ts
26838
- function flattenContent(content) {
26839
- if (typeof content === "string") return content;
26840
- return content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
26841
- }
26842
- var init_contracts = __esm({
26843
- "../../oss/packages/daemon-core/src/providers/contracts.ts"() {
26844
- "use strict";
26845
- }
26846
- });
26847
-
26848
27051
  // ../../oss/packages/daemon-core/src/providers/acp-provider-instance.ts
26849
27052
  var import_stream, import_child_process5, AcpProviderInstance;
26850
27053
  var init_acp_provider_instance = __esm({
@@ -31997,6 +32200,37 @@ function buildAvailableProviders(providerLoader) {
31997
32200
  ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
31998
32201
  }));
31999
32202
  }
32203
+ function buildMachineInfo(profile = "full") {
32204
+ const base = {
32205
+ hostname: os17.hostname(),
32206
+ platform: os17.platform()
32207
+ };
32208
+ if (profile === "live") {
32209
+ return base;
32210
+ }
32211
+ if (profile === "metadata") {
32212
+ const memSnap2 = getHostMemorySnapshot();
32213
+ return {
32214
+ ...base,
32215
+ arch: os17.arch(),
32216
+ cpus: os17.cpus().length,
32217
+ totalMem: memSnap2.totalMem,
32218
+ release: os17.release()
32219
+ };
32220
+ }
32221
+ const memSnap = getHostMemorySnapshot();
32222
+ return {
32223
+ ...base,
32224
+ arch: os17.arch(),
32225
+ cpus: os17.cpus().length,
32226
+ totalMem: memSnap.totalMem,
32227
+ freeMem: memSnap.freeMem,
32228
+ availableMem: memSnap.availableMem,
32229
+ loadavg: os17.loadavg(),
32230
+ uptime: os17.uptime(),
32231
+ release: os17.release()
32232
+ };
32233
+ }
32000
32234
  function parseMessageTime(value) {
32001
32235
  if (typeof value === "number" && Number.isFinite(value)) return value;
32002
32236
  if (typeof value === "string") {
@@ -32052,26 +32286,35 @@ function buildRecentLaunches(recentActivity) {
32052
32286
  })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
32053
32287
  }
32054
32288
  function buildStatusSnapshot(options) {
32289
+ const profile = options.profile || "full";
32055
32290
  const cfg = loadConfig();
32056
32291
  const state = loadState();
32057
32292
  const wsState = getWorkspaceState(cfg);
32058
- const memSnap = getHostMemorySnapshot();
32059
32293
  const recentActivity = getRecentActivity(state, 20);
32060
- const sessions = buildSessionEntries(
32294
+ const unreadSourceSessions = buildSessionEntries(
32061
32295
  options.allStates,
32062
- options.cdpManagers
32296
+ options.cdpManagers,
32297
+ { profile: "full" }
32063
32298
  );
32064
- for (const session of sessions) {
32065
- const lastSeenAt = getSessionSeenAt(state, session.id);
32066
- const seenCompletionMarker = getSessionSeenMarker(state, session.id);
32067
- const lastUsedAt = getSessionLastUsedAt(session);
32068
- const completionMarker = getSessionCompletionMarker(session);
32069
- const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
32070
- getSessionMessageUpdatedAt(session) > 0,
32071
- session.status,
32299
+ const sessions = profile === "full" ? unreadSourceSessions : buildSessionEntries(
32300
+ options.allStates,
32301
+ options.cdpManagers,
32302
+ { profile }
32303
+ );
32304
+ const sessionsById = new Map(sessions.map((session) => [session.id, session]));
32305
+ for (const sourceSession of unreadSourceSessions) {
32306
+ const session = sessionsById.get(sourceSession.id);
32307
+ if (!session) continue;
32308
+ const lastSeenAt = getSessionSeenAt(state, sourceSession.id);
32309
+ const seenCompletionMarker = getSessionSeenMarker(state, sourceSession.id);
32310
+ const lastUsedAt = getSessionLastUsedAt(sourceSession);
32311
+ const completionMarker = getSessionCompletionMarker(sourceSession);
32312
+ const { unread, inboxBucket } = sourceSession.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
32313
+ getSessionMessageUpdatedAt(sourceSession) > 0,
32314
+ sourceSession.status,
32072
32315
  lastUsedAt,
32073
32316
  lastSeenAt,
32074
- getLastMessageRole(session),
32317
+ getLastMessageRole(sourceSession),
32075
32318
  completionMarker,
32076
32319
  seenCompletionMarker
32077
32320
  );
@@ -32081,39 +32324,30 @@ function buildStatusSnapshot(options) {
32081
32324
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
32082
32325
  LOG.info(
32083
32326
  "RecentRead",
32084
- `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(session)} msgUpdatedAt=${getSessionMessageUpdatedAt(session)}`
32327
+ `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(sourceSession)} msgUpdatedAt=${getSessionMessageUpdatedAt(sourceSession)}`
32085
32328
  );
32086
32329
  }
32087
32330
  }
32088
- const terminalBackend = getTerminalBackendRuntimeStatus();
32331
+ const includeMachineMetadata = profile !== "live";
32332
+ const terminalBackend = includeMachineMetadata ? getTerminalBackendRuntimeStatus() : void 0;
32089
32333
  return {
32090
32334
  instanceId: options.instanceId,
32091
- version: options.version,
32092
- daemonMode: options.daemonMode,
32093
- machine: {
32094
- hostname: os17.hostname(),
32095
- platform: os17.platform(),
32096
- arch: os17.arch(),
32097
- cpus: os17.cpus().length,
32098
- totalMem: memSnap.totalMem,
32099
- freeMem: memSnap.freeMem,
32100
- availableMem: memSnap.availableMem,
32101
- loadavg: os17.loadavg(),
32102
- uptime: os17.uptime(),
32103
- release: os17.release()
32104
- },
32105
- machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
32335
+ ...includeMachineMetadata ? { version: options.version } : {},
32336
+ machine: buildMachineInfo(profile),
32337
+ ...includeMachineMetadata ? { machineNickname: options.machineNickname ?? cfg.machineNickname ?? null } : {},
32106
32338
  timestamp: options.timestamp ?? Date.now(),
32107
- detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
32108
32339
  ...options.p2p ? { p2p: options.p2p } : {},
32109
32340
  sessions,
32110
- workspaces: wsState.workspaces,
32111
- defaultWorkspaceId: wsState.defaultWorkspaceId,
32112
- defaultWorkspacePath: wsState.defaultWorkspacePath,
32113
- terminalSizingMode: cfg.terminalSizingMode || "measured",
32114
- recentLaunches: buildRecentLaunches(recentActivity),
32115
- terminalBackend,
32116
- availableProviders: buildAvailableProviders(options.providerLoader)
32341
+ ...terminalBackend ? { terminalBackend } : {},
32342
+ ...includeMachineMetadata && {
32343
+ detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
32344
+ workspaces: wsState.workspaces,
32345
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
32346
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
32347
+ terminalSizingMode: cfg.terminalSizingMode || "measured",
32348
+ recentLaunches: buildRecentLaunches(recentActivity),
32349
+ availableProviders: buildAvailableProviders(options.providerLoader)
32350
+ }
32117
32351
  };
32118
32352
  }
32119
32353
  var os17, READ_DEBUG_ENABLED;
@@ -32384,6 +32618,7 @@ var init_router = __esm({
32384
32618
  init_logger();
32385
32619
  init_builders();
32386
32620
  init_snapshot();
32621
+ init_snapshot();
32387
32622
  init_upgrade_helper();
32388
32623
  fs9 = __toESM(require("fs"));
32389
32624
  CHAT_COMMANDS = [
@@ -32712,6 +32947,25 @@ var init_router = __esm({
32712
32947
  updateConfig({ userName: name });
32713
32948
  return { success: true, userName: name };
32714
32949
  }
32950
+ case "get_status_metadata": {
32951
+ const snapshot = buildStatusSnapshot({
32952
+ allStates: this.deps.instanceManager.collectAllStates(),
32953
+ cdpManagers: this.deps.cdpManagers,
32954
+ providerLoader: this.deps.providerLoader,
32955
+ detectedIdes: this.deps.detectedIdes.value,
32956
+ instanceId: this.deps.statusInstanceId || loadConfig().machineId || "daemon",
32957
+ version: this.deps.statusVersion || "unknown",
32958
+ profile: "metadata"
32959
+ });
32960
+ return { success: true, status: snapshot };
32961
+ }
32962
+ case "get_machine_runtime_stats": {
32963
+ return {
32964
+ success: true,
32965
+ machine: buildMachineInfo("full"),
32966
+ timestamp: Date.now()
32967
+ };
32968
+ }
32715
32969
  case "mark_session_seen": {
32716
32970
  const sessionId = args?.sessionId;
32717
32971
  if (!sessionId || typeof sessionId !== "string") {
@@ -32925,9 +33179,58 @@ var init_reporter = __esm({
32925
33179
  }, 5e3 - elapsed);
32926
33180
  }
32927
33181
  }
33182
+ toDaemonStatusEventName(value) {
33183
+ switch (value) {
33184
+ case "agent:generating_started":
33185
+ case "agent:waiting_approval":
33186
+ case "agent:generating_completed":
33187
+ case "agent:stopped":
33188
+ case "monitor:long_generating":
33189
+ return value;
33190
+ default:
33191
+ return null;
33192
+ }
33193
+ }
33194
+ buildServerStatusEvent(event) {
33195
+ const eventName = this.toDaemonStatusEventName(event.event);
33196
+ if (!eventName) return null;
33197
+ if (eventName.startsWith("provider:")) {
33198
+ return null;
33199
+ }
33200
+ const payload = {
33201
+ event: eventName,
33202
+ timestamp: typeof event.timestamp === "number" && Number.isFinite(event.timestamp) ? event.timestamp : Date.now()
33203
+ };
33204
+ if (typeof event.targetSessionId === "string" && event.targetSessionId.trim()) {
33205
+ payload.targetSessionId = event.targetSessionId.trim();
33206
+ }
33207
+ const providerType = typeof event.providerType === "string" && event.providerType.trim() ? event.providerType.trim() : typeof event.ideType === "string" && event.ideType.trim() ? event.ideType.trim() : "";
33208
+ if (providerType) {
33209
+ payload.providerType = providerType;
33210
+ }
33211
+ if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
33212
+ payload.duration = event.duration;
33213
+ }
33214
+ if (typeof event.elapsedSec === "number" && Number.isFinite(event.elapsedSec)) {
33215
+ payload.elapsedSec = event.elapsedSec;
33216
+ }
33217
+ if (typeof event.modalMessage === "string" && event.modalMessage.trim()) {
33218
+ payload.modalMessage = event.modalMessage;
33219
+ }
33220
+ if (Array.isArray(event.modalButtons)) {
33221
+ const modalButtons = event.modalButtons.filter((button) => typeof button === "string" && button.trim().length > 0);
33222
+ if (modalButtons.length > 0) {
33223
+ payload.modalButtons = modalButtons;
33224
+ }
33225
+ }
33226
+ return payload;
33227
+ }
32928
33228
  emitStatusEvent(event) {
32929
33229
  LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
32930
- this.deps.serverConn?.sendMessage("status_event", event);
33230
+ const serverEvent = this.buildServerStatusEvent(event);
33231
+ if (!serverEvent) return;
33232
+ this.deps.p2p?.sendStatusEvent(serverEvent);
33233
+ this.deps.serverConn?.sendMessage("status_event", serverEvent);
32931
33234
  }
32932
33235
  removeAgentTracking(_key) {
32933
33236
  }
@@ -32996,17 +33299,16 @@ var init_reporter = __esm({
32996
33299
  detectedIdes: this.deps.detectedIdes || [],
32997
33300
  instanceId: this.deps.instanceId,
32998
33301
  version: this.deps.daemonVersion || "unknown",
32999
- daemonMode: true,
33000
33302
  timestamp: now,
33001
33303
  p2p: {
33002
33304
  available: p2p?.isAvailable || false,
33003
33305
  state: p2p?.connectionState || "unavailable",
33004
33306
  peers: p2p?.connectedPeerCount || 0,
33005
33307
  screenshotActive: p2p?.screenshotActive || false
33006
- }
33308
+ },
33309
+ profile: "live"
33007
33310
  }),
33008
- screenshotUsage: this.deps.getScreenshotUsage?.() || null,
33009
- connectedExtensions: []
33311
+ screenshotUsage: this.deps.getScreenshotUsage?.() || null
33010
33312
  };
33011
33313
  const payloadBytes = JSON.stringify(payload).length;
33012
33314
  const p2pSent = this.sendP2PPayload(payload);
@@ -33021,16 +33323,15 @@ var init_reporter = __esm({
33021
33323
  }
33022
33324
  if (opts?.p2pOnly) return;
33023
33325
  const wsPayload = {
33024
- daemonMode: true,
33025
33326
  sessions: sessions.map((session) => ({
33026
33327
  id: session.id,
33027
33328
  parentId: session.parentId,
33028
33329
  providerType: session.providerType,
33029
- providerName: session.providerName,
33330
+ providerName: session.providerName || session.providerType,
33030
33331
  kind: session.kind,
33031
33332
  transport: session.transport,
33032
33333
  status: session.status,
33033
- workspace: session.workspace,
33334
+ workspace: session.workspace ?? null,
33034
33335
  title: session.title,
33035
33336
  cdpConnected: session.cdpConnected,
33036
33337
  currentModel: session.currentModel,
@@ -33038,9 +33339,7 @@ var init_reporter = __esm({
33038
33339
  currentAutoApprove: session.currentAutoApprove
33039
33340
  })),
33040
33341
  p2p: payload.p2p,
33041
- timestamp: now,
33042
- detectedIdes: payload.detectedIdes,
33043
- availableProviders: payload.availableProviders
33342
+ timestamp: now
33044
33343
  };
33045
33344
  const wsHash = this.simpleHash(JSON.stringify({
33046
33345
  ...wsPayload,
@@ -33057,10 +33356,15 @@ var init_reporter = __esm({
33057
33356
  // ─── P2P ─────────────────────────────────────────
33058
33357
  sendP2PPayload(payload) {
33059
33358
  const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
33359
+ const sessions = Array.isArray(hashTarget.sessions) ? hashTarget.sessions.map((session) => {
33360
+ if (!session || typeof session !== "object") return session;
33361
+ const { lastUpdated: _lu, ...stableSession } = session;
33362
+ return stableSession;
33363
+ }) : hashTarget.sessions;
33060
33364
  const hashPayload = hashTarget.machine ? (() => {
33061
33365
  const { freeMem: _f, availableMem: _a2, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
33062
- return { ...hashTarget, machine: stableMachine };
33063
- })() : hashTarget;
33366
+ return { ...hashTarget, sessions, machine: stableMachine };
33367
+ })() : { ...hashTarget, sessions };
33064
33368
  const h = this.simpleHash(JSON.stringify(hashPayload));
33065
33369
  if (h !== this.lastP2PStatusHash) {
33066
33370
  this.lastP2PStatusHash = h;
@@ -40271,6 +40575,8 @@ async function initDaemonComponents(config2) {
40271
40575
  onStatusChange: config2.onStatusChange,
40272
40576
  onPostChatCommand: config2.onPostChatCommand,
40273
40577
  sessionHostControl: config2.sessionHostControl,
40578
+ statusInstanceId: config2.statusInstanceId,
40579
+ statusVersion: config2.statusVersion,
40274
40580
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
40275
40581
  });
40276
40582
  poller = new AgentStreamPoller({
@@ -40396,6 +40702,7 @@ __export(src_exports, {
40396
40702
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory,
40397
40703
  VersionArchive: () => VersionArchive,
40398
40704
  appendRecentActivity: () => appendRecentActivity,
40705
+ buildMachineInfo: () => buildMachineInfo,
40399
40706
  buildSessionEntries: () => buildSessionEntries,
40400
40707
  buildStatusSnapshot: () => buildStatusSnapshot,
40401
40708
  connectCdpManager: () => connectCdpManager,
@@ -40539,6 +40846,7 @@ var init_server_connection = __esm({
40539
40846
  this.ws = new import_ws2.default(fullUrl, {
40540
40847
  headers: {
40541
40848
  "X-ADHDev-Token": this.options.token,
40849
+ "X-ADHDev-Daemon": JSON.stringify(this.options.cliInfo),
40542
40850
  "X-ADHDev-IDE": JSON.stringify(this.options.cliInfo),
40543
40851
  "X-ADHDev-Version": this.options.daemonVersion || "unknown"
40544
40852
  }
@@ -40623,7 +40931,7 @@ var init_server_connection = __esm({
40623
40931
  type: "auth",
40624
40932
  payload: {
40625
40933
  token: this.options.token,
40626
- ide: this.options.cliInfo
40934
+ daemon: this.options.cliInfo
40627
40935
  },
40628
40936
  timestamp: Date.now()
40629
40937
  });
@@ -40863,11 +41171,19 @@ function routeDataChannelMessage(peerId, msg, peers, handlers) {
40863
41171
  if (peer) peer.lastPongAt = Date.now();
40864
41172
  return;
40865
41173
  }
41174
+ if (parsed.type === "subscribe") {
41175
+ handleSubscribe(peerId, parsed, peers, handlers);
41176
+ return;
41177
+ }
41178
+ if (parsed.type === "unsubscribe") {
41179
+ handleUnsubscribe(peerId, parsed, peers);
41180
+ return;
41181
+ }
40866
41182
  if (parsed.type === "screenshot_start") {
40867
41183
  const peer = peers.get(peerId);
40868
41184
  const permission = peer?.sharePermission;
40869
- if (!parsed.ideType) {
40870
- log(`screenshot_start: REJECTED \u2014 no ideType from peer ${peerId}`);
41185
+ if (!parsed.targetSessionId) {
41186
+ log(`screenshot_start: REJECTED \u2014 no targetSessionId from peer ${peerId}`);
40871
41187
  return;
40872
41188
  }
40873
41189
  if (!canPeerStartScreenshots(permission)) {
@@ -40876,9 +41192,9 @@ function routeDataChannelMessage(peerId, msg, peers, handlers) {
40876
41192
  }
40877
41193
  if (peer) {
40878
41194
  peer.screenshotActive = true;
40879
- peer.screenshotIdeType = parsed.ideType;
41195
+ peer.screenshotTargetSessionId = parsed.targetSessionId;
40880
41196
  peer.needsFirstFrame = true;
40881
- log(`screenshot_start: peer=${peerId}, ideType=${parsed.ideType}, channelOpen=${!!peer.dataChannel}, state=${peer.state}`);
41197
+ log(`screenshot_start: peer=${peerId}, targetSessionId=${parsed.targetSessionId}, channelOpen=${!!peer.dataChannel}, state=${peer.state}`);
40882
41198
  handlers.screenshotStartHandler?.();
40883
41199
  } else {
40884
41200
  log(`screenshot_start: peer ${peerId} NOT FOUND in peers map!`);
@@ -40930,6 +41246,87 @@ function routeDataChannelMessage(peerId, msg, peers, handlers) {
40930
41246
  log(`Parse error from peer ${peerId}: ${e?.message}`);
40931
41247
  }
40932
41248
  }
41249
+ function handleSubscribe(peerId, msg, peers, handlers) {
41250
+ const peer = peers.get(peerId);
41251
+ if (!peer) return;
41252
+ if (msg.topic === "session.chat_tail") {
41253
+ const targetSessionId = typeof msg.params?.targetSessionId === "string" ? msg.params.targetSessionId.trim() : "";
41254
+ if (!targetSessionId) return;
41255
+ if (!peer.chatSubscriptions) peer.chatSubscriptions = /* @__PURE__ */ new Map();
41256
+ peer.chatSubscriptions.set(msg.key, {
41257
+ key: msg.key,
41258
+ params: msg.params,
41259
+ seq: 0,
41260
+ cursor: {
41261
+ knownMessageCount: Math.max(0, Number(msg.params.knownMessageCount || 0)),
41262
+ lastMessageSignature: typeof msg.params.lastMessageSignature === "string" ? msg.params.lastMessageSignature : "",
41263
+ tailLimit: Math.max(0, Number(msg.params.tailLimit || 0))
41264
+ },
41265
+ lastDeliveredSignature: ""
41266
+ });
41267
+ } else if (msg.topic === "machine.runtime") {
41268
+ if (!peer.machineRuntimeSubscriptions) peer.machineRuntimeSubscriptions = /* @__PURE__ */ new Map();
41269
+ peer.machineRuntimeSubscriptions.set(msg.key, {
41270
+ key: msg.key,
41271
+ params: msg.params,
41272
+ seq: 0,
41273
+ lastSentAt: 0
41274
+ });
41275
+ } else if (msg.topic === "session_host.diagnostics") {
41276
+ if (!peer.sessionHostDiagnosticsSubscriptions) peer.sessionHostDiagnosticsSubscriptions = /* @__PURE__ */ new Map();
41277
+ peer.sessionHostDiagnosticsSubscriptions.set(msg.key, {
41278
+ key: msg.key,
41279
+ params: msg.params,
41280
+ seq: 0,
41281
+ lastSentAt: 0
41282
+ });
41283
+ } else if (msg.topic === "session.modal") {
41284
+ const targetSessionId = typeof msg.params?.targetSessionId === "string" ? msg.params.targetSessionId.trim() : "";
41285
+ if (!targetSessionId) return;
41286
+ if (!peer.sessionModalSubscriptions) peer.sessionModalSubscriptions = /* @__PURE__ */ new Map();
41287
+ peer.sessionModalSubscriptions.set(msg.key, {
41288
+ key: msg.key,
41289
+ params: msg.params,
41290
+ seq: 0,
41291
+ lastSentAt: 0,
41292
+ lastDeliveredSignature: ""
41293
+ });
41294
+ } else if (msg.topic === "daemon.metadata") {
41295
+ if (!peer.daemonMetadataSubscriptions) peer.daemonMetadataSubscriptions = /* @__PURE__ */ new Map();
41296
+ peer.daemonMetadataSubscriptions.set(msg.key, {
41297
+ key: msg.key,
41298
+ params: msg.params,
41299
+ seq: 0,
41300
+ lastSentAt: 0
41301
+ });
41302
+ } else {
41303
+ return;
41304
+ }
41305
+ handlers.subscriptionChangeHandler?.();
41306
+ }
41307
+ function handleUnsubscribe(peerId, msg, peers) {
41308
+ const peer = peers.get(peerId);
41309
+ if (!peer) return;
41310
+ if (msg.topic === "session.chat_tail") {
41311
+ peer.chatSubscriptions?.delete(msg.key);
41312
+ return;
41313
+ }
41314
+ if (msg.topic === "machine.runtime") {
41315
+ peer.machineRuntimeSubscriptions?.delete(msg.key);
41316
+ return;
41317
+ }
41318
+ if (msg.topic === "session_host.diagnostics") {
41319
+ peer.sessionHostDiagnosticsSubscriptions?.delete(msg.key);
41320
+ return;
41321
+ }
41322
+ if (msg.topic === "session.modal") {
41323
+ peer.sessionModalSubscriptions?.delete(msg.key);
41324
+ return;
41325
+ }
41326
+ if (msg.topic === "daemon.metadata") {
41327
+ peer.daemonMetadataSubscriptions?.delete(msg.key);
41328
+ }
41329
+ }
40933
41330
  async function handleP2PCommand(peerId, msg, peers, handlers) {
40934
41331
  const { id, commandType, data } = msg;
40935
41332
  const peer = peers.get(peerId);
@@ -40950,7 +41347,7 @@ async function handleP2PCommand(peerId, msg, peers, handlers) {
40950
41347
  }
40951
41348
  }
40952
41349
  async function handleInputEvent(peerId, msg, peers, handlers) {
40953
- const { id, action, params, instanceId } = msg;
41350
+ const { id, action, params, targetSessionId: explicitTargetSessionId } = msg;
40954
41351
  const peer = peers.get(peerId);
40955
41352
  const permission = peer?.sharePermission;
40956
41353
  if (!canPeerUseRemoteInput(permission)) {
@@ -40962,11 +41359,11 @@ async function handleInputEvent(peerId, msg, peers, handlers) {
40962
41359
  return;
40963
41360
  }
40964
41361
  try {
40965
- const ideType = instanceId || peer?.screenshotIdeType;
40966
- if (!ideType) {
40967
- log(`[Input] WARNING: No instanceId or screenshotIdeType for peer ${peerId}`);
41362
+ const targetSessionId = explicitTargetSessionId || peer?.screenshotTargetSessionId;
41363
+ if (!targetSessionId) {
41364
+ log(`[Input] WARNING: No targetSessionId for peer ${peerId}`);
40968
41365
  }
40969
- const result = await handlers.inputHandler({ action, params, ideType });
41366
+ const result = await handlers.inputHandler({ action, params, targetSessionId });
40970
41367
  sendToPeer(peer, { id, type: "response", success: true, result });
40971
41368
  } catch (e) {
40972
41369
  sendToPeer(peer, { id, type: "response", success: false, error: e?.message });
@@ -41025,6 +41422,35 @@ var init_screenshot_sender = __esm({
41025
41422
  }
41026
41423
  return sentAny;
41027
41424
  }
41425
+ sendStatusEvent(peers, event) {
41426
+ const payload = JSON.stringify({
41427
+ type: "status_event",
41428
+ payload: event,
41429
+ timestamp: Date.now()
41430
+ });
41431
+ let sentAny = false;
41432
+ for (const peer of peers.values()) {
41433
+ if (peer.state !== "connected" || !peer.dataChannel) continue;
41434
+ try {
41435
+ peer.dataChannel.sendMessage(payload);
41436
+ sentAny = true;
41437
+ } catch {
41438
+ }
41439
+ }
41440
+ return sentAny;
41441
+ }
41442
+ sendTopicUpdateToPeer(peer, update) {
41443
+ if (!peer?.dataChannel || peer.state !== "connected") return false;
41444
+ try {
41445
+ peer.dataChannel.sendMessage(JSON.stringify({
41446
+ type: "topic_update",
41447
+ update
41448
+ }));
41449
+ return true;
41450
+ } catch {
41451
+ return false;
41452
+ }
41453
+ }
41028
41454
  /** Broadcast runtime session output to all connected peers */
41029
41455
  broadcastSessionOutput(peers, sessionId, data) {
41030
41456
  const msg = JSON.stringify({ type: "session_output", sessionId, data });
@@ -41186,7 +41612,12 @@ async function initiateConnection(deps, peerId, sharePermission) {
41186
41612
  pendingCandidates: [],
41187
41613
  remoteDescriptionSet: false,
41188
41614
  isRelay: false,
41189
- lastPongAt: Date.now()
41615
+ lastPongAt: Date.now(),
41616
+ chatSubscriptions: /* @__PURE__ */ new Map(),
41617
+ machineRuntimeSubscriptions: /* @__PURE__ */ new Map(),
41618
+ sessionHostDiagnosticsSubscriptions: /* @__PURE__ */ new Map(),
41619
+ sessionModalSubscriptions: /* @__PURE__ */ new Map(),
41620
+ daemonMetadataSubscriptions: /* @__PURE__ */ new Map()
41190
41621
  };
41191
41622
  deps.peers.set(pid, entry);
41192
41623
  deps.notifyStateChange();
@@ -41433,7 +41864,8 @@ var init_daemon_p2p = __esm({
41433
41864
  commandHandler: null,
41434
41865
  ptyInputHandler: null,
41435
41866
  ptyResizeHandler: null,
41436
- screenshotStartHandler: null
41867
+ screenshotStartHandler: null,
41868
+ subscriptionChangeHandler: null
41437
41869
  };
41438
41870
  get screenshotActive() {
41439
41871
  for (const peer of this.peers.values()) {
@@ -41441,11 +41873,11 @@ var init_daemon_p2p = __esm({
41441
41873
  }
41442
41874
  return false;
41443
41875
  }
41444
- /** Get the ideType for the currently active screenshot request */
41445
- get screenshotIdeType() {
41876
+ /** Get the target session for the currently active screenshot request */
41877
+ get screenshotTargetSessionId() {
41446
41878
  for (const peer of this.peers.values()) {
41447
- if (peer.screenshotActive && peer.state === "connected" && peer.screenshotIdeType) {
41448
- return peer.screenshotIdeType;
41879
+ if (peer.screenshotActive && peer.state === "connected" && peer.screenshotTargetSessionId) {
41880
+ return peer.screenshotTargetSessionId;
41449
41881
  }
41450
41882
  }
41451
41883
  return void 0;
@@ -41597,6 +42029,9 @@ ${e?.stack || ""}`);
41597
42029
  sendStatus(status) {
41598
42030
  return this.screenshotSender.sendStatus(this.peers, status);
41599
42031
  }
42032
+ sendStatusEvent(event) {
42033
+ return this.screenshotSender.sendStatusEvent(this.peers, event);
42034
+ }
41600
42035
  broadcastSessionOutput(sessionId, data) {
41601
42036
  return this.screenshotSender.broadcastSessionOutput(this.peers, sessionId, data);
41602
42037
  }
@@ -41625,6 +42060,89 @@ ${e?.stack || ""}`);
41625
42060
  onScreenshotStart(handler) {
41626
42061
  this.handlers.screenshotStartHandler = handler;
41627
42062
  }
42063
+ onSubscriptionChange(handler) {
42064
+ this.handlers.subscriptionChangeHandler = handler;
42065
+ }
42066
+ hasChatSubscriptions() {
42067
+ for (const peer of this.peers.values()) {
42068
+ if (peer.chatSubscriptions && peer.chatSubscriptions.size > 0) return true;
42069
+ }
42070
+ return false;
42071
+ }
42072
+ hasMachineRuntimeSubscriptions() {
42073
+ for (const peer of this.peers.values()) {
42074
+ if (peer.machineRuntimeSubscriptions && peer.machineRuntimeSubscriptions.size > 0) return true;
42075
+ }
42076
+ return false;
42077
+ }
42078
+ hasSessionHostDiagnosticsSubscriptions() {
42079
+ for (const peer of this.peers.values()) {
42080
+ if (peer.sessionHostDiagnosticsSubscriptions && peer.sessionHostDiagnosticsSubscriptions.size > 0) return true;
42081
+ }
42082
+ return false;
42083
+ }
42084
+ hasSessionModalSubscriptions() {
42085
+ for (const peer of this.peers.values()) {
42086
+ if (peer.sessionModalSubscriptions && peer.sessionModalSubscriptions.size > 0) return true;
42087
+ }
42088
+ return false;
42089
+ }
42090
+ hasDaemonMetadataSubscriptions() {
42091
+ for (const peer of this.peers.values()) {
42092
+ if (peer.daemonMetadataSubscriptions && peer.daemonMetadataSubscriptions.size > 0) return true;
42093
+ }
42094
+ return false;
42095
+ }
42096
+ async flushChatSubscriptions(builder) {
42097
+ for (const peer of this.peers.values()) {
42098
+ if (peer.state !== "connected" || !peer.chatSubscriptions || peer.chatSubscriptions.size === 0) continue;
42099
+ for (const subscription of peer.chatSubscriptions.values()) {
42100
+ const update = await builder(subscription);
42101
+ if (!update) continue;
42102
+ this.screenshotSender.sendTopicUpdateToPeer(peer, update);
42103
+ }
42104
+ }
42105
+ }
42106
+ async flushMachineRuntimeSubscriptions(builder) {
42107
+ for (const peer of this.peers.values()) {
42108
+ if (peer.state !== "connected" || !peer.machineRuntimeSubscriptions || peer.machineRuntimeSubscriptions.size === 0) continue;
42109
+ for (const subscription of peer.machineRuntimeSubscriptions.values()) {
42110
+ const update = await builder(subscription);
42111
+ if (!update) continue;
42112
+ this.screenshotSender.sendTopicUpdateToPeer(peer, update);
42113
+ }
42114
+ }
42115
+ }
42116
+ async flushSessionHostDiagnosticsSubscriptions(builder) {
42117
+ for (const peer of this.peers.values()) {
42118
+ if (peer.state !== "connected" || !peer.sessionHostDiagnosticsSubscriptions || peer.sessionHostDiagnosticsSubscriptions.size === 0) continue;
42119
+ for (const subscription of peer.sessionHostDiagnosticsSubscriptions.values()) {
42120
+ const update = await builder(subscription);
42121
+ if (!update) continue;
42122
+ this.screenshotSender.sendTopicUpdateToPeer(peer, update);
42123
+ }
42124
+ }
42125
+ }
42126
+ async flushSessionModalSubscriptions(builder) {
42127
+ for (const peer of this.peers.values()) {
42128
+ if (peer.state !== "connected" || !peer.sessionModalSubscriptions || peer.sessionModalSubscriptions.size === 0) continue;
42129
+ for (const subscription of peer.sessionModalSubscriptions.values()) {
42130
+ const update = await builder(subscription);
42131
+ if (!update) continue;
42132
+ this.screenshotSender.sendTopicUpdateToPeer(peer, update);
42133
+ }
42134
+ }
42135
+ }
42136
+ async flushDaemonMetadataSubscriptions(builder) {
42137
+ for (const peer of this.peers.values()) {
42138
+ if (peer.state !== "connected" || !peer.daemonMetadataSubscriptions || peer.daemonMetadataSubscriptions.size === 0) continue;
42139
+ for (const subscription of peer.daemonMetadataSubscriptions.values()) {
42140
+ const update = await builder(subscription);
42141
+ if (!update) continue;
42142
+ this.screenshotSender.sendTopicUpdateToPeer(peer, update);
42143
+ }
42144
+ }
42145
+ }
41628
42146
  };
41629
42147
  }
41630
42148
  });
@@ -48285,12 +48803,12 @@ var init_screenshot_controller = __esm({
48285
48803
  async tick() {
48286
48804
  if (!this.deps.isRunning()) return;
48287
48805
  const active = this.deps.isScreenshotActive();
48288
- const ssIdeType = this.deps.getScreenshotIdeType();
48289
- if (active && !ssIdeType) {
48806
+ const targetSessionId = this.deps.getScreenshotTargetSessionId();
48807
+ if (active && !targetSessionId) {
48290
48808
  this.timer = setTimeout(() => this.tick(), 500);
48291
48809
  return;
48292
48810
  }
48293
- const cdp = ssIdeType ? this.deps.getCdp(ssIdeType) : null;
48811
+ const cdp = targetSessionId ? this.deps.getCdp(targetSessionId) : null;
48294
48812
  const isRelay = this.deps.isUsingRelay();
48295
48813
  const profile = isRelay ? this.profileRelay : this.profileDirect;
48296
48814
  this.checkBudgetReset();
@@ -48769,6 +49287,48 @@ __export(adhdev_daemon_exports, {
48769
49287
  isDaemonRunning: () => isDaemonRunning,
48770
49288
  stopDaemon: () => stopDaemon
48771
49289
  });
49290
+ function hashSignatureParts2(parts) {
49291
+ let hash2 = 2166136261;
49292
+ for (const part of parts) {
49293
+ const text = String(part || "");
49294
+ for (let i = 0; i < text.length; i += 1) {
49295
+ hash2 ^= text.charCodeAt(i);
49296
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
49297
+ }
49298
+ hash2 ^= 255;
49299
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
49300
+ }
49301
+ return hash2.toString(16).padStart(8, "0");
49302
+ }
49303
+ function buildChatTailDeliverySignature(payload) {
49304
+ let messages = "";
49305
+ try {
49306
+ messages = JSON.stringify(payload.messages);
49307
+ } catch {
49308
+ messages = String(payload.messages.length);
49309
+ }
49310
+ return hashSignatureParts2([
49311
+ payload.sessionId,
49312
+ payload.historySessionId || "",
49313
+ payload.status,
49314
+ payload.title || "",
49315
+ payload.syncMode,
49316
+ String(payload.replaceFrom),
49317
+ String(payload.totalMessages),
49318
+ payload.lastMessageSignature,
49319
+ payload.activeModal ? `${payload.activeModal.message}|${payload.activeModal.buttons.join("")}` : "",
49320
+ messages
49321
+ ]);
49322
+ }
49323
+ function buildSessionModalDeliverySignature(payload) {
49324
+ return hashSignatureParts2([
49325
+ payload.sessionId,
49326
+ payload.status,
49327
+ payload.title || "",
49328
+ payload.modalMessage || "",
49329
+ Array.isArray(payload.modalButtons) ? payload.modalButtons.join("") : ""
49330
+ ]);
49331
+ }
48772
49332
  function getDaemonPidFile() {
48773
49333
  const dir = path25.join(os23.homedir(), ".adhdev");
48774
49334
  if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
@@ -48832,7 +49392,7 @@ function stopDaemon() {
48832
49392
  return false;
48833
49393
  }
48834
49394
  }
48835
- var os23, fs17, path25, import_http, import_ws3, import_chalk2, pkgVersion, AdhdevDaemon;
49395
+ var os23, fs17, path25, import_http, import_ws3, import_chalk2, pkgVersion, ACTIVE_CHAT_POLL_STATUSES, AdhdevDaemon;
48836
49396
  var init_adhdev_daemon = __esm({
48837
49397
  "src/adhdev-daemon.ts"() {
48838
49398
  "use strict";
@@ -48850,7 +49410,12 @@ var init_adhdev_daemon = __esm({
48850
49410
  import_ws3 = require("ws");
48851
49411
  import_chalk2 = __toESM(require("chalk"));
48852
49412
  init_version();
48853
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.35" });
49413
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.36" });
49414
+ ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
49415
+ "generating",
49416
+ "waiting_approval",
49417
+ "starting"
49418
+ ]);
48854
49419
  AdhdevDaemon = class {
48855
49420
  localHttpServer = null;
48856
49421
  localWss = null;
@@ -48859,6 +49424,11 @@ var init_adhdev_daemon = __esm({
48859
49424
  p2p = null;
48860
49425
  screenshotController = null;
48861
49426
  statusReporter = null;
49427
+ topicSubscriptionTimer = null;
49428
+ p2pChatFlushInFlight = false;
49429
+ pendingP2PChatFlush = false;
49430
+ pendingP2PChatFlushOnlyActive = true;
49431
+ hotP2PChatSessionIds = /* @__PURE__ */ new Set();
48862
49432
  components = null;
48863
49433
  sessionHostEndpoint = null;
48864
49434
  sessionHostController = null;
@@ -48882,6 +49452,252 @@ var init_adhdev_daemon = __esm({
48882
49452
  const mode = this.getCliPresentationMode(sessionId);
48883
49453
  return mode === "chat" || mode === "terminal";
48884
49454
  }
49455
+ async buildChatTailUpdateForSubscription(subscription) {
49456
+ const result = await this.components.router.execute("read_chat", {
49457
+ targetSessionId: subscription.params.targetSessionId,
49458
+ ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
49459
+ knownMessageCount: subscription.cursor.knownMessageCount,
49460
+ lastMessageSignature: subscription.cursor.lastMessageSignature,
49461
+ ...subscription.cursor.tailLimit > 0 ? { tailLimit: subscription.cursor.tailLimit } : {}
49462
+ }, "p2p");
49463
+ if (!result?.success || result.syncMode === "noop") {
49464
+ if (result?.success) {
49465
+ subscription.cursor = {
49466
+ knownMessageCount: Math.max(0, Number(result.totalMessages || subscription.cursor.knownMessageCount)),
49467
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : subscription.cursor.lastMessageSignature,
49468
+ tailLimit: subscription.cursor.tailLimit
49469
+ };
49470
+ }
49471
+ return null;
49472
+ }
49473
+ subscription.seq += 1;
49474
+ const syncMode = result.syncMode === "append" || result.syncMode === "replace_tail" || result.syncMode === "noop" || result.syncMode === "full" ? result.syncMode : "full";
49475
+ subscription.cursor = {
49476
+ knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
49477
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
49478
+ tailLimit: subscription.cursor.tailLimit
49479
+ };
49480
+ const activeModal = result.activeModal && typeof result.activeModal === "object" && typeof result.activeModal.message === "string" && Array.isArray(result.activeModal.buttons) ? {
49481
+ message: result.activeModal.message,
49482
+ buttons: result.activeModal.buttons.filter((button) => typeof button === "string")
49483
+ } : null;
49484
+ const deliverySignature = buildChatTailDeliverySignature({
49485
+ sessionId: subscription.params.targetSessionId,
49486
+ ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
49487
+ messages: Array.isArray(result.messages) ? result.messages : [],
49488
+ status: typeof result.status === "string" ? result.status : "idle",
49489
+ ...typeof result.title === "string" ? { title: result.title } : {},
49490
+ ...activeModal ? { activeModal } : {},
49491
+ syncMode,
49492
+ replaceFrom: Number(result.replaceFrom || 0),
49493
+ totalMessages: Number(result.totalMessages || 0),
49494
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
49495
+ });
49496
+ if (deliverySignature === subscription.lastDeliveredSignature) {
49497
+ return null;
49498
+ }
49499
+ subscription.lastDeliveredSignature = deliverySignature;
49500
+ return {
49501
+ topic: "session.chat_tail",
49502
+ key: subscription.key,
49503
+ sessionId: subscription.params.targetSessionId,
49504
+ ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
49505
+ seq: subscription.seq,
49506
+ timestamp: Date.now(),
49507
+ messages: Array.isArray(result.messages) ? result.messages : [],
49508
+ status: typeof result.status === "string" ? result.status : "idle",
49509
+ ...typeof result.title === "string" ? { title: result.title } : {},
49510
+ ...activeModal ? { activeModal } : {},
49511
+ syncMode,
49512
+ replaceFrom: Number(result.replaceFrom || 0),
49513
+ totalMessages: Number(result.totalMessages || 0),
49514
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
49515
+ };
49516
+ }
49517
+ buildLiveStatusSnapshot() {
49518
+ return buildStatusSnapshot({
49519
+ allStates: this.components.instanceManager.collectAllStates(),
49520
+ cdpManagers: this.components.cdpManagers,
49521
+ providerLoader: this.components.providerLoader,
49522
+ detectedIdes: this.components.detectedIdes.value.map((ide) => ({
49523
+ ...ide,
49524
+ path: ide.path ?? void 0
49525
+ })),
49526
+ instanceId: `daemon_${loadConfig().machineId || "daemon"}`,
49527
+ version: pkgVersion,
49528
+ profile: "live"
49529
+ });
49530
+ }
49531
+ getHotChatSessionIdsForP2PFlush() {
49532
+ const snapshot = this.buildLiveStatusSnapshot();
49533
+ const active = new Set(
49534
+ snapshot.sessions.filter((session) => ACTIVE_CHAT_POLL_STATUSES.has(String(session.status || "").toLowerCase())).map((session) => session.id)
49535
+ );
49536
+ const finalizing = new Set(
49537
+ Array.from(this.hotP2PChatSessionIds).filter((sessionId) => !active.has(sessionId))
49538
+ );
49539
+ this.hotP2PChatSessionIds = active;
49540
+ return { active, finalizing };
49541
+ }
49542
+ async flushP2PChatSubscriptions(options = {}) {
49543
+ if (!this.p2p?.isConnected || !this.p2p.hasChatSubscriptions()) return;
49544
+ const onlyActive = options.onlyActive === true;
49545
+ if (this.p2pChatFlushInFlight) {
49546
+ this.pendingP2PChatFlush = true;
49547
+ this.pendingP2PChatFlushOnlyActive = this.pendingP2PChatFlushOnlyActive && onlyActive;
49548
+ return;
49549
+ }
49550
+ this.p2pChatFlushInFlight = true;
49551
+ try {
49552
+ const hotSessionIds = onlyActive ? this.getHotChatSessionIdsForP2PFlush() : null;
49553
+ await this.p2p.flushChatSubscriptions(async (subscription) => {
49554
+ if (hotSessionIds && !hotSessionIds.active.has(subscription.params.targetSessionId) && !hotSessionIds.finalizing.has(subscription.params.targetSessionId)) {
49555
+ return null;
49556
+ }
49557
+ return this.buildChatTailUpdateForSubscription(subscription);
49558
+ });
49559
+ } finally {
49560
+ this.p2pChatFlushInFlight = false;
49561
+ if (this.pendingP2PChatFlush) {
49562
+ const pendingOnlyActive = this.pendingP2PChatFlushOnlyActive;
49563
+ this.pendingP2PChatFlush = false;
49564
+ this.pendingP2PChatFlushOnlyActive = true;
49565
+ void this.flushP2PChatSubscriptions({ onlyActive: pendingOnlyActive });
49566
+ }
49567
+ }
49568
+ }
49569
+ buildMachineRuntimeUpdateForSubscription(subscription) {
49570
+ const intervalMs = Math.max(5e3, Number(subscription.params.intervalMs || 15e3));
49571
+ const now = Date.now();
49572
+ if (subscription.lastSentAt > 0 && now - subscription.lastSentAt < intervalMs) {
49573
+ return null;
49574
+ }
49575
+ subscription.seq += 1;
49576
+ subscription.lastSentAt = now;
49577
+ return {
49578
+ topic: "machine.runtime",
49579
+ key: subscription.key,
49580
+ machine: buildMachineInfo("full"),
49581
+ seq: subscription.seq,
49582
+ timestamp: now
49583
+ };
49584
+ }
49585
+ async flushP2PMachineRuntimeSubscriptions() {
49586
+ if (!this.p2p?.isConnected || !this.p2p.hasMachineRuntimeSubscriptions()) return;
49587
+ await this.p2p.flushMachineRuntimeSubscriptions(async (subscription) => this.buildMachineRuntimeUpdateForSubscription(subscription));
49588
+ }
49589
+ async buildSessionHostDiagnosticsUpdateForSubscription(subscription) {
49590
+ if (!this.sessionHostController) return null;
49591
+ const intervalMs = Math.max(5e3, Number(subscription.params.intervalMs || 1e4));
49592
+ const now = Date.now();
49593
+ if (subscription.lastSentAt > 0 && now - subscription.lastSentAt < intervalMs) {
49594
+ return null;
49595
+ }
49596
+ const diagnostics = await this.sessionHostController.getDiagnostics({
49597
+ includeSessions: subscription.params.includeSessions !== false,
49598
+ limit: Number(subscription.params.limit) || void 0
49599
+ });
49600
+ subscription.seq += 1;
49601
+ subscription.lastSentAt = now;
49602
+ return {
49603
+ topic: "session_host.diagnostics",
49604
+ key: subscription.key,
49605
+ diagnostics,
49606
+ seq: subscription.seq,
49607
+ timestamp: now
49608
+ };
49609
+ }
49610
+ async flushP2PSessionHostDiagnosticsSubscriptions() {
49611
+ if (!this.p2p?.isConnected || !this.p2p.hasSessionHostDiagnosticsSubscriptions()) return;
49612
+ await this.p2p.flushSessionHostDiagnosticsSubscriptions(
49613
+ async (subscription) => this.buildSessionHostDiagnosticsUpdateForSubscription(subscription)
49614
+ );
49615
+ }
49616
+ findProviderStateBySessionId(sessionId) {
49617
+ if (!this.components || !sessionId) return null;
49618
+ const states = this.components.instanceManager.collectAllStates();
49619
+ for (const state of states) {
49620
+ if (state.instanceId === sessionId) return state;
49621
+ if (state.category === "ide") {
49622
+ const child = state.extensions.find((entry) => entry.instanceId === sessionId);
49623
+ if (child) return child;
49624
+ }
49625
+ }
49626
+ return null;
49627
+ }
49628
+ buildSessionModalUpdateForSubscription(subscription) {
49629
+ const state = this.findProviderStateBySessionId(subscription.params.targetSessionId);
49630
+ if (!state) return null;
49631
+ const now = Date.now();
49632
+ const activeModal = state.activeChat?.activeModal;
49633
+ const modalButtons = Array.isArray(activeModal?.buttons) ? activeModal.buttons.filter((button) => typeof button === "string") : [];
49634
+ const status = String(state.activeChat?.status || state.status || "idle");
49635
+ const title = typeof state.activeChat?.title === "string" ? state.activeChat.title : void 0;
49636
+ const modalMessage = typeof activeModal?.message === "string" ? activeModal.message : void 0;
49637
+ const deliverySignature = buildSessionModalDeliverySignature({
49638
+ sessionId: subscription.params.targetSessionId,
49639
+ status,
49640
+ ...title ? { title } : {},
49641
+ ...modalMessage ? { modalMessage } : {},
49642
+ ...modalButtons.length > 0 ? { modalButtons } : {}
49643
+ });
49644
+ if (deliverySignature === subscription.lastDeliveredSignature) {
49645
+ return null;
49646
+ }
49647
+ subscription.lastDeliveredSignature = deliverySignature;
49648
+ subscription.seq += 1;
49649
+ subscription.lastSentAt = now;
49650
+ return {
49651
+ topic: "session.modal",
49652
+ key: subscription.key,
49653
+ sessionId: subscription.params.targetSessionId,
49654
+ status,
49655
+ ...title ? { title } : {},
49656
+ ...modalMessage ? { modalMessage } : {},
49657
+ ...modalButtons.length > 0 ? { modalButtons } : {},
49658
+ seq: subscription.seq,
49659
+ timestamp: now
49660
+ };
49661
+ }
49662
+ async flushP2PSessionModalSubscriptions() {
49663
+ if (!this.p2p?.isConnected || !this.p2p.hasSessionModalSubscriptions()) return;
49664
+ await this.p2p.flushSessionModalSubscriptions(
49665
+ async (subscription) => this.buildSessionModalUpdateForSubscription(subscription)
49666
+ );
49667
+ }
49668
+ buildDaemonMetadataSnapshot() {
49669
+ return buildStatusSnapshot({
49670
+ allStates: this.components.instanceManager.collectAllStates(),
49671
+ cdpManagers: this.components.cdpManagers,
49672
+ providerLoader: this.components.providerLoader,
49673
+ detectedIdes: this.components.detectedIdes.value.map((ide) => ({
49674
+ ...ide,
49675
+ path: ide.path ?? void 0
49676
+ })),
49677
+ instanceId: `daemon_${loadConfig().machineId || "daemon"}`,
49678
+ version: pkgVersion,
49679
+ profile: "metadata"
49680
+ });
49681
+ }
49682
+ buildDaemonMetadataUpdateForSubscription(subscription) {
49683
+ const now = Date.now();
49684
+ subscription.seq += 1;
49685
+ subscription.lastSentAt = now;
49686
+ return {
49687
+ topic: "daemon.metadata",
49688
+ key: subscription.key,
49689
+ daemonId: `daemon_${loadConfig().machineId || "daemon"}`,
49690
+ status: this.buildDaemonMetadataSnapshot(),
49691
+ seq: subscription.seq,
49692
+ timestamp: now
49693
+ };
49694
+ }
49695
+ async flushP2PDaemonMetadataSubscriptions() {
49696
+ if (!this.p2p?.isConnected || !this.p2p.hasDaemonMetadataSubscriptions()) return;
49697
+ await this.p2p.flushDaemonMetadataSubscriptions(
49698
+ async (subscription) => this.buildDaemonMetadataUpdateForSubscription(subscription)
49699
+ );
49700
+ }
48885
49701
  async start(options = {}) {
48886
49702
  installGlobalInterceptor();
48887
49703
  process.on("uncaughtException", (err) => {
@@ -48914,9 +49730,14 @@ ${err?.stack || ""}`);
48914
49730
  this.sessionHostEndpoint = sessionHostEndpoint;
48915
49731
  this.sessionHostController = new SessionHostController(
48916
49732
  sessionHostEndpoint,
48917
- (event) => this.broadcastLocalIpcMessage("daemon:session_host_event", event)
49733
+ (event) => {
49734
+ this.broadcastLocalIpcMessage("daemon:session_host_event", event);
49735
+ void this.flushP2PSessionHostDiagnosticsSubscriptions();
49736
+ void this.flushP2PSessionModalSubscriptions();
49737
+ }
48918
49738
  );
48919
49739
  await this.sessionHostController.start();
49740
+ const instanceId = `daemon_${config2.machineId}`;
48920
49741
  this.components = await initDaemonComponents({
48921
49742
  providerLogFn: LOG.forComponent("Provider").asLogFn(),
48922
49743
  cliManagerDeps: {
@@ -48949,6 +49770,8 @@ ${err?.stack || ""}`);
48949
49770
  listHostedCliRuntimes: async () => listHostedCliRuntimes2(sessionHostEndpoint)
48950
49771
  },
48951
49772
  enabledIdes: config2.enabledIdes,
49773
+ statusInstanceId: instanceId,
49774
+ statusVersion: pkgVersion,
48952
49775
  onStatusChange: () => this.statusReporter?.onStatusChange(),
48953
49776
  onPostChatCommand: () => {
48954
49777
  setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
@@ -48974,7 +49797,6 @@ ${err?.stack || ""}`);
48974
49797
  }
48975
49798
  }).catch(() => {
48976
49799
  });
48977
- const instanceId = `daemon_${config2.machineId}`;
48978
49800
  this.serverConn = new ServerConnection({
48979
49801
  serverUrl: options.serverUrl || config2.serverUrl,
48980
49802
  token: authToken,
@@ -49024,6 +49846,13 @@ ${err?.stack || ""}`);
49024
49846
  found.adapter.resize(cols, rows);
49025
49847
  }
49026
49848
  });
49849
+ this.p2p.onSubscriptionChange(() => {
49850
+ void this.flushP2PChatSubscriptions();
49851
+ void this.flushP2PMachineRuntimeSubscriptions();
49852
+ void this.flushP2PSessionHostDiagnosticsSubscriptions();
49853
+ void this.flushP2PSessionModalSubscriptions();
49854
+ void this.flushP2PDaemonMetadataSubscriptions();
49855
+ });
49027
49856
  this.p2p.onStateChange((state) => {
49028
49857
  if (state === "connected") {
49029
49858
  LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
@@ -49040,18 +49869,24 @@ ${err?.stack || ""}`);
49040
49869
  this.screenshotController = new ScreenshotController({
49041
49870
  isRunning: () => this.running,
49042
49871
  isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
49043
- getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
49872
+ getScreenshotTargetSessionId: () => this.p2p?.screenshotTargetSessionId,
49044
49873
  isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
49045
49874
  hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
49046
- getCdp: (ideType) => {
49047
- if (ideType) return this.getCdpFor(ideType);
49048
- LOG.warn("P2P", "Screenshot requested without ideType \u2014 cannot determine target IDE. Skipping frame.");
49875
+ getCdp: (targetSessionId) => {
49876
+ if (targetSessionId) return this.getCdpFor(targetSessionId);
49877
+ LOG.warn("P2P", "Screenshot requested without targetSessionId \u2014 cannot determine target session. Skipping frame.");
49049
49878
  return null;
49050
49879
  },
49051
49880
  sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
49052
49881
  }, planLimits ?? void 0);
49053
49882
  this.screenshotController.start();
49054
49883
  this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
49884
+ this.topicSubscriptionTimer = setInterval(() => {
49885
+ void this.flushP2PChatSubscriptions({ onlyActive: true });
49886
+ void this.flushP2PMachineRuntimeSubscriptions();
49887
+ void this.flushP2PSessionHostDiagnosticsSubscriptions();
49888
+ void this.flushP2PSessionModalSubscriptions();
49889
+ }, 2500);
49055
49890
  } else {
49056
49891
  console.log(import_chalk2.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
49057
49892
  }
@@ -49156,10 +49991,26 @@ ${err?.stack || ""}`);
49156
49991
  async handleCommand(msg, cmd, args) {
49157
49992
  LOG.info("Command", `${cmd}${args?.targetSessionId ? ` \u2192 session:${String(args.targetSessionId).split("_")[0]}` : ""}`);
49158
49993
  const cmdStart = Date.now();
49159
- const source = msg.ipcWs ? "ext" : "ws";
49994
+ const source = msg.ipcWs ? "ext" : typeof msg.source === "string" && msg.source.trim() ? msg.source : "ws";
49160
49995
  try {
49996
+ if (source === "api" && !loadConfig().allowServerApiProxy) {
49997
+ this.sendResult(msg, false, {
49998
+ error: "Server API relay is disabled on this daemon. Enable it explicitly with `adhdev daemon:api enable`.",
49999
+ code: "SERVER_API_DISABLED"
50000
+ });
50001
+ return;
50002
+ }
49161
50003
  const result = await this.components.router.execute(cmd, args, source);
49162
50004
  if (cmd.startsWith("workspace_")) this.statusReporter?.throttledReport();
50005
+ if (cmd === "get_status_metadata" || cmd.startsWith("workspace_") || cmd.startsWith("session_host_")) {
50006
+ void this.flushP2PDaemonMetadataSubscriptions();
50007
+ }
50008
+ if (cmd.startsWith("session_host_")) {
50009
+ void this.flushP2PSessionHostDiagnosticsSubscriptions();
50010
+ }
50011
+ if (cmd === "resolve_action" || cmd === "send_chat" || cmd === "read_chat") {
50012
+ void this.flushP2PSessionModalSubscriptions();
50013
+ }
49163
50014
  this.sendResult(msg, result.success, result);
49164
50015
  } catch (e) {
49165
50016
  console.error(import_chalk2.default.red(` \u2717 Command failed: ${e.message}`));
@@ -49199,6 +50050,7 @@ ${err?.stack || ""}`);
49199
50050
  const config2 = loadConfig();
49200
50051
  config2.machineNickname = nickname;
49201
50052
  saveConfig(config2);
50053
+ void this.flushP2PDaemonMetadataSubscriptions();
49202
50054
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", args: { nickname }, success: true, durationMs: Date.now() - cmdStart });
49203
50055
  return { success: true, nickname };
49204
50056
  }
@@ -49211,6 +50063,15 @@ ${err?.stack || ""}`);
49211
50063
  }
49212
50064
  const routed = await this.components.router.execute(cmdType, data, "p2p");
49213
50065
  if (cmdType.startsWith("workspace_")) this.statusReporter?.throttledReport();
50066
+ if (cmdType === "get_status_metadata" || cmdType.startsWith("workspace_") || cmdType.startsWith("session_host_")) {
50067
+ void this.flushP2PDaemonMetadataSubscriptions();
50068
+ }
50069
+ if (cmdType.startsWith("session_host_")) {
50070
+ void this.flushP2PSessionHostDiagnosticsSubscriptions();
50071
+ }
50072
+ if (cmdType === "resolve_action" || cmdType === "send_chat" || cmdType === "read_chat") {
50073
+ void this.flushP2PSessionModalSubscriptions();
50074
+ }
49214
50075
  return routed;
49215
50076
  } catch (e) {
49216
50077
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: false, error: e.message, durationMs: Date.now() - cmdStart });
@@ -49383,6 +50244,10 @@ ${err?.stack || ""}`);
49383
50244
  this.statusReporter.stopReporting();
49384
50245
  this.statusReporter = null;
49385
50246
  }
50247
+ if (this.topicSubscriptionTimer) {
50248
+ clearInterval(this.topicSubscriptionTimer);
50249
+ this.topicSubscriptionTimer = null;
50250
+ }
49386
50251
  if (this.components) {
49387
50252
  await shutdownDaemonComponents(this.components);
49388
50253
  }