@adhdev/daemon-standalone 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
@@ -27843,6 +27843,7 @@ var require_dist2 = __commonJS({
27843
27843
  const parsed = isPlainObject2(raw) ? raw : {};
27844
27844
  return {
27845
27845
  serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
27846
+ allowServerApiProxy: asBoolean(parsed.allowServerApiProxy, DEFAULT_CONFIG.allowServerApiProxy ?? false),
27846
27847
  selectedIde: asNullableString(parsed.selectedIde),
27847
27848
  configuredIdes: asStringArray(parsed.configuredIdes),
27848
27849
  installedExtensions: asStringArray(parsed.installedExtensions),
@@ -27996,6 +27997,7 @@ var require_dist2 = __commonJS({
27996
27997
  import_crypto2 = require("crypto");
27997
27998
  DEFAULT_CONFIG = {
27998
27999
  serverUrl: "https://api.adhf.dev",
28000
+ allowServerApiProxy: false,
27999
28001
  selectedIde: null,
28000
28002
  configuredIdes: [],
28001
28003
  installedExtensions: [],
@@ -30819,6 +30821,7 @@ ${data.message || ""}`.trim();
30819
30821
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
30820
30822
  VersionArchive: () => VersionArchive,
30821
30823
  appendRecentActivity: () => appendRecentActivity,
30824
+ buildMachineInfo: () => buildMachineInfo2,
30822
30825
  buildSessionEntries: () => buildSessionEntries,
30823
30826
  buildStatusSnapshot: () => buildStatusSnapshot2,
30824
30827
  connectCdpManager: () => connectCdpManager,
@@ -34736,11 +34739,24 @@ ${effect.notification.body || ""}`.trim();
34736
34739
  "thinking",
34737
34740
  "active"
34738
34741
  ]);
34739
- var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
34740
- var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
34741
- var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
34742
- var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
34743
- var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
34742
+ var FULL_STATUS_ACTIVE_CHAT_OPTIONS = {
34743
+ includeMessages: true,
34744
+ includeInputContent: true,
34745
+ includeActiveModal: true,
34746
+ messageLimit: 60,
34747
+ totalBytesLimit: 96 * 1024,
34748
+ stringLimit: 4 * 1024,
34749
+ fallbackStringLimit: 1024
34750
+ };
34751
+ var LIVE_STATUS_ACTIVE_CHAT_OPTIONS = {
34752
+ includeMessages: false,
34753
+ includeInputContent: false,
34754
+ includeActiveModal: false,
34755
+ messageLimit: 0,
34756
+ totalBytesLimit: 0,
34757
+ stringLimit: 512,
34758
+ fallbackStringLimit: 256
34759
+ };
34744
34760
  var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
34745
34761
  var STATUS_MODAL_BUTTON_LIMIT = 120;
34746
34762
  function truncateString(value, maxChars) {
@@ -34779,19 +34795,20 @@ ${effect.notification.body || ""}`.trim();
34779
34795
  }
34780
34796
  return msg;
34781
34797
  }
34782
- function trimMessagesForStatus(messages) {
34798
+ function trimMessagesForStatus(messages, options) {
34799
+ if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];
34783
34800
  if (!Array.isArray(messages) || messages.length === 0) return [];
34784
- const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
34801
+ const recent = messages.slice(-options.messageLimit);
34785
34802
  const kept = [];
34786
34803
  let totalBytes = 0;
34787
34804
  for (let i = recent.length - 1; i >= 0; i -= 1) {
34788
- let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT));
34805
+ let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));
34789
34806
  let size = estimateBytes(normalized);
34790
- if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
34791
- normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT));
34807
+ if (size > options.totalBytesLimit) {
34808
+ normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));
34792
34809
  size = estimateBytes(normalized);
34793
34810
  }
34794
- if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
34811
+ if (kept.length > 0 && totalBytes + size > options.totalBytesLimit) {
34795
34812
  continue;
34796
34813
  }
34797
34814
  kept.push(normalized);
@@ -34821,21 +34838,38 @@ ${effect.notification.body || ""}`.trim();
34821
34838
  function isManagedStatusWaiting(status, opts) {
34822
34839
  return normalizeManagedStatus(status, opts) === "waiting_approval";
34823
34840
  }
34824
- function normalizeActiveChatData(activeChat) {
34841
+ function normalizeActiveChatData(activeChat, options = FULL_STATUS_ACTIVE_CHAT_OPTIONS) {
34825
34842
  if (!activeChat) return activeChat;
34843
+ const resolvedOptions = {
34844
+ ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,
34845
+ ...options
34846
+ };
34826
34847
  return {
34827
34848
  ...activeChat,
34828
34849
  status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
34829
- messages: trimMessagesForStatus(activeChat.messages),
34830
- activeModal: activeChat.activeModal ? {
34850
+ messages: trimMessagesForStatus(activeChat.messages, resolvedOptions),
34851
+ activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {
34831
34852
  message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
34832
34853
  buttons: (activeChat.activeModal.buttons || []).map(
34833
34854
  (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
34834
34855
  )
34835
- } : activeChat.activeModal,
34836
- inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
34856
+ } : null,
34857
+ inputContent: resolvedOptions.includeInputContent && activeChat.inputContent ? truncateString(activeChat.inputContent, 2 * 1024) : void 0
34837
34858
  };
34838
34859
  }
34860
+ function getActiveChatOptions(profile) {
34861
+ if (profile === "full") return {};
34862
+ return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
34863
+ }
34864
+ function shouldIncludeSessionControls(profile) {
34865
+ return profile !== "live";
34866
+ }
34867
+ function shouldIncludeSessionMetadata(profile) {
34868
+ return profile !== "live";
34869
+ }
34870
+ function shouldIncludeRuntimeMetadata(profile) {
34871
+ return profile !== "live";
34872
+ }
34839
34873
  function findCdpManager(cdpManagers, key) {
34840
34874
  const exact = cdpManagers.get(key);
34841
34875
  if (exact) return exact;
@@ -34943,74 +34977,88 @@ ${effect.notification.body || ""}`.trim();
34943
34977
  "set_mode",
34944
34978
  "set_thought_level"
34945
34979
  ];
34946
- function buildIdeWorkspaceSession(state, cdpManagers) {
34947
- const activeChat = normalizeActiveChatData(state.activeChat);
34980
+ function buildIdeWorkspaceSession(state, cdpManagers, options) {
34981
+ const profile = options.profile || "full";
34982
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
34983
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
34984
+ const includeSessionControls = shouldIncludeSessionControls(profile);
34948
34985
  const title = activeChat?.title || state.name;
34949
34986
  return {
34950
34987
  id: state.instanceId || state.type,
34951
34988
  parentId: null,
34952
34989
  providerType: state.type,
34953
- providerName: state.name,
34990
+ ...includeSessionMetadata && { providerName: state.name },
34954
34991
  kind: "workspace",
34955
34992
  transport: "cdp-page",
34956
34993
  status: normalizeManagedStatus(activeChat?.status || state.status, {
34957
34994
  activeModal: activeChat?.activeModal || null
34958
34995
  }),
34959
34996
  title,
34960
- workspace: state.workspace || null,
34997
+ ...includeSessionMetadata && { workspace: state.workspace || null },
34961
34998
  activeChat,
34962
- capabilities: IDE_SESSION_CAPABILITIES,
34999
+ ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
34963
35000
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
34964
35001
  currentModel: state.currentModel,
34965
35002
  currentPlan: state.currentPlan,
34966
35003
  currentAutoApprove: state.currentAutoApprove,
34967
- controlValues: state.controlValues,
34968
- providerControls: buildFallbackControls(
34969
- state.providerControls,
34970
- state.currentModel,
34971
- state.currentPlan
34972
- ),
35004
+ ...includeSessionControls && {
35005
+ controlValues: state.controlValues,
35006
+ providerControls: buildFallbackControls(
35007
+ state.providerControls,
35008
+ state.currentModel,
35009
+ state.currentPlan
35010
+ )
35011
+ },
34973
35012
  errorMessage: state.errorMessage,
34974
35013
  errorReason: state.errorReason,
34975
35014
  lastUpdated: state.lastUpdated
34976
35015
  };
34977
35016
  }
34978
- function buildExtensionAgentSession(parent, ext) {
34979
- const activeChat = normalizeActiveChatData(ext.activeChat);
35017
+ function buildExtensionAgentSession(parent, ext, options) {
35018
+ const profile = options.profile || "full";
35019
+ const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
35020
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
35021
+ const includeSessionControls = shouldIncludeSessionControls(profile);
34980
35022
  return {
34981
35023
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
34982
35024
  parentId: parent.instanceId || parent.type,
34983
35025
  providerType: ext.type,
34984
- providerName: ext.name,
35026
+ ...includeSessionMetadata && { providerName: ext.name },
34985
35027
  kind: "agent",
34986
35028
  transport: "cdp-webview",
34987
35029
  status: normalizeManagedStatus(activeChat?.status || ext.status, {
34988
35030
  activeModal: activeChat?.activeModal || null
34989
35031
  }),
34990
35032
  title: activeChat?.title || ext.name,
34991
- workspace: parent.workspace || null,
35033
+ ...includeSessionMetadata && { workspace: parent.workspace || null },
34992
35034
  activeChat,
34993
- capabilities: EXTENSION_SESSION_CAPABILITIES,
35035
+ ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
34994
35036
  currentModel: ext.currentModel,
34995
35037
  currentPlan: ext.currentPlan,
34996
- controlValues: ext.controlValues,
34997
- providerControls: buildFallbackControls(
34998
- ext.providerControls,
34999
- ext.currentModel,
35000
- ext.currentPlan
35001
- ),
35038
+ ...includeSessionControls && {
35039
+ controlValues: ext.controlValues,
35040
+ providerControls: buildFallbackControls(
35041
+ ext.providerControls,
35042
+ ext.currentModel,
35043
+ ext.currentPlan
35044
+ )
35045
+ },
35002
35046
  errorMessage: ext.errorMessage,
35003
35047
  errorReason: ext.errorReason,
35004
35048
  lastUpdated: ext.lastUpdated
35005
35049
  };
35006
35050
  }
35007
- function buildCliSession(state) {
35008
- const activeChat = normalizeActiveChatData(state.activeChat);
35051
+ function buildCliSession(state, options) {
35052
+ const profile = options.profile || "full";
35053
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
35054
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
35055
+ const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
35056
+ const includeSessionControls = shouldIncludeSessionControls(profile);
35009
35057
  return {
35010
35058
  id: state.instanceId,
35011
35059
  parentId: null,
35012
35060
  providerType: state.type,
35013
- providerName: state.name,
35061
+ ...includeSessionMetadata && { providerName: state.name },
35014
35062
  providerSessionId: state.providerSessionId,
35015
35063
  kind: "agent",
35016
35064
  transport: "pty",
@@ -35018,74 +35066,85 @@ ${effect.notification.body || ""}`.trim();
35018
35066
  activeModal: activeChat?.activeModal || null
35019
35067
  }),
35020
35068
  title: activeChat?.title || state.name,
35021
- workspace: state.workspace || null,
35022
- runtimeKey: state.runtime?.runtimeKey,
35023
- runtimeDisplayName: state.runtime?.displayName,
35024
- runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
35025
- runtimeWriteOwner: state.runtime?.writeOwner || null,
35026
- runtimeAttachedClients: state.runtime?.attachedClients || [],
35069
+ ...includeSessionMetadata && { workspace: state.workspace || null },
35070
+ ...includeRuntimeMetadata && {
35071
+ runtimeKey: state.runtime?.runtimeKey,
35072
+ runtimeDisplayName: state.runtime?.displayName,
35073
+ runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
35074
+ runtimeWriteOwner: state.runtime?.writeOwner || null,
35075
+ runtimeAttachedClients: state.runtime?.attachedClients || []
35076
+ },
35027
35077
  mode: state.mode,
35028
35078
  resume: state.resume,
35029
35079
  activeChat,
35030
- capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
35031
- controlValues: state.controlValues,
35032
- providerControls: buildFallbackControls(
35033
- state.providerControls
35034
- ),
35080
+ ...includeSessionMetadata && {
35081
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
35082
+ },
35083
+ ...includeSessionControls && {
35084
+ controlValues: state.controlValues,
35085
+ providerControls: buildFallbackControls(
35086
+ state.providerControls
35087
+ )
35088
+ },
35035
35089
  errorMessage: state.errorMessage,
35036
35090
  errorReason: state.errorReason,
35037
35091
  lastUpdated: state.lastUpdated
35038
35092
  };
35039
35093
  }
35040
- function buildAcpSession(state) {
35041
- const activeChat = normalizeActiveChatData(state.activeChat);
35094
+ function buildAcpSession(state, options) {
35095
+ const profile = options.profile || "full";
35096
+ const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
35097
+ const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
35098
+ const includeSessionControls = shouldIncludeSessionControls(profile);
35042
35099
  return {
35043
35100
  id: state.instanceId,
35044
35101
  parentId: null,
35045
35102
  providerType: state.type,
35046
- providerName: state.name,
35103
+ ...includeSessionMetadata && { providerName: state.name },
35047
35104
  kind: "agent",
35048
35105
  transport: "acp",
35049
35106
  status: normalizeManagedStatus(activeChat?.status || state.status, {
35050
35107
  activeModal: activeChat?.activeModal || null
35051
35108
  }),
35052
35109
  title: activeChat?.title || state.name,
35053
- workspace: state.workspace || null,
35110
+ ...includeSessionMetadata && { workspace: state.workspace || null },
35054
35111
  activeChat,
35055
- capabilities: ACP_SESSION_CAPABILITIES,
35112
+ ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
35056
35113
  currentModel: state.currentModel,
35057
35114
  currentPlan: state.currentPlan,
35058
- acpConfigOptions: state.acpConfigOptions,
35059
- acpModes: state.acpModes,
35060
- controlValues: state.controlValues,
35061
- providerControls: buildFallbackControls(
35062
- state.providerControls,
35063
- state.currentModel,
35064
- state.currentPlan,
35065
- state.acpConfigOptions,
35066
- state.acpModes
35067
- ),
35115
+ ...includeSessionControls && {
35116
+ acpConfigOptions: state.acpConfigOptions,
35117
+ acpModes: state.acpModes,
35118
+ controlValues: state.controlValues,
35119
+ providerControls: buildFallbackControls(
35120
+ state.providerControls,
35121
+ state.currentModel,
35122
+ state.currentPlan,
35123
+ state.acpConfigOptions,
35124
+ state.acpModes
35125
+ )
35126
+ },
35068
35127
  errorMessage: state.errorMessage,
35069
35128
  errorReason: state.errorReason,
35070
35129
  lastUpdated: state.lastUpdated
35071
35130
  };
35072
35131
  }
35073
- function buildSessionEntries(allStates, cdpManagers) {
35132
+ function buildSessionEntries(allStates, cdpManagers, options = {}) {
35074
35133
  const sessions = [];
35075
35134
  const ideStates = allStates.filter((s15) => s15.category === "ide");
35076
35135
  const cliStates = allStates.filter((s15) => s15.category === "cli");
35077
35136
  const acpStates = allStates.filter((s15) => s15.category === "acp");
35078
35137
  for (const state of ideStates) {
35079
- sessions.push(buildIdeWorkspaceSession(state, cdpManagers));
35138
+ sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
35080
35139
  for (const ext of state.extensions) {
35081
- sessions.push(buildExtensionAgentSession(state, ext));
35140
+ sessions.push(buildExtensionAgentSession(state, ext, options));
35082
35141
  }
35083
35142
  }
35084
35143
  for (const state of cliStates) {
35085
- sessions.push(buildCliSession(state));
35144
+ sessions.push(buildCliSession(state, options));
35086
35145
  }
35087
35146
  for (const state of acpStates) {
35088
- sessions.push(buildAcpSession(state));
35147
+ sessions.push(buildAcpSession(state, options));
35089
35148
  }
35090
35149
  const extensionParentIds = new Set(
35091
35150
  sessions.filter((session) => session.transport === "cdp-webview" && !!session.parentId).map((session) => session.parentId)
@@ -35141,9 +35200,26 @@ ${effect.notification.body || ""}`.trim();
35141
35200
  }
35142
35201
  }
35143
35202
  init_logger();
35203
+ function flattenContent(content) {
35204
+ if (typeof content === "string") return content;
35205
+ return content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("\n");
35206
+ }
35144
35207
  init_logger();
35145
35208
  var RECENT_SEND_WINDOW_MS = 1200;
35146
35209
  var recentSendByTarget = /* @__PURE__ */ new Map();
35210
+ function hashSignatureParts2(parts) {
35211
+ let hash2 = 2166136261;
35212
+ for (const part of parts) {
35213
+ const text = String(part || "");
35214
+ for (let i = 0; i < text.length; i += 1) {
35215
+ hash2 ^= text.charCodeAt(i);
35216
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
35217
+ }
35218
+ hash2 ^= 255;
35219
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
35220
+ }
35221
+ return hash2.toString(16).padStart(8, "0");
35222
+ }
35147
35223
  function getCurrentProviderType(h, fallback = "") {
35148
35224
  return h.currentSession?.providerType || h.currentProviderType || fallback;
35149
35225
  }
@@ -35217,6 +35293,134 @@ ${effect.notification.body || ""}`.trim();
35217
35293
  return value;
35218
35294
  }
35219
35295
  }
35296
+ function getChatMessageSignature(message) {
35297
+ if (!message) return "";
35298
+ let content = "";
35299
+ try {
35300
+ content = JSON.stringify(message.content ?? "");
35301
+ } catch {
35302
+ content = String(message.content ?? "");
35303
+ }
35304
+ return hashSignatureParts2([
35305
+ String(message.id || ""),
35306
+ String(message.index ?? ""),
35307
+ String(message.role || ""),
35308
+ String(message.receivedAt ?? message.timestamp ?? ""),
35309
+ content
35310
+ ]);
35311
+ }
35312
+ function normalizeReadChatCursor(args) {
35313
+ const knownMessageCount = Math.max(0, Number(args?.knownMessageCount || 0));
35314
+ const lastMessageSignature = typeof args?.lastMessageSignature === "string" ? args.lastMessageSignature : "";
35315
+ const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
35316
+ return { knownMessageCount, lastMessageSignature, tailLimit };
35317
+ }
35318
+ function normalizeReadChatMessages(payload) {
35319
+ const messages = Array.isArray(payload.messages) ? payload.messages : [];
35320
+ return messages;
35321
+ }
35322
+ function deriveHistoryDedupKey(message) {
35323
+ const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
35324
+ if (unitKey) return `read_chat:${unitKey}`;
35325
+ const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
35326
+ if (!turnKey) return void 0;
35327
+ let content = "";
35328
+ try {
35329
+ content = JSON.stringify(message.content ?? "");
35330
+ } catch {
35331
+ content = String(message.content ?? "");
35332
+ }
35333
+ return `read_chat:${turnKey}:${String(message.role || "").toLowerCase()}:${content}`;
35334
+ }
35335
+ function toHistoryPersistedMessages(messages) {
35336
+ return messages.map((message) => ({
35337
+ role: message.role,
35338
+ content: flattenContent(message.content),
35339
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : void 0,
35340
+ kind: typeof message.kind === "string" ? message.kind : void 0,
35341
+ senderName: typeof message.senderName === "string" ? message.senderName : void 0,
35342
+ historyDedupKey: deriveHistoryDedupKey(message)
35343
+ }));
35344
+ }
35345
+ function computeReadChatSync(messages, cursor) {
35346
+ const totalMessages = messages.length;
35347
+ const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
35348
+ const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
35349
+ if (!knownMessageCount || !knownSignature) {
35350
+ return {
35351
+ syncMode: "full",
35352
+ replaceFrom: 0,
35353
+ messages,
35354
+ totalMessages,
35355
+ lastMessageSignature
35356
+ };
35357
+ }
35358
+ if (knownMessageCount > totalMessages) {
35359
+ return {
35360
+ syncMode: "full",
35361
+ replaceFrom: 0,
35362
+ messages,
35363
+ totalMessages,
35364
+ lastMessageSignature
35365
+ };
35366
+ }
35367
+ if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
35368
+ return {
35369
+ syncMode: "noop",
35370
+ replaceFrom: totalMessages,
35371
+ messages: [],
35372
+ totalMessages,
35373
+ lastMessageSignature
35374
+ };
35375
+ }
35376
+ if (knownMessageCount < totalMessages) {
35377
+ const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
35378
+ if (anchorSignature === knownSignature) {
35379
+ return {
35380
+ syncMode: "append",
35381
+ replaceFrom: knownMessageCount,
35382
+ messages: messages.slice(knownMessageCount),
35383
+ totalMessages,
35384
+ lastMessageSignature
35385
+ };
35386
+ }
35387
+ }
35388
+ const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
35389
+ return {
35390
+ syncMode: replaceFrom === 0 ? "full" : "replace_tail",
35391
+ replaceFrom,
35392
+ messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
35393
+ totalMessages,
35394
+ lastMessageSignature
35395
+ };
35396
+ }
35397
+ function buildReadChatCommandResult(payload, args) {
35398
+ const messages = normalizeReadChatMessages(payload);
35399
+ const cursor = normalizeReadChatCursor(args);
35400
+ if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
35401
+ const tailMessages = messages.slice(-cursor.tailLimit);
35402
+ const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
35403
+ return {
35404
+ success: true,
35405
+ ...payload,
35406
+ messages: tailMessages,
35407
+ syncMode: "full",
35408
+ replaceFrom: 0,
35409
+ totalMessages: messages.length,
35410
+ lastMessageSignature
35411
+ };
35412
+ }
35413
+ const sync = computeReadChatSync(messages, cursor);
35414
+ return {
35415
+ success: true,
35416
+ ...payload,
35417
+ messages: sync.messages,
35418
+ syncMode: sync.syncMode,
35419
+ replaceFrom: sync.replaceFrom,
35420
+ totalMessages: sync.totalMessages,
35421
+ lastMessageSignature: sync.lastMessageSignature
35422
+ };
35423
+ }
35220
35424
  function didProviderConfirmSend(result) {
35221
35425
  const parsed = parseMaybeJson(result);
35222
35426
  if (parsed === true) return true;
@@ -35290,12 +35494,11 @@ ${effect.notification.body || ""}`.trim();
35290
35494
  _log(`${transport} adapter: ${adapter.cliType}`);
35291
35495
  const status = adapter.getStatus();
35292
35496
  if (status) {
35293
- return {
35294
- success: true,
35497
+ return buildReadChatCommandResult({
35295
35498
  messages: status.messages || [],
35296
35499
  status: status.status,
35297
35500
  activeModal: status.activeModal
35298
- };
35501
+ }, args);
35299
35502
  }
35300
35503
  }
35301
35504
  return { success: false, error: `${transport} adapter not found` };
@@ -35315,12 +35518,12 @@ ${effect.notification.body || ""}`.trim();
35315
35518
  _log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
35316
35519
  h.historyWriter.appendNewMessages(
35317
35520
  provider?.type || "unknown_extension",
35318
- parsed.messages || [],
35521
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
35319
35522
  parsed.title,
35320
35523
  args?.targetSessionId,
35321
35524
  historySessionId
35322
35525
  );
35323
- return { success: true, ...parsed };
35526
+ return buildReadChatCommandResult(parsed, args);
35324
35527
  }
35325
35528
  }
35326
35529
  } catch (e) {
@@ -35332,21 +35535,25 @@ ${effect.notification.body || ""}`.trim();
35332
35535
  if (cdp2 && parentSessionId) {
35333
35536
  const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
35334
35537
  if (stream?.agentType !== provider?.type) {
35335
- return { success: true, messages: [], status: "idle" };
35538
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
35336
35539
  }
35337
35540
  if (stream) {
35338
35541
  h.historyWriter.appendNewMessages(
35339
35542
  stream.agentType,
35340
- stream.messages || [],
35543
+ toHistoryPersistedMessages(stream.messages || []),
35341
35544
  void 0,
35342
35545
  args?.targetSessionId,
35343
35546
  historySessionId
35344
35547
  );
35345
- return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
35548
+ return buildReadChatCommandResult({
35549
+ messages: stream.messages || [],
35550
+ status: stream.status,
35551
+ agentType: stream.agentType
35552
+ }, args);
35346
35553
  }
35347
35554
  }
35348
35555
  }
35349
- return { success: true, messages: [], status: "idle" };
35556
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
35350
35557
  }
35351
35558
  const cdp = h.getCdp();
35352
35559
  if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
@@ -35368,18 +35575,18 @@ ${effect.notification.body || ""}`.trim();
35368
35575
  _log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
35369
35576
  h.historyWriter.appendNewMessages(
35370
35577
  provider?.type || getCurrentProviderType(h, "unknown_webview"),
35371
- parsed.messages || [],
35578
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
35372
35579
  parsed.title,
35373
35580
  args?.targetSessionId,
35374
35581
  historySessionId
35375
35582
  );
35376
- return { success: true, ...parsed };
35583
+ return buildReadChatCommandResult(parsed, args);
35377
35584
  }
35378
35585
  }
35379
35586
  } catch (e) {
35380
35587
  _log(`Webview readChat error: ${e.message}`);
35381
35588
  }
