@adhdev/daemon-standalone 0.8.60 → 0.8.62

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
@@ -28313,6 +28313,63 @@ var require_dist2 = __commonJS({
28313
28313
  LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
28314
28314
  }
28315
28315
  });
28316
+ function isBuiltinChatMessageKind(kind) {
28317
+ return typeof kind === "string" && KNOWN_CHAT_MESSAGE_KINDS.has(kind.trim().toLowerCase());
28318
+ }
28319
+ function normalizeChatMessageKind(kind, role) {
28320
+ const normalizedKind = typeof kind === "string" ? kind.trim().toLowerCase() : "";
28321
+ if (normalizedKind && KNOWN_CHAT_MESSAGE_KINDS.has(normalizedKind)) return normalizedKind;
28322
+ const normalizedRole = typeof role === "string" ? role.trim().toLowerCase() : "";
28323
+ return normalizedRole === "system" ? "system" : "standard";
28324
+ }
28325
+ function buildChatMessage(message) {
28326
+ return {
28327
+ ...message,
28328
+ kind: normalizeChatMessageKind(message?.kind, message?.role)
28329
+ };
28330
+ }
28331
+ function buildSystemChatMessage(message) {
28332
+ return buildChatMessage({
28333
+ ...message,
28334
+ role: "system",
28335
+ kind: message?.kind || "system"
28336
+ });
28337
+ }
28338
+ function buildRuntimeSystemChatMessage(message) {
28339
+ return buildSystemChatMessage({
28340
+ ...message,
28341
+ senderName: typeof message?.senderName === "string" && message.senderName.trim() ? message.senderName : "System"
28342
+ });
28343
+ }
28344
+ function buildAssistantChatMessage(message) {
28345
+ return buildChatMessage({
28346
+ ...message,
28347
+ role: "assistant",
28348
+ kind: message?.kind || "standard"
28349
+ });
28350
+ }
28351
+ function buildUserChatMessage(message) {
28352
+ return buildChatMessage({
28353
+ ...message,
28354
+ role: "user",
28355
+ kind: message?.kind || "standard"
28356
+ });
28357
+ }
28358
+ function normalizeChatMessage(message) {
28359
+ return buildChatMessage(message);
28360
+ }
28361
+ function normalizeChatMessages(messages) {
28362
+ return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
28363
+ }
28364
+ var BUILTIN_CHAT_MESSAGE_KINDS;
28365
+ var KNOWN_CHAT_MESSAGE_KINDS;
28366
+ var init_chat_message_normalization = __esm2({
28367
+ "src/providers/chat-message-normalization.ts"() {
28368
+ "use strict";
28369
+ BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
28370
+ KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
28371
+ }
28372
+ });
28316
28373
  function isModuleNotFoundError(error48, ref) {
28317
28374
  if (!(error48 instanceof Error)) return false;
28318
28375
  const message = error48.message || "";
@@ -28962,6 +29019,7 @@ var require_dist2 = __commonJS({
28962
29019
  terminalScreenText,
28963
29020
  baseMessages,
28964
29021
  partialResponse,
29022
+ isWaitingForResponse,
28965
29023
  scope,
28966
29024
  runtimeSettings
28967
29025
  } = options;
@@ -28979,6 +29037,7 @@ var require_dist2 = __commonJS({
28979
29037
  recentScreen: buildCliScreenSnapshot(recentBuffer),
28980
29038
  messages: [...baseMessages],
28981
29039
  partialResponse,
29040
+ isWaitingForResponse,
28982
29041
  promptText: scope?.prompt || "",
28983
29042
  settings: { ...runtimeSettings }
28984
29043
  };
@@ -29160,6 +29219,7 @@ var require_dist2 = __commonJS({
29160
29219
  init_terminal_screen();
29161
29220
  init_pty_transport();
29162
29221
  init_provider_cli_shared();
29222
+ init_chat_message_normalization();
29163
29223
  init_provider_cli_parse();
29164
29224
  init_provider_cli_config();
29165
29225
  init_provider_cli_runtime();
@@ -29712,6 +29772,18 @@ var require_dist2 = __commonJS({
29712
29772
  const holdMs = this.getStatusActivityHoldMs();
29713
29773
  return quietForMs < holdMs || screenStableMs < holdMs;
29714
29774
  }
29775
+ shouldDeferIdleTimeoutFinish() {
29776
+ if (!this.isWaitingForResponse || this.currentStatus === "waiting_approval") {
29777
+ return false;
29778
+ }
29779
+ const latestStatus = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
29780
+ if (latestStatus === "generating") {
29781
+ this.settledBuffer = this.recentOutputBuffer;
29782
+ this.evaluateSettled();
29783
+ return true;
29784
+ }
29785
+ return false;
29786
+ }
29715
29787
  getStartupConfirmationModal(screenText) {
29716
29788
  const text = sanitizeTerminalText(String(screenText || ""));
29717
29789
  if (!text.trim()) return null;
@@ -29870,6 +29942,7 @@ var require_dist2 = __commonJS({
29870
29942
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
29871
29943
  this.idleTimeout = setTimeout(() => {
29872
29944
  if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
29945
+ if (this.shouldDeferIdleTimeoutFinish()) return;
29873
29946
  this.finishResponse();
29874
29947
  }
29875
29948
  }, this.timeouts.generatingIdle);
@@ -29905,6 +29978,7 @@ var require_dist2 = __commonJS({
29905
29978
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
29906
29979
  this.idleTimeout = setTimeout(() => {
29907
29980
  if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
29981
+ if (this.shouldDeferIdleTimeoutFinish()) return;
29908
29982
  this.finishResponse();
29909
29983
  }
29910
29984
  }, this.timeouts.generatingIdle);
@@ -29947,7 +30021,10 @@ var require_dist2 = __commonJS({
29947
30021
  this.setStatus("generating", "script_detect");
29948
30022
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
29949
30023
  this.idleTimeout = setTimeout(() => {
29950
- if (this.isWaitingForResponse) this.finishResponse();
30024
+ if (this.isWaitingForResponse) {
30025
+ if (this.shouldDeferIdleTimeoutFinish()) return;
30026
+ this.finishResponse();
30027
+ }
29951
30028
  }, this.timeouts.generatingIdle);
29952
30029
  this.onStatusChange?.();
29953
30030
  return;
@@ -30015,6 +30092,7 @@ var require_dist2 = __commonJS({
30015
30092
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
30016
30093
  this.idleTimeout = setTimeout(() => {
30017
30094
  if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
30095
+ if (this.shouldDeferIdleTimeoutFinish()) return;
30018
30096
  this.clearIdleFinishCandidate("idle_timeout_finish");
30019
30097
  this.finishResponse();
30020
30098
  }
@@ -30153,6 +30231,7 @@ var require_dist2 = __commonJS({
30153
30231
  tail: text.slice(-500),
30154
30232
  screenText,
30155
30233
  rawBuffer: this.accumulatedRawBuffer,
30234
+ isWaitingForResponse: this.isWaitingForResponse,
30156
30235
  screen: buildCliScreenSnapshot(screenText),
30157
30236
  tailScreen: buildCliScreenSnapshot(text.slice(-500))
30158
30237
  });
@@ -30217,11 +30296,10 @@ var require_dist2 = __commonJS({
30217
30296
  );
30218
30297
  const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
30219
30298
  if (parsed && Array.isArray(parsed.messages)) {
30220
- const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => ({
30299
+ const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
30221
30300
  ...message,
30222
30301
  id: message.id || `msg_${index}`,
30223
30302
  index: typeof message.index === "number" ? message.index : index,
30224
- kind: message.kind || "standard",
30225
30303
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30226
30304
  })) : hydrateCliParsedMessages(parsed.messages, {
30227
30305
  committedMessages: this.committedMessages,
@@ -30242,13 +30320,11 @@ var require_dist2 = __commonJS({
30242
30320
  id: "cli_session",
30243
30321
  status: this.currentStatus,
30244
30322
  title: this.cliName,
30245
- messages: messages.slice(-50).map((message, index) => ({
30246
- id: `msg_${index}`,
30247
- role: message.role,
30248
- content: message.content,
30249
- timestamp: message.timestamp,
30250
- index,
30251
- kind: "standard"
30323
+ messages: messages.slice(-50).map((message, index) => buildChatMessage({
30324
+ ...message,
30325
+ id: message.id || `msg_${index}`,
30326
+ index: typeof message.index === "number" ? message.index : index,
30327
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30252
30328
  })),
30253
30329
  activeModal: this.activeModal
30254
30330
  };
@@ -30265,6 +30341,7 @@ var require_dist2 = __commonJS({
30265
30341
  terminalScreenText: this.terminalScreen.getText(),
30266
30342
  baseMessages: this.committedMessages,
30267
30343
  partialResponse: this.responseBuffer,
30344
+ isWaitingForResponse: this.isWaitingForResponse,
30268
30345
  scope: this.currentTurnScope,
30269
30346
  runtimeSettings: this.runtimeSettings
30270
30347
  });
@@ -30283,6 +30360,7 @@ var require_dist2 = __commonJS({
30283
30360
  terminalScreenText: this.terminalScreen.getText(),
30284
30361
  baseMessages,
30285
30362
  partialResponse,
30363
+ isWaitingForResponse: this.isWaitingForResponse,
30286
30364
  scope,
30287
30365
  runtimeSettings: this.runtimeSettings
30288
30366
  });
@@ -30871,6 +30949,7 @@ ${data.message || ""}`.trim();
30871
30949
  __export2(index_exports, {
30872
30950
  AcpProviderInstance: () => AcpProviderInstance,
30873
30951
  AgentStreamPoller: () => AgentStreamPoller,
30952
+ BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
30874
30953
  CdpDomHandlers: () => CdpDomHandlers,
30875
30954
  CliProviderInstance: () => CliProviderInstance,
30876
30955
  DAEMON_WS_PATH: () => DAEMON_WS_PATH,
@@ -30895,9 +30974,14 @@ ${data.message || ""}`.trim();
30895
30974
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
30896
30975
  VersionArchive: () => VersionArchive,
30897
30976
  appendRecentActivity: () => appendRecentActivity,
30977
+ buildAssistantChatMessage: () => buildAssistantChatMessage,
30978
+ buildChatMessage: () => buildChatMessage,
30898
30979
  buildMachineInfo: () => buildMachineInfo2,
30980
+ buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
30899
30981
  buildSessionEntries: () => buildSessionEntries,
30900
30982
  buildStatusSnapshot: () => buildStatusSnapshot2,
30983
+ buildSystemChatMessage: () => buildSystemChatMessage,
30984
+ buildUserChatMessage: () => buildUserChatMessage,
30901
30985
  clearDebugTrace: () => clearDebugTrace,
30902
30986
  configureDebugTraceStore: () => configureDebugTraceStore,
30903
30987
  connectCdpManager: () => connectCdpManager,
@@ -30929,6 +31013,7 @@ ${data.message || ""}`.trim();
30929
31013
  initDaemonComponents: () => initDaemonComponents2,
30930
31014
  installExtensions: () => installExtensions,
30931
31015
  installGlobalInterceptor: () => installGlobalInterceptor,
31016
+ isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
30932
31017
  isCdpConnected: () => isCdpConnected,
30933
31018
  isExtensionInstalled: () => isExtensionInstalled,
30934
31019
  isIdeRunning: () => isIdeRunning,
@@ -30947,6 +31032,9 @@ ${data.message || ""}`.trim();
30947
31032
  markSetupComplete: () => markSetupComplete,
30948
31033
  maybeRunDaemonUpgradeHelperFromEnv: () => maybeRunDaemonUpgradeHelperFromEnv2,
30949
31034
  normalizeActiveChatData: () => normalizeActiveChatData,
31035
+ normalizeChatMessage: () => normalizeChatMessage,
31036
+ normalizeChatMessageKind: () => normalizeChatMessageKind,
31037
+ normalizeChatMessages: () => normalizeChatMessages,
30950
31038
  normalizeInputEnvelope: () => normalizeInputEnvelope,
30951
31039
  normalizeManagedStatus: () => normalizeManagedStatus,
30952
31040
  normalizeMessageParts: () => normalizeMessageParts,
@@ -32928,6 +33016,215 @@ ${data.message || ""}`.trim();
32928
33016
  }
32929
33017
  };
32930
33018
  var crypto2 = __toESM2(require("crypto"));
33019
+ function normalizeInputEnvelope(input) {
33020
+ const normalized = normalizeInputEnvelopePayload(input);
33021
+ const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
33022
+ return {
33023
+ parts: normalized.parts,
33024
+ textFallback,
33025
+ ...normalized.metadata ? { metadata: normalized.metadata } : {}
33026
+ };
33027
+ }
33028
+ function normalizeMessageParts(content) {
33029
+ if (typeof content === "string") return [{ type: "text", text: content }];
33030
+ if (!Array.isArray(content)) {
33031
+ if (content && typeof content === "object" && typeof content.text === "string") {
33032
+ return [{ type: "text", text: String(content.text) }];
33033
+ }
33034
+ return [];
33035
+ }
33036
+ const parts = [];
33037
+ for (const raw of content) {
33038
+ if (typeof raw === "string") {
33039
+ parts.push({ type: "text", text: raw });
33040
+ continue;
33041
+ }
33042
+ if (!raw || typeof raw !== "object") continue;
33043
+ const part = normalizeMessagePartObject(raw);
33044
+ if (part) parts.push(part);
33045
+ }
33046
+ return parts;
33047
+ }
33048
+ function flattenMessageParts(parts) {
33049
+ return parts.map((part) => {
33050
+ if (part.type === "text") return part.text;
33051
+ if (part.type === "resource") return part.resource.text || "";
33052
+ return "";
33053
+ }).filter((value) => value.length > 0).join("\n");
33054
+ }
33055
+ function normalizeInputEnvelopePayload(input) {
33056
+ if (typeof input === "string") {
33057
+ return { parts: [{ type: "text", text: input }], textFallback: input };
33058
+ }
33059
+ if (!input || typeof input !== "object") {
33060
+ return { parts: [], textFallback: "" };
33061
+ }
33062
+ const record2 = input;
33063
+ const nestedInput = record2.input;
33064
+ if (nestedInput && typeof nestedInput === "object") {
33065
+ const nested = nestedInput;
33066
+ return {
33067
+ parts: normalizeInputParts(nested.parts ?? nested.prompt),
33068
+ textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
33069
+ metadata: normalizeInputMetadata(nested.metadata)
33070
+ };
33071
+ }
33072
+ const directText = typeof record2.text === "string" ? record2.text : typeof record2.message === "string" ? record2.message : void 0;
33073
+ if (directText !== void 0) {
33074
+ return { parts: [{ type: "text", text: directText }], textFallback: directText };
33075
+ }
33076
+ const directParts = normalizeInputParts(record2.parts ?? record2.prompt);
33077
+ return {
33078
+ parts: directParts,
33079
+ textFallback: typeof record2.textFallback === "string" ? record2.textFallback : void 0,
33080
+ metadata: normalizeInputMetadata(record2.metadata)
33081
+ };
33082
+ }
33083
+ function normalizeInputMetadata(value) {
33084
+ if (!value || typeof value !== "object") return void 0;
33085
+ const record2 = value;
33086
+ const metadata = {};
33087
+ if (record2.source === "dashboard" || record2.source === "shortcut_api" || record2.source === "provider_script" || record2.source === "session_replay") {
33088
+ metadata.source = record2.source;
33089
+ }
33090
+ if (typeof record2.clientTimestamp === "number" && Number.isFinite(record2.clientTimestamp)) {
33091
+ metadata.clientTimestamp = record2.clientTimestamp;
33092
+ }
33093
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
33094
+ }
33095
+ function normalizeInputParts(value) {
33096
+ if (!Array.isArray(value)) return [];
33097
+ const parts = [];
33098
+ for (const raw of value) {
33099
+ if (typeof raw === "string") {
33100
+ parts.push({ type: "text", text: raw });
33101
+ continue;
33102
+ }
33103
+ if (!raw || typeof raw !== "object") continue;
33104
+ const part = normalizeInputPartObject(raw);
33105
+ if (part) parts.push(part);
33106
+ }
33107
+ return parts;
33108
+ }
33109
+ function normalizeInputPartObject(raw) {
33110
+ const type = raw.type;
33111
+ if (type === "text" && typeof raw.text === "string") {
33112
+ return { type, text: raw.text };
33113
+ }
33114
+ if (type === "image" && typeof raw.mimeType === "string") {
33115
+ return {
33116
+ type,
33117
+ mimeType: raw.mimeType,
33118
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33119
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33120
+ ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
33121
+ };
33122
+ }
33123
+ if (type === "audio" && typeof raw.mimeType === "string") {
33124
+ return {
33125
+ type,
33126
+ mimeType: raw.mimeType,
33127
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33128
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33129
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
33130
+ };
33131
+ }
33132
+ if (type === "video" && typeof raw.mimeType === "string") {
33133
+ return {
33134
+ type,
33135
+ mimeType: raw.mimeType,
33136
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33137
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33138
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
33139
+ };
33140
+ }
33141
+ if (type === "resource" && typeof raw.uri === "string") {
33142
+ return {
33143
+ type,
33144
+ uri: raw.uri,
33145
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33146
+ ...typeof raw.name === "string" ? { name: raw.name } : {},
33147
+ ...typeof raw.text === "string" ? { text: raw.text } : {},
33148
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
33149
+ };
33150
+ }
33151
+ if (type === "resource_link" && typeof raw.uri === "string") {
33152
+ return {
33153
+ type: "resource",
33154
+ uri: raw.uri,
33155
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33156
+ ...typeof raw.name === "string" ? { name: raw.name } : {}
33157
+ };
33158
+ }
33159
+ return null;
33160
+ }
33161
+ function normalizeMessagePartObject(raw) {
33162
+ const type = raw.type;
33163
+ if (type === "text" && typeof raw.text === "string") {
33164
+ return { type, text: raw.text };
33165
+ }
33166
+ if (type === "image" && typeof raw.mimeType === "string") {
33167
+ return {
33168
+ type,
33169
+ mimeType: raw.mimeType,
33170
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33171
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
33172
+ };
33173
+ }
33174
+ if (type === "audio" && typeof raw.mimeType === "string") {
33175
+ return {
33176
+ type,
33177
+ mimeType: raw.mimeType,
33178
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33179
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33180
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
33181
+ };
33182
+ }
33183
+ if (type === "video" && typeof raw.mimeType === "string") {
33184
+ return {
33185
+ type,
33186
+ mimeType: raw.mimeType,
33187
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33188
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33189
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
33190
+ };
33191
+ }
33192
+ if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
33193
+ return {
33194
+ type,
33195
+ uri: raw.uri,
33196
+ name: raw.name,
33197
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33198
+ ...typeof raw.size === "number" ? { size: raw.size } : {}
33199
+ };
33200
+ }
33201
+ if (type === "resource" && raw.resource && typeof raw.resource === "object") {
33202
+ const resource = raw.resource;
33203
+ if (typeof resource.uri !== "string") return null;
33204
+ return {
33205
+ type,
33206
+ resource: {
33207
+ uri: resource.uri,
33208
+ ...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
33209
+ ...typeof resource.text === "string" ? { text: resource.text } : {},
33210
+ ...typeof resource.blob === "string" ? { blob: resource.blob } : {}
33211
+ }
33212
+ };
33213
+ }
33214
+ return null;
33215
+ }
33216
+ function flattenInputParts(parts) {
33217
+ return parts.map((part) => {
33218
+ if (part.type === "text") return part.text;
33219
+ if (part.type === "audio") return part.transcript || "";
33220
+ if (part.type === "resource") return part.text || "";
33221
+ return "";
33222
+ }).filter((value) => value.length > 0).join("\n");
33223
+ }
33224
+ function flattenContent(content) {
33225
+ if (typeof content === "string") return content;
33226
+ return flattenMessageParts(normalizeMessageParts(content));
33227
+ }
32931
33228
  var DEFAULT_MONITOR_CONFIG = {
32932
33229
  approvalAlert: true,
32933
33230
  longGeneratingAlert: true,
@@ -33038,6 +33335,7 @@ ${data.message || ""}`.trim();
33038
33335
  }
33039
33336
  }
33040
33337
  };
33338
+ init_chat_message_normalization();
33041
33339
  function extractProviderControlValues(controls, data) {
33042
33340
  if (!data || typeof data !== "object") return void 0;
33043
33341
  const values = {};
@@ -33105,13 +33403,58 @@ ${data.message || ""}`.trim();
33105
33403
  level: raw.notification.level === "success" || raw.notification.level === "warning" ? raw.notification.level : "info",
33106
33404
  channels: Array.isArray(raw.notification.channels) ? raw.notification.channels.filter((channel) => channel === "bubble" || channel === "toast" || channel === "browser") : void 0,
33107
33405
  preferenceKey: raw.notification.preferenceKey === "disconnect" || raw.notification.preferenceKey === "completion" || raw.notification.preferenceKey === "approval" || raw.notification.preferenceKey === "browser" ? raw.notification.preferenceKey : void 0,
33108
- bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0
33406
+ bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0,
33407
+ bubbleKind: typeof raw.notification.bubbleKind === "string" ? raw.notification.bubbleKind : void 0,
33408
+ bubbleRole: raw.notification.bubbleRole === "assistant" || raw.notification.bubbleRole === "user" ? raw.notification.bubbleRole : raw.notification.bubbleRole === "system" ? "system" : void 0,
33409
+ bubbleSenderName: typeof raw.notification.bubbleSenderName === "string" ? raw.notification.bubbleSenderName : void 0
33109
33410
  }
33110
33411
  });
33111
33412
  }
33112
33413
  }
33113
33414
  return effects;
33114
33415
  }
33416
+ function buildPersistedProviderEffectMessage(effect) {
33417
+ if (!effect) return null;
33418
+ if (effect.type === "message" && effect.message) {
33419
+ const role = effect.message.role === "assistant" || effect.message.role === "user" ? effect.message.role : "system";
33420
+ if (role === "system") {
33421
+ return buildRuntimeSystemChatMessage({
33422
+ content: effect.message.content,
33423
+ kind: effect.message.kind,
33424
+ senderName: effect.message.senderName
33425
+ });
33426
+ }
33427
+ return buildChatMessage({
33428
+ role,
33429
+ content: effect.message.content,
33430
+ kind: effect.message.kind,
33431
+ senderName: effect.message.senderName
33432
+ });
33433
+ }
33434
+ if (effect.type === "notification" && effect.notification) {
33435
+ const bubbleContent = effect.notification.bubbleContent ?? formatNotificationBubbleFallback(effect.notification.title, effect.notification.body);
33436
+ const flattened = typeof bubbleContent === "string" ? bubbleContent.trim() : flattenContent(bubbleContent).trim();
33437
+ if (!flattened && (!Array.isArray(bubbleContent) || bubbleContent.length === 0)) return null;
33438
+ const role = effect.notification.bubbleRole === "assistant" || effect.notification.bubbleRole === "user" ? effect.notification.bubbleRole : "system";
33439
+ if (role === "system") {
33440
+ return buildRuntimeSystemChatMessage({
33441
+ content: bubbleContent,
33442
+ kind: effect.notification.bubbleKind,
33443
+ senderName: effect.notification.bubbleSenderName
33444
+ });
33445
+ }
33446
+ return buildChatMessage({
33447
+ role,
33448
+ content: bubbleContent,
33449
+ kind: effect.notification.bubbleKind,
33450
+ senderName: effect.notification.bubbleSenderName
33451
+ });
33452
+ }
33453
+ if (effect.type === "toast" && effect.toast?.message) {
33454
+ return buildRuntimeSystemChatMessage({ content: effect.toast.message });
33455
+ }
33456
+ return null;
33457
+ }
33115
33458
  function normalizeControlListResult(data) {
33116
33459
  if (data && typeof data === "object" && Array.isArray(data.options)) {
33117
33460
  return {
@@ -33178,9 +33521,17 @@ ${data.message || ""}`.trim();
33178
33521
  }
33179
33522
  return String(value);
33180
33523
  }
33524
+ function formatNotificationBubbleFallback(title, body) {
33525
+ const cleanTitle = typeof title === "string" ? title.trim() : "";
33526
+ const cleanBody = String(body || "").trim();
33527
+ if (cleanTitle && cleanBody) return `${cleanTitle}
33528
+ ${cleanBody}`;
33529
+ return cleanTitle || cleanBody;
33530
+ }
33181
33531
  var fs32 = __toESM2(require("fs"));
33182
33532
  var path7 = __toESM2(require("path"));
33183
33533
  var os52 = __toESM2(require("os"));
33534
+ init_chat_message_normalization();
33184
33535
  var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
33185
33536
  var RETAIN_DAYS = 30;
33186
33537
  var CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
@@ -33386,11 +33737,11 @@ ${data.message || ""}`.trim();
33386
33737
  this.appendNewMessages(
33387
33738
  agentType,
33388
33739
  [{
33389
- role: "system",
33390
- kind: "system",
33391
- content,
33392
- receivedAt: options.receivedAt,
33393
- senderName: options.senderName,
33740
+ ...buildRuntimeSystemChatMessage({
33741
+ content,
33742
+ receivedAt: options.receivedAt,
33743
+ senderName: options.senderName
33744
+ }),
33394
33745
  historyDedupKey: options.dedupKey
33395
33746
  }],
33396
33747
  options.sessionTitle,
@@ -33741,6 +34092,7 @@ ${data.message || ""}`.trim();
33741
34092
  })
33742
34093
  };
33743
34094
  }
34095
+ init_chat_message_normalization();
33744
34096
  var ExtensionProviderInstance = class {
33745
34097
  type;
33746
34098
  category = "extension";
@@ -33947,8 +34299,8 @@ ${data.message || ""}`.trim();
33947
34299
  if (this.appliedEffectKeys.has(effectKey)) continue;
33948
34300
  this.appliedEffectKeys.add(effectKey);
33949
34301
  if (effect.persist !== false) {
33950
- const persisted = this.getPersistedEffectContent(effect);
33951
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
34302
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
34303
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
33952
34304
  }
33953
34305
  if (effect.type === "message" && effect.message) {
33954
34306
  this.pushEvent({
@@ -33983,34 +34335,42 @@ ${data.message || ""}`.trim();
33983
34335
  }
33984
34336
  }
33985
34337
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
33986
- const normalizedContent = String(content || "").trim();
33987
- if (!normalizedContent) return;
34338
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
34339
+ content,
34340
+ receivedAt,
34341
+ timestamp: receivedAt
34342
+ }), dedupKey);
34343
+ }
34344
+ appendRuntimeMessage(message, dedupKey) {
34345
+ const normalizedMessage = buildChatMessage({
34346
+ ...message,
34347
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
34348
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
34349
+ });
34350
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
34351
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
33988
34352
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
33989
34353
  this.runtimeMessages.push({
33990
34354
  key: dedupKey,
33991
- message: {
33992
- role: "system",
33993
- senderName: "System",
33994
- content: normalizedContent,
33995
- receivedAt,
33996
- timestamp: receivedAt
33997
- }
34355
+ message: normalizedMessage
33998
34356
  });
33999
34357
  if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
34000
- this.historyWriter.appendNewMessages(
34001
- this.type,
34002
- [{
34003
- role: "system",
34004
- senderName: "System",
34005
- content: normalizedContent,
34006
- kind: "system",
34007
- receivedAt,
34008
- historyDedupKey: dedupKey
34009
- }],
34010
- this.chatTitle || this.agentName || this.provider.name,
34011
- this.instanceId,
34012
- this.chatId || this.instanceId
34013
- );
34358
+ if (normalizedContent) {
34359
+ this.historyWriter.appendNewMessages(
34360
+ this.type,
34361
+ [{
34362
+ role: normalizedMessage.role,
34363
+ senderName: normalizedMessage.senderName,
34364
+ kind: normalizedMessage.kind,
34365
+ content: normalizedContent,
34366
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
34367
+ historyDedupKey: dedupKey
34368
+ }],
34369
+ this.chatTitle || this.agentName || this.provider.name,
34370
+ this.instanceId,
34371
+ this.chatId || this.instanceId
34372
+ );
34373
+ }
34014
34374
  }
34015
34375
  /**
34016
34376
  * Assign stable receivedAt to extension messages.
@@ -34027,16 +34387,16 @@ ${data.message || ""}`.trim();
34027
34387
  nextHashes.set(hash2, msg.receivedAt);
34028
34388
  }
34029
34389
  this.prevMessageHashes = nextHashes;
34030
- return messages;
34390
+ return normalizeChatMessages(messages);
34031
34391
  }
34032
34392
  mergeConversationMessages(messages) {
34033
- if (this.runtimeMessages.length === 0) return messages;
34034
- return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34393
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(messages);
34394
+ return normalizeChatMessages([...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34035
34395
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
34036
34396
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
34037
34397
  if (aTime !== bTime) return aTime - bTime;
34038
34398
  return a.index - b2.index;
34039
- }).map((entry) => entry.message);
34399
+ }).map((entry) => entry.message));
34040
34400
  }
34041
34401
  getPersistedEffectContent(effect) {
34042
34402
  if (effect.type === "message") {
@@ -34144,6 +34504,7 @@ ${effect.notification.body || ""}`.trim();
34144
34504
  if (cleanMessage) lines.push(cleanMessage);
34145
34505
  return lines.join("\n");
34146
34506
  }
34507
+ init_chat_message_normalization();
34147
34508
  var IdeProviderInstance = class {
34148
34509
  type;
34149
34510
  category = "ide";
@@ -34524,8 +34885,8 @@ ${effect.notification.body || ""}`.trim();
34524
34885
  if (this.appliedEffectKeys.has(effectKey)) continue;
34525
34886
  this.appliedEffectKeys.add(effectKey);
34526
34887
  if (effect.persist !== false) {
34527
- const persisted = this.getPersistedEffectContent(effect);
34528
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
34888
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
34889
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
34529
34890
  }
34530
34891
  if (effect.type === "message" && effect.message) {
34531
34892
  this.pushEvent({
@@ -34560,8 +34921,20 @@ ${effect.notification.body || ""}`.trim();
34560
34921
  }
34561
34922
  }
34562
34923
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
34563
- const normalizedContent = String(content || "").trim();
34564
- if (!normalizedContent) return;
34924
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
34925
+ content,
34926
+ receivedAt,
34927
+ timestamp: receivedAt
34928
+ }), dedupKey);
34929
+ }
34930
+ appendRuntimeMessage(message, dedupKey) {
34931
+ const normalizedMessage = buildChatMessage({
34932
+ ...message,
34933
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
34934
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
34935
+ });
34936
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
34937
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
34565
34938
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
34566
34939
  if (!this.cachedChat) {
34567
34940
  this.cachedChat = {
@@ -34575,38 +34948,34 @@ ${effect.notification.body || ""}`.trim();
34575
34948
  }
34576
34949
  this.runtimeMessages.push({
34577
34950
  key: dedupKey,
34578
- message: {
34579
- role: "system",
34580
- senderName: "System",
34581
- content: normalizedContent,
34582
- receivedAt,
34583
- timestamp: receivedAt
34584
- }
34951
+ message: normalizedMessage
34585
34952
  });
34586
34953
  if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
34587
- this.historyWriter.appendNewMessages(
34588
- this.type,
34589
- [{
34590
- role: "system",
34591
- senderName: "System",
34592
- content: normalizedContent,
34593
- kind: "system",
34594
- receivedAt,
34595
- historyDedupKey: dedupKey
34596
- }],
34597
- this.cachedChat?.title || this.provider.name,
34598
- this.instanceId,
34599
- this.cachedChat?.id || this.instanceId
34600
- );
34954
+ if (normalizedContent) {
34955
+ this.historyWriter.appendNewMessages(
34956
+ this.type,
34957
+ [{
34958
+ role: normalizedMessage.role,
34959
+ senderName: normalizedMessage.senderName,
34960
+ kind: normalizedMessage.kind,
34961
+ content: normalizedContent,
34962
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
34963
+ historyDedupKey: dedupKey
34964
+ }],
34965
+ this.cachedChat?.title || this.provider.name,
34966
+ this.instanceId,
34967
+ this.cachedChat?.id || this.instanceId
34968
+ );
34969
+ }
34601
34970
  }
34602
34971
  mergeConversationMessages(messages) {
34603
- if (this.runtimeMessages.length === 0) return messages;
34604
- return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34972
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(messages);
34973
+ return normalizeChatMessages([...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34605
34974
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
34606
34975
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
34607
34976
  if (aTime !== bTime) return aTime - bTime;
34608
34977
  return a.index - b2.index;
34609
- }).map((entry) => entry.message);
34978
+ }).map((entry) => entry.message));
34610
34979
  }
34611
34980
  getPersistedEffectContent(effect) {
34612
34981
  if (effect.type === "message") {
@@ -35494,215 +35863,6 @@ ${effect.notification.body || ""}`.trim();
35494
35863
  }
35495
35864
  }
35496
35865
  init_logger();
35497
- function normalizeInputEnvelope(input) {
35498
- const normalized = normalizeInputEnvelopePayload(input);
35499
- const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
35500
- return {
35501
- parts: normalized.parts,
35502
- textFallback,
35503
- ...normalized.metadata ? { metadata: normalized.metadata } : {}
35504
- };
35505
- }
35506
- function normalizeMessageParts(content) {
35507
- if (typeof content === "string") return [{ type: "text", text: content }];
35508
- if (!Array.isArray(content)) {
35509
- if (content && typeof content === "object" && typeof content.text === "string") {
35510
- return [{ type: "text", text: String(content.text) }];
35511
- }
35512
- return [];
35513
- }
35514
- const parts = [];
35515
- for (const raw of content) {
35516
- if (typeof raw === "string") {
35517
- parts.push({ type: "text", text: raw });
35518
- continue;
35519
- }
35520
- if (!raw || typeof raw !== "object") continue;
35521
- const part = normalizeMessagePartObject(raw);
35522
- if (part) parts.push(part);
35523
- }
35524
- return parts;
35525
- }
35526
- function flattenMessageParts(parts) {
35527
- return parts.map((part) => {
35528
- if (part.type === "text") return part.text;
35529
- if (part.type === "resource") return part.resource.text || "";
35530
- return "";
35531
- }).filter((value) => value.length > 0).join("\n");
35532
- }
35533
- function normalizeInputEnvelopePayload(input) {
35534
- if (typeof input === "string") {
35535
- return { parts: [{ type: "text", text: input }], textFallback: input };
35536
- }
35537
- if (!input || typeof input !== "object") {
35538
- return { parts: [], textFallback: "" };
35539
- }
35540
- const record2 = input;
35541
- const nestedInput = record2.input;
35542
- if (nestedInput && typeof nestedInput === "object") {
35543
- const nested = nestedInput;
35544
- return {
35545
- parts: normalizeInputParts(nested.parts ?? nested.prompt),
35546
- textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
35547
- metadata: normalizeInputMetadata(nested.metadata)
35548
- };
35549
- }
35550
- const directText = typeof record2.text === "string" ? record2.text : typeof record2.message === "string" ? record2.message : void 0;
35551
- if (directText !== void 0) {
35552
- return { parts: [{ type: "text", text: directText }], textFallback: directText };
35553
- }
35554
- const directParts = normalizeInputParts(record2.parts ?? record2.prompt);
35555
- return {
35556
- parts: directParts,
35557
- textFallback: typeof record2.textFallback === "string" ? record2.textFallback : void 0,
35558
- metadata: normalizeInputMetadata(record2.metadata)
35559
- };
35560
- }
35561
- function normalizeInputMetadata(value) {
35562
- if (!value || typeof value !== "object") return void 0;
35563
- const record2 = value;
35564
- const metadata = {};
35565
- if (record2.source === "dashboard" || record2.source === "shortcut_api" || record2.source === "provider_script" || record2.source === "session_replay") {
35566
- metadata.source = record2.source;
35567
- }
35568
- if (typeof record2.clientTimestamp === "number" && Number.isFinite(record2.clientTimestamp)) {
35569
- metadata.clientTimestamp = record2.clientTimestamp;
35570
- }
35571
- return Object.keys(metadata).length > 0 ? metadata : void 0;
35572
- }
35573
- function normalizeInputParts(value) {
35574
- if (!Array.isArray(value)) return [];
35575
- const parts = [];
35576
- for (const raw of value) {
35577
- if (typeof raw === "string") {
35578
- parts.push({ type: "text", text: raw });
35579
- continue;
35580
- }
35581
- if (!raw || typeof raw !== "object") continue;
35582
- const part = normalizeInputPartObject(raw);
35583
- if (part) parts.push(part);
35584
- }
35585
- return parts;
35586
- }
35587
- function normalizeInputPartObject(raw) {
35588
- const type = raw.type;
35589
- if (type === "text" && typeof raw.text === "string") {
35590
- return { type, text: raw.text };
35591
- }
35592
- if (type === "image" && typeof raw.mimeType === "string") {
35593
- return {
35594
- type,
35595
- mimeType: raw.mimeType,
35596
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35597
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35598
- ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
35599
- };
35600
- }
35601
- if (type === "audio" && typeof raw.mimeType === "string") {
35602
- return {
35603
- type,
35604
- mimeType: raw.mimeType,
35605
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35606
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35607
- ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
35608
- };
35609
- }
35610
- if (type === "video" && typeof raw.mimeType === "string") {
35611
- return {
35612
- type,
35613
- mimeType: raw.mimeType,
35614
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35615
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35616
- ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
35617
- };
35618
- }
35619
- if (type === "resource" && typeof raw.uri === "string") {
35620
- return {
35621
- type,
35622
- uri: raw.uri,
35623
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35624
- ...typeof raw.name === "string" ? { name: raw.name } : {},
35625
- ...typeof raw.text === "string" ? { text: raw.text } : {},
35626
- ...typeof raw.data === "string" ? { data: raw.data } : {}
35627
- };
35628
- }
35629
- if (type === "resource_link" && typeof raw.uri === "string") {
35630
- return {
35631
- type: "resource",
35632
- uri: raw.uri,
35633
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35634
- ...typeof raw.name === "string" ? { name: raw.name } : {}
35635
- };
35636
- }
35637
- return null;
35638
- }
35639
- function normalizeMessagePartObject(raw) {
35640
- const type = raw.type;
35641
- if (type === "text" && typeof raw.text === "string") {
35642
- return { type, text: raw.text };
35643
- }
35644
- if (type === "image" && typeof raw.mimeType === "string") {
35645
- return {
35646
- type,
35647
- mimeType: raw.mimeType,
35648
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35649
- ...typeof raw.data === "string" ? { data: raw.data } : {}
35650
- };
35651
- }
35652
- if (type === "audio" && typeof raw.mimeType === "string") {
35653
- return {
35654
- type,
35655
- mimeType: raw.mimeType,
35656
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35657
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35658
- ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
35659
- };
35660
- }
35661
- if (type === "video" && typeof raw.mimeType === "string") {
35662
- return {
35663
- type,
35664
- mimeType: raw.mimeType,
35665
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35666
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35667
- ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
35668
- };
35669
- }
35670
- if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
35671
- return {
35672
- type,
35673
- uri: raw.uri,
35674
- name: raw.name,
35675
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35676
- ...typeof raw.size === "number" ? { size: raw.size } : {}
35677
- };
35678
- }
35679
- if (type === "resource" && raw.resource && typeof raw.resource === "object") {
35680
- const resource = raw.resource;
35681
- if (typeof resource.uri !== "string") return null;
35682
- return {
35683
- type,
35684
- resource: {
35685
- uri: resource.uri,
35686
- ...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
35687
- ...typeof resource.text === "string" ? { text: resource.text } : {},
35688
- ...typeof resource.blob === "string" ? { blob: resource.blob } : {}
35689
- }
35690
- };
35691
- }
35692
- return null;
35693
- }
35694
- function flattenInputParts(parts) {
35695
- return parts.map((part) => {
35696
- if (part.type === "text") return part.text;
35697
- if (part.type === "audio") return part.transcript || "";
35698
- if (part.type === "resource") return part.text || "";
35699
- return "";
35700
- }).filter((value) => value.length > 0).join("\n");
35701
- }
35702
- function flattenContent(content) {
35703
- if (typeof content === "string") return content;
35704
- return flattenMessageParts(normalizeMessageParts(content));
35705
- }
35706
35866
  init_logger();
35707
35867
  var NORMAL_TRACE_BUFFER_SIZE = 200;
35708
35868
  var DEV_TRACE_BUFFER_SIZE = 1e3;
@@ -35826,6 +35986,7 @@ ${effect.notification.body || ""}`.trim();
35826
35986
  function createInteractionId(prefix = "ix") {
35827
35987
  return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
35828
35988
  }
35989
+ init_chat_message_normalization();
35829
35990
  var RECENT_SEND_WINDOW_MS = 1200;
35830
35991
  var recentSendByTarget = /* @__PURE__ */ new Map();
35831
35992
  function hashSignatureParts2(parts) {
@@ -35955,7 +36116,7 @@ ${effect.notification.body || ""}`.trim();
35955
36116
  }
35956
36117
  function normalizeReadChatMessages(payload) {
35957
36118
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
35958
- return messages;
36119
+ return normalizeChatMessages(messages);
35959
36120
  }
35960
36121
  function deriveHistoryDedupKey(message) {
35961
36122
  const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
@@ -38285,6 +38446,7 @@ ${effect.notification.body || ""}`.trim();
38285
38446
  var import_node_module = require("module");
38286
38447
  init_provider_cli_adapter();
38287
38448
  init_logger();
38449
+ init_chat_message_normalization();
38288
38450
  var CachedDatabaseSync = null;
38289
38451
  function getDatabaseSync() {
38290
38452
  if (CachedDatabaseSync) return CachedDatabaseSync;
@@ -38779,8 +38941,8 @@ ${effect.notification.body || ""}`.trim();
38779
38941
  if (this.appliedEffectKeys.has(effectKey)) continue;
38780
38942
  this.appliedEffectKeys.add(effectKey);
38781
38943
  if (effect.persist !== false) {
38782
- const persisted = this.getPersistedEffectContent(effect);
38783
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
38944
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
38945
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
38784
38946
  }
38785
38947
  if (effect.type === "message" && effect.message) {
38786
38948
  const content = typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content);
@@ -38904,44 +39066,53 @@ ${effect.notification.body || ""}`.trim();
38904
39066
  );
38905
39067
  }
38906
39068
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
38907
- const normalizedContent = String(content || "").trim();
38908
- if (!normalizedContent) return;
39069
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
39070
+ content,
39071
+ receivedAt,
39072
+ timestamp: receivedAt
39073
+ }), dedupKey);
39074
+ }
39075
+ appendRuntimeMessage(message, dedupKey) {
39076
+ const normalizedMessage = buildChatMessage({
39077
+ ...message,
39078
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
39079
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
39080
+ });
39081
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
39082
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
38909
39083
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
38910
39084
  this.runtimeMessages.push({
38911
39085
  key: dedupKey,
38912
- message: {
38913
- role: "system",
38914
- senderName: "System",
38915
- content: normalizedContent,
38916
- receivedAt,
38917
- timestamp: receivedAt
38918
- }
39086
+ message: normalizedMessage
38919
39087
  });
38920
39088
  if (this.runtimeMessages.length > 50) {
38921
39089
  this.runtimeMessages = this.runtimeMessages.slice(-50);
38922
39090
  }
38923
- this.historyWriter.appendNewMessages(
38924
- this.type,
38925
- [{
38926
- role: "system",
38927
- senderName: "System",
38928
- content: normalizedContent,
38929
- receivedAt,
38930
- historyDedupKey: dedupKey
38931
- }],
38932
- this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
38933
- this.instanceId,
38934
- this.providerSessionId
38935
- );
39091
+ if (normalizedContent) {
39092
+ this.historyWriter.appendNewMessages(
39093
+ this.type,
39094
+ [{
39095
+ role: normalizedMessage.role,
39096
+ senderName: normalizedMessage.senderName,
39097
+ kind: normalizedMessage.kind,
39098
+ content: normalizedContent,
39099
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
39100
+ historyDedupKey: dedupKey
39101
+ }],
39102
+ this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
39103
+ this.instanceId,
39104
+ this.providerSessionId
39105
+ );
39106
+ }
38936
39107
  }
38937
39108
  mergeConversationMessages(parsedMessages) {
38938
- if (this.runtimeMessages.length === 0) return parsedMessages;
38939
- return [...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
39109
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
39110
+ return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
38940
39111
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
38941
39112
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
38942
39113
  if (aTime !== bTime) return aTime - bTime;
38943
39114
  return a.index - b2.index;
38944
- }).map((entry) => entry.message);
39115
+ }).map((entry) => entry.message));
38945
39116
  }