35382
- return { success: true, messages: [], status: "idle" };
35589
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
35383
35590
  }
35384
35591
  const script = h.getProviderScript("readChat") || h.getProviderScript("read_chat");
35385
35592
  if (script) {
@@ -35396,18 +35603,18 @@ ${effect.notification.body || ""}`.trim();
35396
35603
  _log(`OK: ${parsed.messages?.length} msgs`);
35397
35604
  h.historyWriter.appendNewMessages(
35398
35605
  provider?.type || getCurrentProviderType(h, "unknown_ide"),
35399
- parsed.messages || [],
35606
+ toHistoryPersistedMessages(normalizeReadChatMessages(parsed)),
35400
35607
  parsed.title,
35401
35608
  args?.targetSessionId,
35402
35609
  historySessionId
35403
35610
  );
35404
- return { success: true, ...parsed };
35611
+ return buildReadChatCommandResult(parsed, args);
35405
35612
  }
35406
35613
  } catch (e) {
35407
35614
  LOG2.info("Command", `[read_chat] Script error: ${e.message}`);
35408
35615
  }
35409
35616
  }
35410
- return { success: true, messages: [], status: "idle" };
35617
+ return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
35411
35618
  }
35412
35619
  async function handleSendChat(h, args) {
35413
35620
  const text = args?.text || args?.message;
@@ -36524,21 +36731,21 @@ ${effect.notification.body || ""}`.trim();
36524
36731
  });
36525
36732
  }
36526
36733
  async function executeProviderScript(h, args, scriptName) {
36527
- const { agentType, ideType } = args || {};
36528
- if (!agentType) return { success: false, error: "agentType is required" };
36734
+ const resolvedProviderType = h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
36735
+ if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
36529
36736
  const loader = h.ctx.providerLoader;
36530
36737
  if (!loader) return { success: false, error: "ProviderLoader not initialized" };
36531
- const provider = loader.resolve(agentType);
36532
- if (!provider) return { success: false, error: `Provider not found: ${agentType}` };
36738
+ const provider = loader.resolve(resolvedProviderType);
36739
+ if (!provider) return { success: false, error: `Provider not found: ${resolvedProviderType}` };
36533
36740
  const webviewScriptName = `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`;
36534
36741
  const hasWebviewScript = provider.category === "ide" && !!provider.scripts?.[webviewScriptName];
36535
36742
  const actualScriptName = hasWebviewScript ? webviewScriptName : scriptName;
36536
36743
  if (!provider.scripts?.[actualScriptName]) {
36537
- return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
36744
+ return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
36538
36745
  }
36539
36746
  const normalizedArgs = normalizeProviderScriptArgs(args);
36540
36747
  if (provider.category === "cli") {
36541
- const adapter = h.getCliAdapter(args?.targetSessionId || agentType);
36748
+ const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
36542
36749
  if (!adapter?.invokeScript) {
36543
36750
  return { success: false, error: `CLI adapter does not support script '${actualScriptName}'` };
36544
36751
  }
@@ -36563,7 +36770,7 @@ ${effect.notification.body || ""}`.trim();
36563
36770
  const scriptFn = provider.scripts[actualScriptName];
36564
36771
  const scriptCode = scriptFn(normalizedArgs);
36565
36772
  if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
36566
- const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
36773
+ const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
36567
36774
  LOG2.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
36568
36775
  const cdp = h.getCdp(cdpKey);
36569
36776
  if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
@@ -36571,7 +36778,7 @@ ${effect.notification.body || ""}`.trim();
36571
36778
  let result;
36572
36779
  if (provider.category === "extension") {
36573
36780
  const runtimeSessionId = h.currentSession?.sessionId || args?.targetSessionId;
36574
- if (!runtimeSessionId) return { success: false, error: `No target session found for ${agentType}` };
36781
+ if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
36575
36782
  const parentSessionId = h.currentSession?.parentSessionId;
36576
36783
  if (parentSessionId) {
36577
36784
  await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
@@ -36600,7 +36807,7 @@ ${effect.notification.body || ""}`.trim();
36600
36807
  }
36601
36808
  } else {
36602
36809
  if (!targetSessionId) {
36603
- return { success: false, error: `No active session found for ${agentType}` };
36810
+ return { success: false, error: `No active session found for ${resolvedProviderType}` };
36604
36811
  }
36605
36812
  result = await cdp.evaluateInSessionFrame(targetSessionId, scriptCode);
36606
36813
  }
@@ -37973,10 +38180,6 @@ ${effect.notification.body || ""}`.trim();
37973
38180
  var import_stream = require("stream");
37974
38181
  var import_child_process5 = require("child_process");
37975
38182
  var import_sdk = (init_acp(), __toCommonJS(acp_exports));
37976
- function flattenContent(content) {
37977
- if (typeof content === "string") return content;
37978
- return content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("\n");
37979
- }
37980
38183
  init_logger();
37981
38184
  var AcpProviderInstance = class {
37982
38185
  constructor(provider, workingDir, cliArgs = []) {
@@ -41326,6 +41529,37 @@ Run 'adhdev doctor' for detailed diagnostics.`
41326
41529
  ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
41327
41530
  }));
41328
41531
  }
41532
+ function buildMachineInfo2(profile = "full") {
41533
+ const base = {
41534
+ hostname: os16.hostname(),
41535
+ platform: os16.platform()
41536
+ };
41537
+ if (profile === "live") {
41538
+ return base;
41539
+ }
41540
+ if (profile === "metadata") {
41541
+ const memSnap2 = getHostMemorySnapshot();
41542
+ return {
41543
+ ...base,
41544
+ arch: os16.arch(),
41545
+ cpus: os16.cpus().length,
41546
+ totalMem: memSnap2.totalMem,
41547
+ release: os16.release()
41548
+ };
41549
+ }
41550
+ const memSnap = getHostMemorySnapshot();
41551
+ return {
41552
+ ...base,
41553
+ arch: os16.arch(),
41554
+ cpus: os16.cpus().length,
41555
+ totalMem: memSnap.totalMem,
41556
+ freeMem: memSnap.freeMem,
41557
+ availableMem: memSnap.availableMem,
41558
+ loadavg: os16.loadavg(),
41559
+ uptime: os16.uptime(),
41560
+ release: os16.release()
41561
+ };
41562
+ }
41329
41563
  function parseMessageTime(value) {
41330
41564
  if (typeof value === "number" && Number.isFinite(value)) return value;
41331
41565
  if (typeof value === "string") {
@@ -41381,26 +41615,35 @@ Run 'adhdev doctor' for detailed diagnostics.`
41381
41615
  })).sort((a, b2) => b2.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
41382
41616
  }
41383
41617
  function buildStatusSnapshot2(options) {
41618
+ const profile = options.profile || "full";
41384
41619
  const cfg = loadConfig2();
41385
41620
  const state = loadState();
41386
41621
  const wsState = getWorkspaceState2(cfg);
41387
- const memSnap = getHostMemorySnapshot();
41388
41622
  const recentActivity = getRecentActivity(state, 20);
41389
- const sessions = buildSessionEntries(
41623
+ const unreadSourceSessions = buildSessionEntries(
41390
41624
  options.allStates,
41391
- options.cdpManagers
41625
+ options.cdpManagers,
41626
+ { profile: "full" }
41392
41627
  );
41393
- for (const session of sessions) {
41394
- const lastSeenAt = getSessionSeenAt(state, session.id);
41395
- const seenCompletionMarker = getSessionSeenMarker(state, session.id);
41396
- const lastUsedAt = getSessionLastUsedAt(session);
41397
- const completionMarker = getSessionCompletionMarker(session);
41398
- const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
41399
- getSessionMessageUpdatedAt(session) > 0,
41400
- session.status,
41628
+ const sessions = profile === "full" ? unreadSourceSessions : buildSessionEntries(
41629
+ options.allStates,
41630
+ options.cdpManagers,
41631
+ { profile }
41632
+ );
41633
+ const sessionsById = new Map(sessions.map((session) => [session.id, session]));
41634
+ for (const sourceSession of unreadSourceSessions) {
41635
+ const session = sessionsById.get(sourceSession.id);
41636
+ if (!session) continue;
41637
+ const lastSeenAt = getSessionSeenAt(state, sourceSession.id);
41638
+ const seenCompletionMarker = getSessionSeenMarker(state, sourceSession.id);
41639
+ const lastUsedAt = getSessionLastUsedAt(sourceSession);
41640
+ const completionMarker = getSessionCompletionMarker(sourceSession);
41641
+ const { unread, inboxBucket } = sourceSession.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
41642
+ getSessionMessageUpdatedAt(sourceSession) > 0,
41643
+ sourceSession.status,
41401
41644
  lastUsedAt,
41402
41645
  lastSeenAt,
41403
- getLastMessageRole(session),
41646
+ getLastMessageRole(sourceSession),
41404
41647
  completionMarker,
41405
41648
  seenCompletionMarker
41406
41649
  );
@@ -41410,39 +41653,30 @@ Run 'adhdev doctor' for detailed diagnostics.`
41410
41653
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
41411
41654
  LOG2.info(
41412
41655
  "RecentRead",
41413
- `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)}`
41656
+ `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)}`
41414
41657
  );
41415
41658
  }
41416
41659
  }
41417
- const terminalBackend = getTerminalBackendRuntimeStatus();
41660
+ const includeMachineMetadata = profile !== "live";
41661
+ const terminalBackend = includeMachineMetadata ? getTerminalBackendRuntimeStatus() : void 0;
41418
41662
  return {
41419
41663
  instanceId: options.instanceId,
41420
- version: options.version,
41421
- daemonMode: options.daemonMode,
41422
- machine: {
41423
- hostname: os16.hostname(),
41424
- platform: os16.platform(),
41425
- arch: os16.arch(),
41426
- cpus: os16.cpus().length,
41427
- totalMem: memSnap.totalMem,
41428
- freeMem: memSnap.freeMem,
41429
- availableMem: memSnap.availableMem,
41430
- loadavg: os16.loadavg(),
41431
- uptime: os16.uptime(),
41432
- release: os16.release()
41433
- },
41434
- machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
41664
+ ...includeMachineMetadata ? { version: options.version } : {},
41665
+ machine: buildMachineInfo2(profile),
41666
+ ...includeMachineMetadata ? { machineNickname: options.machineNickname ?? cfg.machineNickname ?? null } : {},
41435
41667
  timestamp: options.timestamp ?? Date.now(),
41436
- detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
41437
41668
  ...options.p2p ? { p2p: options.p2p } : {},
41438
41669
  sessions,
41439
- workspaces: wsState.workspaces,
41440
- defaultWorkspaceId: wsState.defaultWorkspaceId,
41441
- defaultWorkspacePath: wsState.defaultWorkspacePath,
41442
- terminalSizingMode: cfg.terminalSizingMode || "measured",
41443
- recentLaunches: buildRecentLaunches(recentActivity),
41444
- terminalBackend,
41445
- availableProviders: buildAvailableProviders(options.providerLoader)
41670
+ ...terminalBackend ? { terminalBackend } : {},
41671
+ ...includeMachineMetadata && {
41672
+ detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
41673
+ workspaces: wsState.workspaces,
41674
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
41675
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
41676
+ terminalSizingMode: cfg.terminalSizingMode || "measured",
41677
+ recentLaunches: buildRecentLaunches(recentActivity),
41678
+ availableProviders: buildAvailableProviders(options.providerLoader)
41679
+ }
41446
41680
  };
41447
41681
  }
41448
41682
  var import_child_process7 = require("child_process");
@@ -41994,6 +42228,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
41994
42228
  updateConfig({ userName: name });
41995
42229
  return { success: true, userName: name };
41996
42230
  }
42231
+ case "get_status_metadata": {
42232
+ const snapshot = buildStatusSnapshot2({
42233
+ allStates: this.deps.instanceManager.collectAllStates(),
42234
+ cdpManagers: this.deps.cdpManagers,
42235
+ providerLoader: this.deps.providerLoader,
42236
+ detectedIdes: this.deps.detectedIdes.value,
42237
+ instanceId: this.deps.statusInstanceId || loadConfig2().machineId || "daemon",
42238
+ version: this.deps.statusVersion || "unknown",
42239
+ profile: "metadata"
42240
+ });
42241
+ return { success: true, status: snapshot };
42242
+ }
42243
+ case "get_machine_runtime_stats": {
42244
+ return {
42245
+ success: true,
42246
+ machine: buildMachineInfo2("full"),
42247
+ timestamp: Date.now()
42248
+ };
42249
+ }
41997
42250
  case "mark_session_seen": {
41998
42251
  const sessionId = args?.sessionId;
41999
42252
  if (!sessionId || typeof sessionId !== "string") {
@@ -42197,9 +42450,58 @@ Run 'adhdev doctor' for detailed diagnostics.`
42197
42450
  }, 5e3 - elapsed);