38946
39117
  formatApprovalRequestMessage(modalMessage, buttons) {
38947
39118
  const lines = ["Approval requested"];
@@ -39010,6 +39181,7 @@ ${effect.notification.body || ""}`.trim();
39010
39181
  var import_stream = require("stream");
39011
39182
  var import_child_process5 = require("child_process");
39012
39183
  var import_sdk = (init_acp(), __toCommonJS(acp_exports));
39184
+ init_chat_message_normalization();
39013
39185
  init_logger();
39014
39186
  function getPromptCapabilityFlags(agentCapabilities) {
39015
39187
  const prompt = agentCapabilities?.promptCapabilities || {};
@@ -39175,24 +39347,21 @@ ${effect.notification.body || ""}`.trim();
39175
39347
  }
39176
39348
  getState() {
39177
39349
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
39178
- const recentMessages = this.messages.slice(-50).map((m) => {
39350
+ const recentMessages = normalizeChatMessages(this.messages.slice(-50).map((m) => {
39179
39351
  const content = this.truncateContent(m.content);
39180
- return {
39181
- role: m.role,
39182
- content,
39183
- timestamp: m.timestamp,
39184
- toolCalls: m.toolCalls
39185
- };
39186
- });
39352
+ return buildChatMessage({
39353
+ ...m,
39354
+ content
39355
+ });
39356
+ }));
39187
39357
  if (this.currentStatus === "generating" && (this.partialContent || this.partialBlocks.length > 0)) {
39188
39358
  const blocks = this.buildPartialBlocks();
39189
39359
  if (blocks.length > 0) {
39190
- recentMessages.push({
39191
- role: "assistant",
39360
+ recentMessages.push(buildAssistantChatMessage({
39192
39361
  content: blocks,
39193
39362
  timestamp: Date.now(),
39194
39363
  toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
39195
- });
39364
+ }));
39196
39365
  }
39197
39366
  }
39198
39367
  return {
@@ -39205,7 +39374,7 @@ ${effect.notification.body || ""}`.trim();
39205
39374
  id: this.sessionId || `${this.type}_${this.workingDir}`,
39206
39375
  title: `${this.provider.name} \xB7 ${dirName}`,
39207
39376
  status: this.currentStatus,
39208
- messages: recentMessages,
39377
+ messages: normalizeChatMessages(recentMessages),
39209
39378
  activeModal: this.currentStatus === "waiting_approval" ? {
39210
39379
  message: this.activeToolCalls.find((t) => t.status === "running")?.name || "Permission requested",
39211
39380
  buttons: ["Approve", "Reject"]
@@ -39737,11 +39906,10 @@ ${effect.notification.body || ""}`.trim();
39737
39906
  if (b2.type === "resource") return { type: "resource", resource: b2.resource };
39738
39907
  return { type: "text", text: flattenContent([b2]) };
39739
39908
  }) : [{ type: "text", text }];
39740
- this.messages.push({
39741
- role: "user",
39909
+ this.messages.push(buildUserChatMessage({
39742
39910
  content: contentBlocks && contentBlocks.length > 0 ? contentBlocks : text,
39743
39911
  timestamp: Date.now()
39744
- });
39912
+ }));
39745
39913
  this.currentStatus = "generating";
39746
39914
  this.partialContent = "";
39747
39915
  this.partialBlocks = [];
@@ -39911,11 +40079,11 @@ ${effect.notification.body || ""}`.trim();
39911
40079
  content = m.content.filter((p) => p.type === "text").map((p) => p.text || "").join("\n");
39912
40080
  }
39913
40081
  if (content.trim()) {
39914
- this.messages.push({
40082
+ this.messages.push(buildChatMessage({
39915
40083
  role: m.role || "assistant",
39916
40084
  content: content.trim(),
39917
40085
  timestamp: Date.now()
39918
- });
40086
+ }));
39919
40087
  this.partialContent = "";
39920
40088
  }
39921
40089
  }
@@ -39991,12 +40159,11 @@ ${effect.notification.body || ""}`.trim();
39991
40159
  return b2;
39992
40160
  }).filter((b2) => b2.type !== "text" || b2.type === "text" && b2.text.trim());
39993
40161
  if (finalBlocks.length > 0) {
39994
- this.messages.push({
39995
- role: "assistant",
40162
+ this.messages.push(buildAssistantChatMessage({
39996
40163
  content: finalBlocks.length === 1 && finalBlocks[0].type === "text" ? finalBlocks[0].text : finalBlocks,
39997
40164
  timestamp: Date.now(),
39998
40165
  toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
39999
- });
40166
+ }));
40000
40167
  }