42198
42451
  }
42199
42452
  }
42453
+ toDaemonStatusEventName(value) {
42454
+ switch (value) {
42455
+ case "agent:generating_started":
42456
+ case "agent:waiting_approval":
42457
+ case "agent:generating_completed":
42458
+ case "agent:stopped":
42459
+ case "monitor:long_generating":
42460
+ return value;
42461
+ default:
42462
+ return null;
42463
+ }
42464
+ }
42465
+ buildServerStatusEvent(event) {
42466
+ const eventName = this.toDaemonStatusEventName(event.event);
42467
+ if (!eventName) return null;
42468
+ if (eventName.startsWith("provider:")) {
42469
+ return null;
42470
+ }
42471
+ const payload = {
42472
+ event: eventName,
42473
+ timestamp: typeof event.timestamp === "number" && Number.isFinite(event.timestamp) ? event.timestamp : Date.now()
42474
+ };
42475
+ if (typeof event.targetSessionId === "string" && event.targetSessionId.trim()) {
42476
+ payload.targetSessionId = event.targetSessionId.trim();
42477
+ }
42478
+ const providerType = typeof event.providerType === "string" && event.providerType.trim() ? event.providerType.trim() : typeof event.ideType === "string" && event.ideType.trim() ? event.ideType.trim() : "";
42479
+ if (providerType) {
42480
+ payload.providerType = providerType;
42481
+ }
42482
+ if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
42483
+ payload.duration = event.duration;
42484
+ }
42485
+ if (typeof event.elapsedSec === "number" && Number.isFinite(event.elapsedSec)) {
42486
+ payload.elapsedSec = event.elapsedSec;
42487
+ }
42488
+ if (typeof event.modalMessage === "string" && event.modalMessage.trim()) {
42489
+ payload.modalMessage = event.modalMessage;
42490
+ }
42491
+ if (Array.isArray(event.modalButtons)) {
42492
+ const modalButtons = event.modalButtons.filter((button) => typeof button === "string" && button.trim().length > 0);
42493
+ if (modalButtons.length > 0) {
42494
+ payload.modalButtons = modalButtons;
42495
+ }
42496
+ }
42497
+ return payload;
42498
+ }
42200
42499
  emitStatusEvent(event) {
42201
42500
  LOG2.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
42202
- this.deps.serverConn?.sendMessage("status_event", event);
42501
+ const serverEvent = this.buildServerStatusEvent(event);
42502
+ if (!serverEvent) return;
42503
+ this.deps.p2p?.sendStatusEvent(serverEvent);
42504
+ this.deps.serverConn?.sendMessage("status_event", serverEvent);
42203
42505
  }
42204
42506
  removeAgentTracking(_key) {
42205
42507
  }
@@ -42268,17 +42570,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
42268
42570
  detectedIdes: this.deps.detectedIdes || [],
42269
42571
  instanceId: this.deps.instanceId,
42270
42572
  version: this.deps.daemonVersion || "unknown",
42271
- daemonMode: true,
42272
42573
  timestamp: now,
42273
42574
  p2p: {
42274
42575
  available: p2p?.isAvailable || false,
42275
42576
  state: p2p?.connectionState || "unavailable",
42276
42577
  peers: p2p?.connectedPeerCount || 0,
42277
42578
  screenshotActive: p2p?.screenshotActive || false
42278
- }
42579
+ },
42580
+ profile: "live"
42279
42581
  }),
42280
- screenshotUsage: this.deps.getScreenshotUsage?.() || null,
42281
- connectedExtensions: []
42582
+ screenshotUsage: this.deps.getScreenshotUsage?.() || null
42282
42583
  };
42283
42584
  const payloadBytes = JSON.stringify(payload).length;
42284
42585
  const p2pSent = this.sendP2PPayload(payload);
@@ -42293,16 +42594,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
42293
42594
  }
42294
42595
  if (opts?.p2pOnly) return;
42295
42596
  const wsPayload = {
42296
- daemonMode: true,
42297
42597
  sessions: sessions.map((session) => ({
42298
42598
  id: session.id,
42299
42599
  parentId: session.parentId,
42300
42600
  providerType: session.providerType,
42301
- providerName: session.providerName,
42601
+ providerName: session.providerName || session.providerType,
42302
42602
  kind: session.kind,
42303
42603
  transport: session.transport,
42304
42604
  status: session.status,
42305
- workspace: session.workspace,
42605
+ workspace: session.workspace ?? null,
42306
42606
  title: session.title,
42307
42607
  cdpConnected: session.cdpConnected,
42308
42608
  currentModel: session.currentModel,
@@ -42310,9 +42610,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42310
42610
  currentAutoApprove: session.currentAutoApprove
42311
42611
  })),
42312
42612
  p2p: payload.p2p,
42313
- timestamp: now,
42314
- detectedIdes: payload.detectedIdes,
42315
- availableProviders: payload.availableProviders
42613
+ timestamp: now
42316
42614
  };
42317
42615
  const wsHash = this.simpleHash(JSON.stringify({
42318
42616
  ...wsPayload,
@@ -42329,10 +42627,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
42329
42627
  // ─── P2P ─────────────────────────────────────────
42330
42628
  sendP2PPayload(payload) {
42331
42629
  const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
42630
+ const sessions = Array.isArray(hashTarget.sessions) ? hashTarget.sessions.map((session) => {
42631
+ if (!session || typeof session !== "object") return session;
42632
+ const { lastUpdated: _lu, ...stableSession } = session;
42633
+ return stableSession;
42634
+ }) : hashTarget.sessions;
42332
42635
  const hashPayload = hashTarget.machine ? (() => {
42333
42636
  const { freeMem: _f, availableMem: _a2, loadavg: _l2, uptime: _u, ...stableMachine } = hashTarget.machine;
42334
- return { ...hashTarget, machine: stableMachine };
42335
- })() : hashTarget;
42637
+ return { ...hashTarget, sessions, machine: stableMachine };
42638
+ })() : { ...hashTarget, sessions };
42336
42639
  const h = this.simpleHash(JSON.stringify(hashPayload));
42337
42640
  if (h !== this.lastP2PStatusHash) {
42338
42641
  this.lastP2PStatusHash = h;
@@ -49388,6 +49691,8 @@ data: ${JSON.stringify(msg.data)}
49388
49691
  onStatusChange: config2.onStatusChange,
49389
49692
  onPostChatCommand: config2.onPostChatCommand,
49390
49693
  sessionHostControl: config2.sessionHostControl,
49694
+ statusInstanceId: config2.statusInstanceId,
49695
+ statusVersion: config2.statusVersion,
49391
49696
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG2.forComponent(`CDP:${ideType}`).asLogFn())
49392
49697
  });