40001
40168
  this.partialContent = "";
40002
40169
  this.partialBlocks = [];
@@ -40056,11 +40223,10 @@ ${effect.notification.body || ""}`.trim();
40056
40223
  appendSystemMessage(content, timestamp = Date.now()) {
40057
40224
  const normalizedContent = String(content || "").trim();
40058
40225
  if (!normalizedContent) return;
40059
- this.messages.push({
40060
- role: "system",
40226
+ this.messages.push(buildRuntimeSystemChatMessage({
40061
40227
  content: normalizedContent,
40062
40228
  timestamp
40063
- });
40229
+ }));
40064
40230
  if (this.messages.length > 200) {
40065
40231
  this.messages = this.messages.slice(-100);
40066
40232
  }
@@ -44689,6 +44855,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44689
44855
  }
44690
44856
  };
44691
44857
  init_logger();
44858
+ init_chat_message_normalization();
44692
44859
  var AgentStreamPoller = class {
44693
44860
  deps;
44694
44861
  timer = null;
@@ -44844,12 +45011,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44844
45011
  type: "message",
44845
45012
  id: effectId,
44846
45013
  persist: true,
44847
- message: {
44848
- role: "system",
44849
- senderName: "System",
44850
- kind: "system",
45014
+ message: buildRuntimeSystemChatMessage({
44851
45015
  content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel)
44852
- }
45016
+ })
44853
45017
  }
44854
45018
  ]
44855
45019
  };
@@ -45091,6 +45255,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45091
45255
  this.eventListeners = [];
45092
45256
  }
45093
45257
  };
45258
+ init_chat_message_normalization();
45094
45259
  var fs10 = __toESM2(require("fs"));
45095
45260
  var path18 = __toESM2(require("path"));
45096
45261
  var os18 = __toESM2(require("os"));