49393
49698
  poller = new AgentStreamPoller({
@@ -50015,18 +50320,75 @@ var SESSION_TARGET_COMMANDS = /* @__PURE__ */ new Set([
50015
50320
  "restart_session",
50016
50321
  "agent_command"
50017
50322
  ]);
50323
+ var ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
50324
+ "generating",
50325
+ "waiting_approval",
50326
+ "starting"
50327
+ ]);
50328
+ function hashSignatureParts(parts) {
50329
+ let hash2 = 2166136261;
50330
+ for (const part of parts) {
50331
+ const text = String(part || "");
50332
+ for (let i = 0; i < text.length; i += 1) {
50333
+ hash2 ^= text.charCodeAt(i);
50334
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
50335
+ }
50336
+ hash2 ^= 255;
50337
+ hash2 = Math.imul(hash2, 16777619) >>> 0;
50338
+ }
50339
+ return hash2.toString(16).padStart(8, "0");
50340
+ }
50341
+ function buildChatTailDeliverySignature(payload) {
50342
+ let messages = "";
50343
+ try {
50344
+ messages = JSON.stringify(payload.messages);
50345
+ } catch {
50346
+ messages = String(payload.messages.length);
50347
+ }
50348
+ return hashSignatureParts([
50349
+ payload.sessionId,
50350
+ payload.historySessionId || "",
50351
+ payload.status,
50352
+ payload.title || "",
50353
+ payload.syncMode,
50354
+ String(payload.replaceFrom),
50355
+ String(payload.totalMessages),
50356
+ payload.lastMessageSignature,
50357
+ payload.activeModal ? `${payload.activeModal.message}|${payload.activeModal.buttons.join("")}` : "",
50358
+ messages
50359
+ ]);
50360
+ }
50361
+ function buildSessionModalDeliverySignature(payload) {
50362
+ return hashSignatureParts([
50363
+ payload.sessionId,
50364
+ payload.status,
50365
+ payload.title || "",
50366
+ payload.modalMessage || "",
50367
+ Array.isArray(payload.modalButtons) ? payload.modalButtons.join("") : ""
50368
+ ]);
50369
+ }
50018
50370
  var StandaloneServer = class {
50019
50371
  httpServer = null;
50020
50372
  wss = null;
50021
50373
  clients = /* @__PURE__ */ new Set();
50374
+ wsSubscriptions = /* @__PURE__ */ new Map();
50375
+ wsMachineRuntimeSubscriptions = /* @__PURE__ */ new Map();
50376
+ wsSessionHostDiagnosticsSubscriptions = /* @__PURE__ */ new Map();
50377
+ wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
50378
+ wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
50022
50379
  authToken = null;
50023
50380
  statusTimer = null;
50024
50381
  lastStatusBroadcastAt = 0;
50025
50382
  statusBroadcastPending = false;
50383
+ lastWsStatusSignature = null;
50384
+ wsChatFlushInFlight = false;
50385
+ pendingWsChatFlush = null;
50386
+ hotWsChatSessionIds = /* @__PURE__ */ new Set();
50026
50387
  running = false;
50027
50388
  components = null;
50028
50389
  devServer = null;
50029
50390
  sessionHostEndpoint = null;
50391
+ sessionHostControl = null;
50030
50392
  isRecoverableSessionHostError(error48) {
50031
50393
  const message = error48 instanceof Error ? error48.message : String(error48);
50032
50394
  return message.includes("ECONNREFUSED") || message.includes("ENOENT") || message.includes("Session host socket unavailable");
@@ -50074,12 +50436,15 @@ var StandaloneServer = class {
50074
50436
  async start(options = {}) {
50075
50437
  const port = options.port || DEFAULT_PORT;
50076
50438
  const host = options.host || "127.0.0.1";
50439
+ const cfg = (0, import_daemon_core2.loadConfig)();
50077
50440
  const sessionHostEndpoint = await ensureSessionHostReady();
50078
50441
  this.sessionHostEndpoint = sessionHostEndpoint;
50079
50442
  const sessionHostControl = new StandaloneSessionHostControlPlane(
50080
50443
  async () => this.ensureActiveSessionHostEndpoint()
50081
50444
  );
50445
+ this.sessionHostControl = sessionHostControl;
50082
50446
  this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
50447
+ const statusInstanceId = `standalone_${cfg.machineId || "mach_unknown"}`;
50083
50448
  this.components = await (0, import_daemon_core2.initDaemonComponents)({
50084
50449
  cliManagerDeps: {
50085
50450
  getServerConn: () => null,
@@ -50116,6 +50481,9 @@ var StandaloneServer = class {
50116
50481
  }),
50117
50482
  listHostedCliRuntimes: async () => listHostedCliRuntimes(sessionHostEndpoint)
50118
50483
  },
50484
+ statusInstanceId,
50485
+ statusVersion: pkgVersion,
50486
+ statusDaemonMode: false,
50119
50487
  onStatusChange: () => this.scheduleBroadcastStatus(),
50120
50488
  sessionHostControl,
50121
50489
  onStreamsUpdated: (ideType, streams) => {
@@ -50157,6 +50525,10 @@ var StandaloneServer = class {
50157
50525
  });
50158
50526
  this.statusTimer = setInterval(() => {
50159
50527
  this.scheduleBroadcastStatus();
50528
+ void this.flushWsChatSubscriptions(void 0, { onlyActive: true });
50529
+ void this.flushWsMachineRuntimeSubscriptions();
50530
+ void this.flushWsSessionHostDiagnosticsSubscriptions();
50531
+ void this.flushWsSessionModalSubscriptions();
50160
50532
  }, STATUS_INTERVAL);
50161
50533
  this.running = true;
50162
50534
  await new Promise((resolve4) => {
@@ -50492,13 +50864,27 @@ var StandaloneServer = class {
50492
50864
  }
50493
50865
  }
50494
50866
  this.clients.add(ws2);
50867
+ this.wsSubscriptions.set(ws2, /* @__PURE__ */ new Map());
50868
+ this.wsMachineRuntimeSubscriptions.set(ws2, /* @__PURE__ */ new Map());
50869
+ this.wsSessionHostDiagnosticsSubscriptions.set(ws2, /* @__PURE__ */ new Map());
50870
+ this.wsSessionModalSubscriptions.set(ws2, /* @__PURE__ */ new Map());
50871
+ this.wsDaemonMetadataSubscriptions.set(ws2, /* @__PURE__ */ new Map());
50495
50872
  console.log(`[WS] Client connected (total: ${this.clients.size})`);
50496
- const status = this.getStatus();
50873
+ const status = this.getWsStatus(this.buildSharedSnapshot("live"));
50874
+ this.lastWsStatusSignature = this.buildWsStatusSignature(status);
50497
50875
  ws2.send(JSON.stringify({ type: "status", data: status }));
50498
50876
  void this.pushWsRuntimeSnapshots(ws2);
50499
50877
  ws2.on("message", async (raw) => {
50500
50878
  try {
50501
50879
  const msg = JSON.parse(raw.toString());
50880
+ if (msg.type === "subscribe") {
50881
+ await this.handleWsSubscribe(ws2, msg);
50882
+ return;
50883
+ }
50884
+ if (msg.type === "unsubscribe") {
50885
+ this.handleWsUnsubscribe(ws2, msg);
50886
+ return;
50887
+ }
50502
50888
  if (msg.type === "command") {
50503
50889
  const envelope = msg.data && typeof msg.data === "object" ? {
50504
50890
  ...msg.data,
@@ -50522,14 +50908,394 @@ var StandaloneServer = class {
50522
50908
  });
50523
50909
  ws2.on("close", () => {
50524
50910
  this.clients.delete(ws2);
50911
+ this.wsSubscriptions.delete(ws2);
50912
+ this.wsMachineRuntimeSubscriptions.delete(ws2);
50913
+ this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
50914
+ this.wsSessionModalSubscriptions.delete(ws2);
50915
+ this.wsDaemonMetadataSubscriptions.delete(ws2);
50525
50916
  console.log(`[WS] Client disconnected (total: ${this.clients.size})`);
50526
50917
  });
50527
50918
  ws2.on("error", () => {
50528
50919
  this.clients.delete(ws2);
50920
+ this.wsSubscriptions.delete(ws2);
50921
+ this.wsMachineRuntimeSubscriptions.delete(ws2);
50922
+ this.wsSessionHostDiagnosticsSubscriptions.delete(ws2);
50923
+ this.wsSessionModalSubscriptions.delete(ws2);
50924
+ this.wsDaemonMetadataSubscriptions.delete(ws2);
50925
+ });
50926
+ }
50927
+ async handleWsSubscribe(ws2, msg) {
50928
+ if (msg.topic === "session.chat_tail") {
50929
+ const params = msg.params;
50930
+ if (!params?.targetSessionId) return;
50931
+ const subs = this.wsSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
50932
+ this.wsSubscriptions.set(ws2, subs);
50933
+ subs.set(msg.key, {
50934
+ request: {
50935
+ ...msg,
50936
+ topic: "session.chat_tail",
50937
+ params
50938
+ },
50939
+ seq: 0,
50940
+ cursor: {
50941
+ knownMessageCount: Math.max(0, Number(params.knownMessageCount || 0)),
50942
+ lastMessageSignature: typeof params.lastMessageSignature === "string" ? params.lastMessageSignature : "",
50943
+ tailLimit: Math.max(0, Number(params.tailLimit || 0))
50944
+ },
50945
+ lastDeliveredSignature: ""
50946
+ });
50947
+ await this.flushWsChatSubscriptions(ws2);
50948
+ return;
50949
+ }
50950
+ if (msg.topic === "machine.runtime") {
50951
+ const params = msg.params;
50952
+ const subs = this.wsMachineRuntimeSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
50953
+ this.wsMachineRuntimeSubscriptions.set(ws2, subs);
50954
+ subs.set(msg.key, {
50955
+ request: {
50956
+ ...msg,
50957
+ topic: "machine.runtime",
50958
+ params
50959
+ },
50960
+ seq: 0,
50961
+ lastSentAt: 0
50962
+ });
50963
+ await this.flushWsMachineRuntimeSubscriptions(ws2);
50964
+ return;
50965
+ }
50966
+ if (msg.topic === "session_host.diagnostics") {
50967
+ const params = msg.params;
50968
+ const subs = this.wsSessionHostDiagnosticsSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
50969
+ this.wsSessionHostDiagnosticsSubscriptions.set(ws2, subs);
50970
+ subs.set(msg.key, {
50971
+ request: {
50972
+ ...msg,
50973
+ topic: "session_host.diagnostics",
50974
+ params
50975
+ },
50976
+ seq: 0,
50977
+ lastSentAt: 0
50978
+ });
50979
+ await this.flushWsSessionHostDiagnosticsSubscriptions(ws2);
50980
+ return;
50981
+ }
50982
+ if (msg.topic === "session.modal") {
50983
+ const params = msg.params;
50984
+ if (!params?.targetSessionId) return;
50985
+ const subs = this.wsSessionModalSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
50986
+ this.wsSessionModalSubscriptions.set(ws2, subs);
50987
+ subs.set(msg.key, {
50988
+ request: {
50989
+ ...msg,
50990
+ topic: "session.modal",
50991
+ params
50992
+ },
50993
+ seq: 0,
50994
+ lastSentAt: 0,
50995
+ lastDeliveredSignature: ""
50996
+ });
50997
+ await this.flushWsSessionModalSubscriptions(ws2);
50998
+ return;
50999
+ }
51000
+ if (msg.topic === "daemon.metadata") {
51001
+ const params = msg.params;
51002
+ const subs = this.wsDaemonMetadataSubscriptions.get(ws2) || /* @__PURE__ */ new Map();
51003
+ this.wsDaemonMetadataSubscriptions.set(ws2, subs);
51004
+ subs.set(msg.key, {
51005
+ request: {
51006
+ ...msg,
51007
+ topic: "daemon.metadata",
51008
+ params
51009
+ },
51010
+ seq: 0,
51011
+ lastSentAt: 0
51012
+ });
51013
+ await this.flushWsDaemonMetadataSubscriptions(ws2);
51014
+ }
51015
+ }
51016
+ handleWsUnsubscribe(ws2, msg) {
51017
+ if (msg.topic === "session.chat_tail") {
51018
+ this.wsSubscriptions.get(ws2)?.delete(msg.key);
51019
+ return;
51020
+ }
51021
+ if (msg.topic === "machine.runtime") {
51022
+ this.wsMachineRuntimeSubscriptions.get(ws2)?.delete(msg.key);
51023
+ return;
51024
+ }
51025
+ if (msg.topic === "session_host.diagnostics") {
51026
+ this.wsSessionHostDiagnosticsSubscriptions.get(ws2)?.delete(msg.key);
51027
+ return;
51028
+ }
51029
+ if (msg.topic === "session.modal") {
51030
+ this.wsSessionModalSubscriptions.get(ws2)?.delete(msg.key);
51031
+ return;
51032
+ }
51033
+ if (msg.topic === "daemon.metadata") {
51034
+ this.wsDaemonMetadataSubscriptions.get(ws2)?.delete(msg.key);
51035
+ }
51036
+ }
51037
+ async buildChatTailUpdate(request, state, key) {
51038
+ const result = await this.executeCommand("read_chat", {
51039
+ targetSessionId: request.targetSessionId,
51040
+ ...request.historySessionId ? { historySessionId: request.historySessionId } : {},
51041
+ knownMessageCount: state.cursor.knownMessageCount,
51042
+ lastMessageSignature: state.cursor.lastMessageSignature,
51043
+ ...state.cursor.tailLimit > 0 ? { tailLimit: state.cursor.tailLimit } : {}
51044
+ });
51045
+ if (!result?.success || result.syncMode === "noop") {
51046
+ if (result?.success) {
51047
+ state.cursor = {
51048
+ knownMessageCount: Math.max(0, Number(result.totalMessages || state.cursor.knownMessageCount)),
51049
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : state.cursor.lastMessageSignature,
51050
+ tailLimit: state.cursor.tailLimit
51051
+ };
51052
+ }
51053
+ return null;
51054
+ }
51055
+ state.seq += 1;
51056
+ const syncMode = result.syncMode === "append" || result.syncMode === "replace_tail" || result.syncMode === "noop" || result.syncMode === "full" ? result.syncMode : "full";
51057
+ state.cursor = {
51058
+ knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
51059
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
51060
+ tailLimit: state.cursor.tailLimit
51061
+ };
51062
+ const activeModal = result.activeModal && typeof result.activeModal === "object" && typeof result.activeModal.message === "string" && Array.isArray(result.activeModal.buttons) ? {
51063
+ message: result.activeModal.message,
51064
+ buttons: result.activeModal.buttons.filter((button) => typeof button === "string")
51065
+ } : null;
51066
+ const deliverySignature = buildChatTailDeliverySignature({
51067
+ sessionId: request.targetSessionId,
51068
+ ...request.historySessionId ? { historySessionId: request.historySessionId } : {},
51069
+ messages: Array.isArray(result.messages) ? result.messages : [],
51070
+ status: typeof result.status === "string" ? result.status : "idle",
51071
+ ...typeof result.title === "string" ? { title: result.title } : {},
51072
+ ...activeModal ? { activeModal } : {},
51073
+ syncMode,
51074
+ replaceFrom: Number(result.replaceFrom || 0),
51075
+ totalMessages: Number(result.totalMessages || 0),
51076
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
51077
+ });
51078
+ if (deliverySignature === state.lastDeliveredSignature) {
51079
+ return null;
51080
+ }
51081
+ state.lastDeliveredSignature = deliverySignature;
51082
+ return {
51083
+ topic: "session.chat_tail",
51084
+ key,
51085
+ sessionId: request.targetSessionId,
51086
+ ...request.historySessionId ? { historySessionId: request.historySessionId } : {},
51087
+ seq: state.seq,
51088
+ timestamp: Date.now(),
51089
+ messages: Array.isArray(result.messages) ? result.messages : [],
51090
+ status: typeof result.status === "string" ? result.status : "idle",
51091
+ ...typeof result.title === "string" ? { title: result.title } : {},
51092
+ ...activeModal ? { activeModal } : {},
51093
+ syncMode,
51094
+ replaceFrom: Number(result.replaceFrom || 0),
51095
+ totalMessages: Number(result.totalMessages || 0),
51096
+ lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
51097
+ };
51098
+ }
51099
+ getHotChatSessionIdsForWsFlush() {
51100
+ const snapshot = this.buildSharedSnapshot("live");
51101
+ const active = new Set(
51102
+ snapshot.sessions.filter((session) => ACTIVE_CHAT_POLL_STATUSES.has(String(session.status || "").toLowerCase())).map((session) => session.id)
51103
+ );
51104
+ const finalizing = new Set(
51105
+ Array.from(this.hotWsChatSessionIds).filter((sessionId) => !active.has(sessionId))
51106
+ );
51107
+ this.hotWsChatSessionIds = active;
51108
+ return { active, finalizing };
51109
+ }
51110
+ async flushWsChatSubscriptions(targetWs, options = {}) {
51111
+ if (this.wsChatFlushInFlight) {
51112
+ const nextOnlyActive = options.onlyActive === true;
51113
+ const pending = this.pendingWsChatFlush;
51114
+ this.pendingWsChatFlush = {
51115
+ targetWs: pending?.targetWs === void 0 || targetWs === void 0 ? void 0 : targetWs,
51116
+ onlyActive: pending ? pending.onlyActive && nextOnlyActive : nextOnlyActive
51117
+ };
51118
+ return;
51119
+ }
51120
+ this.wsChatFlushInFlight = true;
51121
+ try {
51122
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
51123
+ const hotSessionIds = options.onlyActive ? this.getHotChatSessionIdsForWsFlush() : null;
51124
+ for (const ws2 of targets) {
51125
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51126
+ const subs = this.wsSubscriptions.get(ws2);
51127
+ if (!subs || subs.size === 0) continue;
51128
+ for (const [key, sub] of subs.entries()) {
51129
+ const targetSessionId = sub.request.params.targetSessionId;
51130
+ if (hotSessionIds && !hotSessionIds.active.has(targetSessionId) && !hotSessionIds.finalizing.has(targetSessionId)) {
51131
+ continue;
51132
+ }
51133
+ const update = await this.buildChatTailUpdate(sub.request.params, sub, key);
51134
+ if (!update || ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51135
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
51136
+ }
51137
+ }
51138
+ } finally {
51139
+ this.wsChatFlushInFlight = false;
51140
+ if (this.pendingWsChatFlush) {
51141
+ const pending = this.pendingWsChatFlush;
51142
+ this.pendingWsChatFlush = null;
51143
+ void this.flushWsChatSubscriptions(pending.targetWs, { onlyActive: pending.onlyActive });
51144
+ }
51145
+ }
51146
+ }
51147
+ buildMachineRuntimeUpdate(state, key) {
51148
+ const intervalMs = Math.max(5e3, Number(state.request.params.intervalMs || 15e3));
51149
+ const now = Date.now();
51150
+ if (state.lastSentAt > 0 && now - state.lastSentAt < intervalMs) {
51151
+ return null;
51152
+ }
51153
+ state.seq += 1;
51154
+ state.lastSentAt = now;
51155
+ return {
51156
+ topic: "machine.runtime",
51157
+ key,
51158
+ machine: (0, import_daemon_core2.buildMachineInfo)("full"),
51159
+ seq: state.seq,
51160
+ timestamp: now
51161
+ };
51162
+ }
51163
+ async flushWsMachineRuntimeSubscriptions(targetWs) {
51164
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
51165
+ for (const ws2 of targets) {
51166
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51167
+ const subs = this.wsMachineRuntimeSubscriptions.get(ws2);
51168
+ if (!subs || subs.size === 0) continue;
51169
+ for (const [key, sub] of subs.entries()) {
51170
+ const update = this.buildMachineRuntimeUpdate(sub, key);
51171
+ if (!update || ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51172
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
51173
+ }
51174
+ }
51175
+ }
51176
+ async buildSessionHostDiagnosticsUpdate(state, key) {
51177
+ if (!this.sessionHostControl) return null;
51178
+ const intervalMs = Math.max(5e3, Number(state.request.params.intervalMs || 1e4));
51179
+ const now = Date.now();
51180
+ if (state.lastSentAt > 0 && now - state.lastSentAt < intervalMs) {
51181
+ return null;
51182
+ }
51183
+ const diagnostics = await this.sessionHostControl.getDiagnostics({
51184
+ includeSessions: state.request.params.includeSessions !== false,
51185
+ limit: Number(state.request.params.limit) || void 0
51186
+ });
51187
+ state.seq += 1;
51188
+ state.lastSentAt = now;
51189
+ return {
51190
+ topic: "session_host.diagnostics",
51191
+ key,
51192
+ diagnostics,
51193
+ seq: state.seq,
51194
+ timestamp: now
51195
+ };
51196
+ }
51197
+ async flushWsSessionHostDiagnosticsSubscriptions(targetWs) {
51198
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
51199
+ for (const ws2 of targets) {
51200
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51201
+ const subs = this.wsSessionHostDiagnosticsSubscriptions.get(ws2);
51202
+ if (!subs || subs.size === 0) continue;
51203
+ for (const [key, sub] of subs.entries()) {
51204
+ const update = await this.buildSessionHostDiagnosticsUpdate(sub, key);
51205
+ if (!update || ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51206
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
51207
+ }
51208
+ }
51209
+ }
51210
+ findProviderStateBySessionId(sessionId) {
51211
+ if (!this.components || !sessionId) return null;
51212
+ const states = this.components.instanceManager.collectAllStates();
51213
+ for (const state of states) {
51214
+ if (state.instanceId === sessionId) return state;
51215
+ if (state.category === "ide") {
51216
+ const child = state.extensions.find((entry) => entry.instanceId === sessionId);
51217
+ if (child) return child;
51218
+ }
51219
+ }
51220
+ return null;
51221
+ }
51222
+ buildSessionModalUpdate(state, key) {
51223
+ const providerState = this.findProviderStateBySessionId(state.request.params.targetSessionId);
51224
+ if (!providerState) return null;
51225
+ const now = Date.now();
51226
+ state.seq += 1;
51227
+ state.lastSentAt = now;
51228
+ const activeModal = providerState.activeChat?.activeModal;
51229
+ const modalButtons = Array.isArray(activeModal?.buttons) ? activeModal.buttons.filter((button) => typeof button === "string") : [];
51230
+ const status = String(providerState.activeChat?.status || providerState.status || "idle");
51231
+ const title = typeof providerState.activeChat?.title === "string" ? providerState.activeChat.title : void 0;
51232
+ const modalMessage = typeof activeModal?.message === "string" ? activeModal.message : void 0;
51233
+ const deliverySignature = buildSessionModalDeliverySignature({
51234
+ sessionId: state.request.params.targetSessionId,
51235
+ status,
51236
+ ...title ? { title } : {},
51237
+ ...modalMessage ? { modalMessage } : {},
51238
+ ...modalButtons.length > 0 ? { modalButtons } : {}
50529
51239
  });
51240
+ if (deliverySignature === state.lastDeliveredSignature) {
51241
+ return null;
51242
+ }
51243
+ state.lastDeliveredSignature = deliverySignature;
51244
+ return {
51245
+ topic: "session.modal",
51246
+ key,
51247
+ sessionId: state.request.params.targetSessionId,
51248
+ status,
51249
+ ...title ? { title } : {},
51250
+ ...modalMessage ? { modalMessage } : {},
51251
+ ...modalButtons.length > 0 ? { modalButtons } : {},
51252
+ seq: state.seq,
51253
+ timestamp: now
51254
+ };
51255
+ }
51256
+ async flushWsSessionModalSubscriptions(targetWs) {
51257
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
51258
+ for (const ws2 of targets) {
51259
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51260
+ const subs = this.wsSessionModalSubscriptions.get(ws2);
51261
+ if (!subs || subs.size === 0) continue;
51262
+ for (const [key, sub] of subs.entries()) {
51263
+ const update = this.buildSessionModalUpdate(sub, key);
51264
+ if (!update || ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51265
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
51266
+ }
51267
+ }
51268
+ }
51269
+ buildDaemonMetadataUpdate(state, key) {
51270
+ const now = Date.now();
51271
+ state.seq += 1;
51272
+ state.lastSentAt = now;
51273
+ const cfgSnap = (0, import_daemon_core2.loadConfig)();
51274
+ return {
51275
+ topic: "daemon.metadata",
51276
+ key,
51277
+ daemonId: `standalone_${cfgSnap.machineId || "standalone"}`,
51278
+ status: this.buildSharedSnapshot("metadata"),
51279
+ userName: cfgSnap.userName || void 0,
51280
+ seq: state.seq,
51281
+ timestamp: now
51282
+ };
51283
+ }
51284
+ async flushWsDaemonMetadataSubscriptions(targetWs) {
51285
+ const targets = targetWs ? [targetWs] : Array.from(this.clients);
51286
+ for (const ws2 of targets) {
51287
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51288
+ const subs = this.wsDaemonMetadataSubscriptions.get(ws2);
51289
+ if (!subs || subs.size === 0) continue;
51290
+ for (const [key, sub] of subs.entries()) {
51291
+ const update = this.buildDaemonMetadataUpdate(sub, key);
51292
+ if (ws2.readyState !== import_ws.WebSocket.OPEN) continue;
51293
+ ws2.send(JSON.stringify({ type: "topic_update", update }));
51294
+ }
51295
+ }
50530
51296
  }
50531
51297
  // ─── Core Logic ───
50532
- buildSharedSnapshot() {
51298
+ buildSharedSnapshot(profile = "full") {
50533
51299
  const cfgSnap = (0, import_daemon_core2.loadConfig)();
50534
51300
  const machineId = cfgSnap.machineId || "mach_unknown";
50535
51301
  const allStates = this.components.instanceManager.collectAllStates();
@@ -50543,7 +51309,7 @@ var StandaloneServer = class {
50543
51309
  })),
50544
51310
  instanceId: `standalone_${machineId}`,
50545
51311
  version: pkgVersion,
50546
- daemonMode: false
51312
+ profile
50547
51313
  });
50548
51314
  }
50549
51315
  async pushWsRuntimeSnapshots(ws2) {
@@ -50571,27 +51337,62 @@ var StandaloneServer = class {
50571
51337
  });
50572
51338
  }
50573
51339
  }
50574
- getStatus(snapshot = this.buildSharedSnapshot()) {
51340
+ getStatus(snapshot = this.buildSharedSnapshot("full")) {
50575
51341
  const cfgSnap = (0, import_daemon_core2.loadConfig)();
51342
+ const machineRuntime = (0, import_daemon_core2.buildMachineInfo)("full");
50576
51343
  return {
50577
51344
  ...snapshot,
50578
51345
  id: snapshot.instanceId,
50579
- daemonMode: false,
50580
51346
  type: "standalone",
50581
51347
  platform: snapshot.machine.platform,
50582
51348
  hostname: snapshot.machine.hostname,
50583
51349
  userName: cfgSnap.userName || void 0,
50584
51350
  system: {
50585
- cpus: snapshot.machine.cpus,
50586
- totalMem: snapshot.machine.totalMem,
50587
- freeMem: snapshot.machine.freeMem,
50588
- availableMem: snapshot.machine.availableMem,
50589
- loadavg: snapshot.machine.loadavg,
50590
- uptime: snapshot.machine.uptime,
50591
- arch: snapshot.machine.arch
51351
+ cpus: snapshot.machine.cpus ?? machineRuntime.cpus ?? 0,
51352
+ totalMem: snapshot.machine.totalMem ?? machineRuntime.totalMem ?? 0,
51353
+ freeMem: snapshot.machine.freeMem ?? machineRuntime.freeMem ?? 0,
51354
+ availableMem: snapshot.machine.availableMem ?? machineRuntime.availableMem ?? 0,
51355
+ loadavg: snapshot.machine.loadavg ?? machineRuntime.loadavg ?? [],
51356
+ uptime: snapshot.machine.uptime ?? machineRuntime.uptime ?? 0,
51357
+ arch: snapshot.machine.arch ?? machineRuntime.arch ?? os5.arch()
50592
51358
  }
50593
51359
  };
50594
51360
  }
51361
+ getWsStatus(snapshot = this.buildSharedSnapshot("live")) {
51362
+ return {
51363
+ instanceId: snapshot.instanceId,
51364
+ machine: snapshot.machine,
51365
+ timestamp: snapshot.timestamp,
51366
+ sessions: snapshot.sessions,
51367
+ terminalBackend: snapshot.terminalBackend
51368
+ };
51369
+ }
51370
+ buildWsStatusSignature(status) {
51371
+ return JSON.stringify({
51372
+ instanceId: status.instanceId,
51373
+ machine: {
51374
+ hostname: status.machine.hostname,
51375
+ platform: status.machine.platform
51376
+ },
51377
+ sessions: status.sessions.map((session) => ({
51378
+ id: session.id,
51379
+ parentId: session.parentId,
51380
+ providerType: session.providerType,
51381
+ kind: session.kind,
51382
+ transport: session.transport,
51383
+ status: session.status,
51384
+ title: session.title,
51385
+ cdpConnected: session.cdpConnected,
51386
+ currentModel: session.currentModel,
51387
+ currentPlan: session.currentPlan,
51388
+ currentAutoApprove: session.currentAutoApprove,
51389
+ lastSeenAt: session.lastSeenAt,
51390
+ unread: session.unread,
51391
+ inboxBucket: session.inboxBucket,
51392
+ surfaceHidden: session.surfaceHidden
51393
+ }))
51394
+ });
51395
+ }
50595
51396
  normalizeCommandEnvelope(input) {
50596
51397
  const body = input && typeof input === "object" ? input : {};
50597
51398
  const type = typeof body.type === "string" && body.type.trim() ? body.type.trim() : typeof body.commandType === "string" && body.commandType.trim() ? body.commandType.trim() : typeof body.command === "string" && body.command.trim() ? body.command.trim() : "";
@@ -50613,6 +51414,11 @@ var StandaloneServer = class {
50613
51414
  }
50614
51415
  const result = await this.components.router.execute(type, args, "standalone");
50615
51416
  if (type.startsWith("workspace_") || type.startsWith("session_host_")) this.scheduleBroadcastStatus();
51417
+ if (type === "get_status_metadata" || type === "set_user_name" || type === "set_machine_nickname" || type.startsWith("workspace_") || type.startsWith("session_host_")) {
51418
+ void this.flushWsDaemonMetadataSubscriptions();
51419
+ }
51420
+ if (type.startsWith("session_host_")) void this.flushWsSessionHostDiagnosticsSubscriptions();
51421
+ if (type === "resolve_action" || type === "send_chat" || type === "read_chat") void this.flushWsSessionModalSubscriptions();
50616
51422
  return result;
50617
51423
  }
50618
51424
  scheduleBroadcastStatus() {
@@ -50632,8 +51438,11 @@ var StandaloneServer = class {
50632
51438
  }
50633
51439
  broadcastStatus() {
50634
51440
  if (this.clients.size === 0) return;
51441
+ const status = this.getWsStatus(this.buildSharedSnapshot("live"));
51442
+ const signature = this.buildWsStatusSignature(status);
51443
+ if (signature === this.lastWsStatusSignature) return;
51444
+ this.lastWsStatusSignature = signature;
50635
51445
  this.lastStatusBroadcastAt = Date.now();
50636
- const status = this.getStatus();
50637
51446
  const msg = JSON.stringify({ type: "status", data: status });
50638
51447
  const cdpCount = [...this.components.cdpManagers.values()].filter((m) => m.isConnected).length;
50639
51448
  import_daemon_core2.LOG.debug("Broadcast", `status \u2192 ${this.clients.size} client(s), ${status.sessions?.length || 0} session(s), ${cdpCount} CDP`);
@@ -50673,6 +51482,12 @@ var StandaloneServer = class {
50673
51482
  }
50674
51483
  }
50675
51484
  this.clients.clear();
51485
+ this.wsSubscriptions.clear();
51486
+ this.wsMachineRuntimeSubscriptions.clear();
51487
+ this.wsSessionHostDiagnosticsSubscriptions.clear();
51488
+ this.wsSessionModalSubscriptions.clear();
51489
+ this.wsDaemonMetadataSubscriptions.clear();
51490
+ this.lastWsStatusSignature = null;
50676
51491
  if (this.wss) {
50677
51492
  this.wss.close();
50678
51493
  this.wss = null;
@@ -50680,6 +51495,7 @@ var StandaloneServer = class {
50680
51495
  if (this.components) {
50681
51496
  await (0, import_daemon_core2.shutdownDaemonComponents)(this.components);
50682
51497
  }
51498
+ this.sessionHostControl = null;
50683
51499
  if (this.httpServer) {
50684
51500
  this.httpServer.close();
50685
51501
  this.httpServer = null;