@adhdev/daemon-standalone 0.8.59 → 0.8.61

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 || "";
@@ -29160,6 +29217,7 @@ var require_dist2 = __commonJS({
29160
29217
  init_terminal_screen();
29161
29218
  init_pty_transport();
29162
29219
  init_provider_cli_shared();
29220
+ init_chat_message_normalization();
29163
29221
  init_provider_cli_parse();
29164
29222
  init_provider_cli_config();
29165
29223
  init_provider_cli_runtime();
@@ -29270,6 +29328,7 @@ var require_dist2 = __commonJS({
29270
29328
  static MAX_TRACE_ENTRIES = 250;
29271
29329
  providerResolutionMeta;
29272
29330
  static IDLE_FINISH_CONFIRM_MS = 2e3;
29331
+ static HERMES_IDLE_FINISH_CONFIRM_MS = 5e3;
29273
29332
  static STATUS_ACTIVITY_HOLD_MS = 2e3;
29274
29333
  static FINISH_RETRY_DELAY_MS = 300;
29275
29334
  static MAX_FINISH_RETRIES = 2;
@@ -29277,6 +29336,12 @@ var require_dist2 = __commonJS({
29277
29336
  this.messages = [...this.committedMessages];
29278
29337
  this.structuredMessages = [...this.committedMessages];
29279
29338
  }
29339
+ getIdleFinishConfirmMs() {
29340
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
29341
+ }
29342
+ getStatusActivityHoldMs() {
29343
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
29344
+ }
29280
29345
  setStatus(status, trigger) {
29281
29346
  const prev = this.currentStatus;
29282
29347
  if (prev === status) return;
@@ -29299,6 +29364,7 @@ var require_dist2 = __commonJS({
29299
29364
  }
29300
29365
  armIdleFinishCandidate(assistantLength) {
29301
29366
  const now = Date.now();
29367
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
29302
29368
  this.idleFinishCandidate = {
29303
29369
  armedAt: now,
29304
29370
  lastOutputAt: this.lastOutputAt,
@@ -29307,7 +29373,7 @@ var require_dist2 = __commonJS({
29307
29373
  assistantLength
29308
29374
  };
29309
29375
  this.recordTrace("idle_candidate_armed", {
29310
- confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
29376
+ confirmMs: idleFinishConfirmMs,
29311
29377
  candidate: this.idleFinishCandidate,
29312
29378
  ...buildCliTraceParseSnapshot({
29313
29379
  accumulatedBuffer: this.accumulatedBuffer,
@@ -29322,7 +29388,7 @@ var require_dist2 = __commonJS({
29322
29388
  this.settleTimer = null;
29323
29389
  this.settledBuffer = this.recentOutputBuffer;
29324
29390
  this.evaluateSettled();
29325
- }, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
29391
+ }, idleFinishConfirmMs);
29326
29392
  }
29327
29393
  recordTrace(type, payload = {}) {
29328
29394
  const entry = {
@@ -29701,7 +29767,8 @@ var require_dist2 = __commonJS({
29701
29767
  hasRecentInteractiveActivity(now) {
29702
29768
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
29703
29769
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : Number.MAX_SAFE_INTEGER;
29704
- return quietForMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS || screenStableMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
29770
+ const holdMs = this.getStatusActivityHoldMs();
29771
+ return quietForMs < holdMs || screenStableMs < holdMs;
29705
29772
  }
29706
29773
  getStartupConfirmationModal(screenText) {
29707
29774
  const text = sanitizeTerminalText(String(screenText || ""));
@@ -29853,6 +29920,7 @@ var require_dist2 = __commonJS({
29853
29920
  clearPendingScriptStatus();
29854
29921
  }
29855
29922
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
29923
+ const statusActivityHoldMs = this.getStatusActivityHoldMs();
29856
29924
  const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
29857
29925
  if (shouldHoldGenerating) {
29858
29926
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
@@ -29868,7 +29936,7 @@ var require_dist2 = __commonJS({
29868
29936
  recentInteractiveActivity,
29869
29937
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
29870
29938
  lastScreenChangeAt: this.lastScreenChangeAt,
29871
- holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
29939
+ holdMs: statusActivityHoldMs,
29872
29940
  ...buildCliTraceParseSnapshot({
29873
29941
  accumulatedBuffer: this.accumulatedBuffer,
29874
29942
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -29957,11 +30025,12 @@ var require_dist2 = __commonJS({
29957
30025
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
29958
30026
  const hasAssistantTurn = !!lastParsedAssistant;
29959
30027
  const assistantLength = lastParsedAssistant?.content?.length || 0;
29960
- const idleQuietThresholdMs = Math.max(2e3, this.timeouts.outputSettle);
29961
- const idleStableThresholdMs = 2e3;
30028
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
30029
+ const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
30030
+ const idleStableThresholdMs = idleFinishConfirmMs;
29962
30031
  const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
29963
30032
  const candidate = this.idleFinishCandidate;
29964
- const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
30033
+ const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
29965
30034
  const canFinishImmediately = idleReady && candidateQuiet;
29966
30035
  this.recordTrace("idle_decision", {
29967
30036
  visibleIdlePrompt,
@@ -29973,7 +30042,7 @@ var require_dist2 = __commonJS({
29973
30042
  idleQuietThresholdMs,
29974
30043
  idleStableThresholdMs,
29975
30044
  idleReady,
29976
- idleFinishConfirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
30045
+ idleFinishConfirmMs,
29977
30046
  idleFinishCandidate: candidate,
29978
30047
  candidateQuiet,
29979
30048
  canFinishImmediately,
@@ -30206,11 +30275,10 @@ var require_dist2 = __commonJS({
30206
30275
  );
30207
30276
  const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
30208
30277
  if (parsed && Array.isArray(parsed.messages)) {
30209
- const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => ({
30278
+ const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
30210
30279
  ...message,
30211
30280
  id: message.id || `msg_${index}`,
30212
30281
  index: typeof message.index === "number" ? message.index : index,
30213
- kind: message.kind || "standard",
30214
30282
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30215
30283
  })) : hydrateCliParsedMessages(parsed.messages, {
30216
30284
  committedMessages: this.committedMessages,
@@ -30231,13 +30299,11 @@ var require_dist2 = __commonJS({
30231
30299
  id: "cli_session",
30232
30300
  status: this.currentStatus,
30233
30301
  title: this.cliName,
30234
- messages: messages.slice(-50).map((message, index) => ({
30235
- id: `msg_${index}`,
30236
- role: message.role,
30237
- content: message.content,
30238
- timestamp: message.timestamp,
30239
- index,
30240
- kind: "standard"
30302
+ messages: messages.slice(-50).map((message, index) => buildChatMessage({
30303
+ ...message,
30304
+ id: message.id || `msg_${index}`,
30305
+ index: typeof message.index === "number" ? message.index : index,
30306
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30241
30307
  })),
30242
30308
  activeModal: this.activeModal
30243
30309
  };
@@ -30860,6 +30926,7 @@ ${data.message || ""}`.trim();
30860
30926
  __export2(index_exports, {
30861
30927
  AcpProviderInstance: () => AcpProviderInstance,
30862
30928
  AgentStreamPoller: () => AgentStreamPoller,
30929
+ BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
30863
30930
  CdpDomHandlers: () => CdpDomHandlers,
30864
30931
  CliProviderInstance: () => CliProviderInstance,
30865
30932
  DAEMON_WS_PATH: () => DAEMON_WS_PATH,
@@ -30884,9 +30951,14 @@ ${data.message || ""}`.trim();
30884
30951
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
30885
30952
  VersionArchive: () => VersionArchive,
30886
30953
  appendRecentActivity: () => appendRecentActivity,
30954
+ buildAssistantChatMessage: () => buildAssistantChatMessage,
30955
+ buildChatMessage: () => buildChatMessage,
30887
30956
  buildMachineInfo: () => buildMachineInfo2,
30957
+ buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
30888
30958
  buildSessionEntries: () => buildSessionEntries,
30889
30959
  buildStatusSnapshot: () => buildStatusSnapshot2,
30960
+ buildSystemChatMessage: () => buildSystemChatMessage,
30961
+ buildUserChatMessage: () => buildUserChatMessage,
30890
30962
  clearDebugTrace: () => clearDebugTrace,
30891
30963
  configureDebugTraceStore: () => configureDebugTraceStore,
30892
30964
  connectCdpManager: () => connectCdpManager,
@@ -30918,6 +30990,7 @@ ${data.message || ""}`.trim();
30918
30990
  initDaemonComponents: () => initDaemonComponents2,
30919
30991
  installExtensions: () => installExtensions,
30920
30992
  installGlobalInterceptor: () => installGlobalInterceptor,
30993
+ isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
30921
30994
  isCdpConnected: () => isCdpConnected,
30922
30995
  isExtensionInstalled: () => isExtensionInstalled,
30923
30996
  isIdeRunning: () => isIdeRunning,
@@ -30936,6 +31009,9 @@ ${data.message || ""}`.trim();
30936
31009
  markSetupComplete: () => markSetupComplete,
30937
31010
  maybeRunDaemonUpgradeHelperFromEnv: () => maybeRunDaemonUpgradeHelperFromEnv2,
30938
31011
  normalizeActiveChatData: () => normalizeActiveChatData,
31012
+ normalizeChatMessage: () => normalizeChatMessage,
31013
+ normalizeChatMessageKind: () => normalizeChatMessageKind,
31014
+ normalizeChatMessages: () => normalizeChatMessages,
30939
31015
  normalizeInputEnvelope: () => normalizeInputEnvelope,
30940
31016
  normalizeManagedStatus: () => normalizeManagedStatus,
30941
31017
  normalizeMessageParts: () => normalizeMessageParts,
@@ -32917,6 +32993,215 @@ ${data.message || ""}`.trim();
32917
32993
  }
32918
32994
  };
32919
32995
  var crypto2 = __toESM2(require("crypto"));
32996
+ function normalizeInputEnvelope(input) {
32997
+ const normalized = normalizeInputEnvelopePayload(input);
32998
+ const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
32999
+ return {
33000
+ parts: normalized.parts,
33001
+ textFallback,
33002
+ ...normalized.metadata ? { metadata: normalized.metadata } : {}
33003
+ };
33004
+ }
33005
+ function normalizeMessageParts(content) {
33006
+ if (typeof content === "string") return [{ type: "text", text: content }];
33007
+ if (!Array.isArray(content)) {
33008
+ if (content && typeof content === "object" && typeof content.text === "string") {
33009
+ return [{ type: "text", text: String(content.text) }];
33010
+ }
33011
+ return [];
33012
+ }
33013
+ const parts = [];
33014
+ for (const raw of content) {
33015
+ if (typeof raw === "string") {
33016
+ parts.push({ type: "text", text: raw });
33017
+ continue;
33018
+ }
33019
+ if (!raw || typeof raw !== "object") continue;
33020
+ const part = normalizeMessagePartObject(raw);
33021
+ if (part) parts.push(part);
33022
+ }
33023
+ return parts;
33024
+ }
33025
+ function flattenMessageParts(parts) {
33026
+ return parts.map((part) => {
33027
+ if (part.type === "text") return part.text;
33028
+ if (part.type === "resource") return part.resource.text || "";
33029
+ return "";
33030
+ }).filter((value) => value.length > 0).join("\n");
33031
+ }
33032
+ function normalizeInputEnvelopePayload(input) {
33033
+ if (typeof input === "string") {
33034
+ return { parts: [{ type: "text", text: input }], textFallback: input };
33035
+ }
33036
+ if (!input || typeof input !== "object") {
33037
+ return { parts: [], textFallback: "" };
33038
+ }
33039
+ const record2 = input;
33040
+ const nestedInput = record2.input;
33041
+ if (nestedInput && typeof nestedInput === "object") {
33042
+ const nested = nestedInput;
33043
+ return {
33044
+ parts: normalizeInputParts(nested.parts ?? nested.prompt),
33045
+ textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
33046
+ metadata: normalizeInputMetadata(nested.metadata)
33047
+ };
33048
+ }
33049
+ const directText = typeof record2.text === "string" ? record2.text : typeof record2.message === "string" ? record2.message : void 0;
33050
+ if (directText !== void 0) {
33051
+ return { parts: [{ type: "text", text: directText }], textFallback: directText };
33052
+ }
33053
+ const directParts = normalizeInputParts(record2.parts ?? record2.prompt);
33054
+ return {
33055
+ parts: directParts,
33056
+ textFallback: typeof record2.textFallback === "string" ? record2.textFallback : void 0,
33057
+ metadata: normalizeInputMetadata(record2.metadata)
33058
+ };
33059
+ }
33060
+ function normalizeInputMetadata(value) {
33061
+ if (!value || typeof value !== "object") return void 0;
33062
+ const record2 = value;
33063
+ const metadata = {};
33064
+ if (record2.source === "dashboard" || record2.source === "shortcut_api" || record2.source === "provider_script" || record2.source === "session_replay") {
33065
+ metadata.source = record2.source;
33066
+ }
33067
+ if (typeof record2.clientTimestamp === "number" && Number.isFinite(record2.clientTimestamp)) {
33068
+ metadata.clientTimestamp = record2.clientTimestamp;
33069
+ }
33070
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
33071
+ }
33072
+ function normalizeInputParts(value) {
33073
+ if (!Array.isArray(value)) return [];
33074
+ const parts = [];
33075
+ for (const raw of value) {
33076
+ if (typeof raw === "string") {
33077
+ parts.push({ type: "text", text: raw });
33078
+ continue;
33079
+ }
33080
+ if (!raw || typeof raw !== "object") continue;
33081
+ const part = normalizeInputPartObject(raw);
33082
+ if (part) parts.push(part);
33083
+ }
33084
+ return parts;
33085
+ }
33086
+ function normalizeInputPartObject(raw) {
33087
+ const type = raw.type;
33088
+ if (type === "text" && typeof raw.text === "string") {
33089
+ return { type, text: raw.text };
33090
+ }
33091
+ if (type === "image" && typeof raw.mimeType === "string") {
33092
+ return {
33093
+ type,
33094
+ mimeType: raw.mimeType,
33095
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33096
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33097
+ ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
33098
+ };
33099
+ }
33100
+ if (type === "audio" && typeof raw.mimeType === "string") {
33101
+ return {
33102
+ type,
33103
+ mimeType: raw.mimeType,
33104
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33105
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33106
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
33107
+ };
33108
+ }
33109
+ if (type === "video" && typeof raw.mimeType === "string") {
33110
+ return {
33111
+ type,
33112
+ mimeType: raw.mimeType,
33113
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33114
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33115
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
33116
+ };
33117
+ }
33118
+ if (type === "resource" && typeof raw.uri === "string") {
33119
+ return {
33120
+ type,
33121
+ uri: raw.uri,
33122
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33123
+ ...typeof raw.name === "string" ? { name: raw.name } : {},
33124
+ ...typeof raw.text === "string" ? { text: raw.text } : {},
33125
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
33126
+ };
33127
+ }
33128
+ if (type === "resource_link" && typeof raw.uri === "string") {
33129
+ return {
33130
+ type: "resource",
33131
+ uri: raw.uri,
33132
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33133
+ ...typeof raw.name === "string" ? { name: raw.name } : {}
33134
+ };
33135
+ }
33136
+ return null;
33137
+ }
33138
+ function normalizeMessagePartObject(raw) {
33139
+ const type = raw.type;
33140
+ if (type === "text" && typeof raw.text === "string") {
33141
+ return { type, text: raw.text };
33142
+ }
33143
+ if (type === "image" && typeof raw.mimeType === "string") {
33144
+ return {
33145
+ type,
33146
+ mimeType: raw.mimeType,
33147
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33148
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
33149
+ };
33150
+ }
33151
+ if (type === "audio" && typeof raw.mimeType === "string") {
33152
+ return {
33153
+ type,
33154
+ mimeType: raw.mimeType,
33155
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33156
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33157
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
33158
+ };
33159
+ }
33160
+ if (type === "video" && typeof raw.mimeType === "string") {
33161
+ return {
33162
+ type,
33163
+ mimeType: raw.mimeType,
33164
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
33165
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
33166
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
33167
+ };
33168
+ }
33169
+ if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
33170
+ return {
33171
+ type,
33172
+ uri: raw.uri,
33173
+ name: raw.name,
33174
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
33175
+ ...typeof raw.size === "number" ? { size: raw.size } : {}
33176
+ };
33177
+ }
33178
+ if (type === "resource" && raw.resource && typeof raw.resource === "object") {
33179
+ const resource = raw.resource;
33180
+ if (typeof resource.uri !== "string") return null;
33181
+ return {
33182
+ type,
33183
+ resource: {
33184
+ uri: resource.uri,
33185
+ ...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
33186
+ ...typeof resource.text === "string" ? { text: resource.text } : {},
33187
+ ...typeof resource.blob === "string" ? { blob: resource.blob } : {}
33188
+ }
33189
+ };
33190
+ }
33191
+ return null;
33192
+ }
33193
+ function flattenInputParts(parts) {
33194
+ return parts.map((part) => {
33195
+ if (part.type === "text") return part.text;
33196
+ if (part.type === "audio") return part.transcript || "";
33197
+ if (part.type === "resource") return part.text || "";
33198
+ return "";
33199
+ }).filter((value) => value.length > 0).join("\n");
33200
+ }
33201
+ function flattenContent(content) {
33202
+ if (typeof content === "string") return content;
33203
+ return flattenMessageParts(normalizeMessageParts(content));
33204
+ }
32920
33205
  var DEFAULT_MONITOR_CONFIG = {
32921
33206
  approvalAlert: true,
32922
33207
  longGeneratingAlert: true,
@@ -33027,6 +33312,7 @@ ${data.message || ""}`.trim();
33027
33312
  }
33028
33313
  }
33029
33314
  };
33315
+ init_chat_message_normalization();
33030
33316
  function extractProviderControlValues(controls, data) {
33031
33317
  if (!data || typeof data !== "object") return void 0;
33032
33318
  const values = {};
@@ -33094,13 +33380,58 @@ ${data.message || ""}`.trim();
33094
33380
  level: raw.notification.level === "success" || raw.notification.level === "warning" ? raw.notification.level : "info",
33095
33381
  channels: Array.isArray(raw.notification.channels) ? raw.notification.channels.filter((channel) => channel === "bubble" || channel === "toast" || channel === "browser") : void 0,
33096
33382
  preferenceKey: raw.notification.preferenceKey === "disconnect" || raw.notification.preferenceKey === "completion" || raw.notification.preferenceKey === "approval" || raw.notification.preferenceKey === "browser" ? raw.notification.preferenceKey : void 0,
33097
- bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0
33383
+ bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0,
33384
+ bubbleKind: typeof raw.notification.bubbleKind === "string" ? raw.notification.bubbleKind : void 0,
33385
+ bubbleRole: raw.notification.bubbleRole === "assistant" || raw.notification.bubbleRole === "user" ? raw.notification.bubbleRole : raw.notification.bubbleRole === "system" ? "system" : void 0,
33386
+ bubbleSenderName: typeof raw.notification.bubbleSenderName === "string" ? raw.notification.bubbleSenderName : void 0
33098
33387
  }
33099
33388
  });
33100
33389
  }
33101
33390
  }
33102
33391
  return effects;
33103
33392
  }
33393
+ function buildPersistedProviderEffectMessage(effect) {
33394
+ if (!effect) return null;
33395
+ if (effect.type === "message" && effect.message) {
33396
+ const role = effect.message.role === "assistant" || effect.message.role === "user" ? effect.message.role : "system";
33397
+ if (role === "system") {
33398
+ return buildRuntimeSystemChatMessage({
33399
+ content: effect.message.content,
33400
+ kind: effect.message.kind,
33401
+ senderName: effect.message.senderName
33402
+ });
33403
+ }
33404
+ return buildChatMessage({
33405
+ role,
33406
+ content: effect.message.content,
33407
+ kind: effect.message.kind,
33408
+ senderName: effect.message.senderName
33409
+ });
33410
+ }
33411
+ if (effect.type === "notification" && effect.notification) {
33412
+ const bubbleContent = effect.notification.bubbleContent ?? formatNotificationBubbleFallback(effect.notification.title, effect.notification.body);
33413
+ const flattened = typeof bubbleContent === "string" ? bubbleContent.trim() : flattenContent(bubbleContent).trim();
33414
+ if (!flattened && (!Array.isArray(bubbleContent) || bubbleContent.length === 0)) return null;
33415
+ const role = effect.notification.bubbleRole === "assistant" || effect.notification.bubbleRole === "user" ? effect.notification.bubbleRole : "system";
33416
+ if (role === "system") {
33417
+ return buildRuntimeSystemChatMessage({
33418
+ content: bubbleContent,
33419
+ kind: effect.notification.bubbleKind,
33420
+ senderName: effect.notification.bubbleSenderName
33421
+ });
33422
+ }
33423
+ return buildChatMessage({
33424
+ role,
33425
+ content: bubbleContent,
33426
+ kind: effect.notification.bubbleKind,
33427
+ senderName: effect.notification.bubbleSenderName
33428
+ });
33429
+ }
33430
+ if (effect.type === "toast" && effect.toast?.message) {
33431
+ return buildRuntimeSystemChatMessage({ content: effect.toast.message });
33432
+ }
33433
+ return null;
33434
+ }
33104
33435
  function normalizeControlListResult(data) {
33105
33436
  if (data && typeof data === "object" && Array.isArray(data.options)) {
33106
33437
  return {
@@ -33167,9 +33498,17 @@ ${data.message || ""}`.trim();
33167
33498
  }
33168
33499
  return String(value);
33169
33500
  }
33501
+ function formatNotificationBubbleFallback(title, body) {
33502
+ const cleanTitle = typeof title === "string" ? title.trim() : "";
33503
+ const cleanBody = String(body || "").trim();
33504
+ if (cleanTitle && cleanBody) return `${cleanTitle}
33505
+ ${cleanBody}`;
33506
+ return cleanTitle || cleanBody;
33507
+ }
33170
33508
  var fs32 = __toESM2(require("fs"));
33171
33509
  var path7 = __toESM2(require("path"));
33172
33510
  var os52 = __toESM2(require("os"));
33511
+ init_chat_message_normalization();
33173
33512
  var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
33174
33513
  var RETAIN_DAYS = 30;
33175
33514
  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;
@@ -33375,11 +33714,11 @@ ${data.message || ""}`.trim();
33375
33714
  this.appendNewMessages(
33376
33715
  agentType,
33377
33716
  [{
33378
- role: "system",
33379
- kind: "system",
33380
- content,
33381
- receivedAt: options.receivedAt,
33382
- senderName: options.senderName,
33717
+ ...buildRuntimeSystemChatMessage({
33718
+ content,
33719
+ receivedAt: options.receivedAt,
33720
+ senderName: options.senderName
33721
+ }),
33383
33722
  historyDedupKey: options.dedupKey
33384
33723
  }],
33385
33724
  options.sessionTitle,
@@ -33730,6 +34069,7 @@ ${data.message || ""}`.trim();
33730
34069
  })
33731
34070
  };
33732
34071
  }
34072
+ init_chat_message_normalization();
33733
34073
  var ExtensionProviderInstance = class {
33734
34074
  type;
33735
34075
  category = "extension";
@@ -33936,8 +34276,8 @@ ${data.message || ""}`.trim();
33936
34276
  if (this.appliedEffectKeys.has(effectKey)) continue;
33937
34277
  this.appliedEffectKeys.add(effectKey);
33938
34278
  if (effect.persist !== false) {
33939
- const persisted = this.getPersistedEffectContent(effect);
33940
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
34279
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
34280
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
33941
34281
  }
33942
34282
  if (effect.type === "message" && effect.message) {
33943
34283
  this.pushEvent({
@@ -33972,34 +34312,42 @@ ${data.message || ""}`.trim();
33972
34312
  }
33973
34313
  }
33974
34314
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
33975
- const normalizedContent = String(content || "").trim();
33976
- if (!normalizedContent) return;
34315
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
34316
+ content,
34317
+ receivedAt,
34318
+ timestamp: receivedAt
34319
+ }), dedupKey);
34320
+ }
34321
+ appendRuntimeMessage(message, dedupKey) {
34322
+ const normalizedMessage = buildChatMessage({
34323
+ ...message,
34324
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
34325
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
34326
+ });
34327
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
34328
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
33977
34329
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
33978
34330
  this.runtimeMessages.push({
33979
34331
  key: dedupKey,
33980
- message: {
33981
- role: "system",
33982
- senderName: "System",
33983
- content: normalizedContent,
33984
- receivedAt,
33985
- timestamp: receivedAt
33986
- }
34332
+ message: normalizedMessage
33987
34333
  });
33988
34334
  if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
33989
- this.historyWriter.appendNewMessages(
33990
- this.type,
33991
- [{
33992
- role: "system",
33993
- senderName: "System",
33994
- content: normalizedContent,
33995
- kind: "system",
33996
- receivedAt,
33997
- historyDedupKey: dedupKey
33998
- }],
33999
- this.chatTitle || this.agentName || this.provider.name,
34000
- this.instanceId,
34001
- this.chatId || this.instanceId
34002
- );
34335
+ if (normalizedContent) {
34336
+ this.historyWriter.appendNewMessages(
34337
+ this.type,
34338
+ [{
34339
+ role: normalizedMessage.role,
34340
+ senderName: normalizedMessage.senderName,
34341
+ kind: normalizedMessage.kind,
34342
+ content: normalizedContent,
34343
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
34344
+ historyDedupKey: dedupKey
34345
+ }],
34346
+ this.chatTitle || this.agentName || this.provider.name,
34347
+ this.instanceId,
34348
+ this.chatId || this.instanceId
34349
+ );
34350
+ }
34003
34351
  }
34004
34352
  /**
34005
34353
  * Assign stable receivedAt to extension messages.
@@ -34016,16 +34364,16 @@ ${data.message || ""}`.trim();
34016
34364
  nextHashes.set(hash2, msg.receivedAt);
34017
34365
  }
34018
34366
  this.prevMessageHashes = nextHashes;
34019
- return messages;
34367
+ return normalizeChatMessages(messages);
34020
34368
  }
34021
34369
  mergeConversationMessages(messages) {
34022
- if (this.runtimeMessages.length === 0) return messages;
34023
- return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34370
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(messages);
34371
+ return normalizeChatMessages([...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34024
34372
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
34025
34373
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
34026
34374
  if (aTime !== bTime) return aTime - bTime;
34027
34375
  return a.index - b2.index;
34028
- }).map((entry) => entry.message);
34376
+ }).map((entry) => entry.message));
34029
34377
  }
34030
34378
  getPersistedEffectContent(effect) {
34031
34379
  if (effect.type === "message") {
@@ -34133,6 +34481,7 @@ ${effect.notification.body || ""}`.trim();
34133
34481
  if (cleanMessage) lines.push(cleanMessage);
34134
34482
  return lines.join("\n");
34135
34483
  }
34484
+ init_chat_message_normalization();
34136
34485
  var IdeProviderInstance = class {
34137
34486
  type;
34138
34487
  category = "ide";
@@ -34513,8 +34862,8 @@ ${effect.notification.body || ""}`.trim();
34513
34862
  if (this.appliedEffectKeys.has(effectKey)) continue;
34514
34863
  this.appliedEffectKeys.add(effectKey);
34515
34864
  if (effect.persist !== false) {
34516
- const persisted = this.getPersistedEffectContent(effect);
34517
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
34865
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
34866
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
34518
34867
  }
34519
34868
  if (effect.type === "message" && effect.message) {
34520
34869
  this.pushEvent({
@@ -34549,8 +34898,20 @@ ${effect.notification.body || ""}`.trim();
34549
34898
  }
34550
34899
  }
34551
34900
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
34552
- const normalizedContent = String(content || "").trim();
34553
- if (!normalizedContent) return;
34901
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
34902
+ content,
34903
+ receivedAt,
34904
+ timestamp: receivedAt
34905
+ }), dedupKey);
34906
+ }
34907
+ appendRuntimeMessage(message, dedupKey) {
34908
+ const normalizedMessage = buildChatMessage({
34909
+ ...message,
34910
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
34911
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
34912
+ });
34913
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
34914
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
34554
34915
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
34555
34916
  if (!this.cachedChat) {
34556
34917
  this.cachedChat = {
@@ -34564,38 +34925,34 @@ ${effect.notification.body || ""}`.trim();
34564
34925
  }
34565
34926
  this.runtimeMessages.push({
34566
34927
  key: dedupKey,
34567
- message: {
34568
- role: "system",
34569
- senderName: "System",
34570
- content: normalizedContent,
34571
- receivedAt,
34572
- timestamp: receivedAt
34573
- }
34928
+ message: normalizedMessage
34574
34929
  });
34575
34930
  if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
34576
- this.historyWriter.appendNewMessages(
34577
- this.type,
34578
- [{
34579
- role: "system",
34580
- senderName: "System",
34581
- content: normalizedContent,
34582
- kind: "system",
34583
- receivedAt,
34584
- historyDedupKey: dedupKey
34585
- }],
34586
- this.cachedChat?.title || this.provider.name,
34587
- this.instanceId,
34588
- this.cachedChat?.id || this.instanceId
34589
- );
34931
+ if (normalizedContent) {
34932
+ this.historyWriter.appendNewMessages(
34933
+ this.type,
34934
+ [{
34935
+ role: normalizedMessage.role,
34936
+ senderName: normalizedMessage.senderName,
34937
+ kind: normalizedMessage.kind,
34938
+ content: normalizedContent,
34939
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
34940
+ historyDedupKey: dedupKey
34941
+ }],
34942
+ this.cachedChat?.title || this.provider.name,
34943
+ this.instanceId,
34944
+ this.cachedChat?.id || this.instanceId
34945
+ );
34946
+ }
34590
34947
  }
34591
34948
  mergeConversationMessages(messages) {
34592
- if (this.runtimeMessages.length === 0) return messages;
34593
- return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34949
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(messages);
34950
+ return normalizeChatMessages([...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
34594
34951
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
34595
34952
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
34596
34953
  if (aTime !== bTime) return aTime - bTime;
34597
34954
  return a.index - b2.index;
34598
- }).map((entry) => entry.message);
34955
+ }).map((entry) => entry.message));
34599
34956
  }
34600
34957
  getPersistedEffectContent(effect) {
34601
34958
  if (effect.type === "message") {
@@ -35483,215 +35840,6 @@ ${effect.notification.body || ""}`.trim();
35483
35840
  }
35484
35841
  }
35485
35842
  init_logger();
35486
- function normalizeInputEnvelope(input) {
35487
- const normalized = normalizeInputEnvelopePayload(input);
35488
- const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
35489
- return {
35490
- parts: normalized.parts,
35491
- textFallback,
35492
- ...normalized.metadata ? { metadata: normalized.metadata } : {}
35493
- };
35494
- }
35495
- function normalizeMessageParts(content) {
35496
- if (typeof content === "string") return [{ type: "text", text: content }];
35497
- if (!Array.isArray(content)) {
35498
- if (content && typeof content === "object" && typeof content.text === "string") {
35499
- return [{ type: "text", text: String(content.text) }];
35500
- }
35501
- return [];
35502
- }
35503
- const parts = [];
35504
- for (const raw of content) {
35505
- if (typeof raw === "string") {
35506
- parts.push({ type: "text", text: raw });
35507
- continue;
35508
- }
35509
- if (!raw || typeof raw !== "object") continue;
35510
- const part = normalizeMessagePartObject(raw);
35511
- if (part) parts.push(part);
35512
- }
35513
- return parts;
35514
- }
35515
- function flattenMessageParts(parts) {
35516
- return parts.map((part) => {
35517
- if (part.type === "text") return part.text;
35518
- if (part.type === "resource") return part.resource.text || "";
35519
- return "";
35520
- }).filter((value) => value.length > 0).join("\n");
35521
- }
35522
- function normalizeInputEnvelopePayload(input) {
35523
- if (typeof input === "string") {
35524
- return { parts: [{ type: "text", text: input }], textFallback: input };
35525
- }
35526
- if (!input || typeof input !== "object") {
35527
- return { parts: [], textFallback: "" };
35528
- }
35529
- const record2 = input;
35530
- const nestedInput = record2.input;
35531
- if (nestedInput && typeof nestedInput === "object") {
35532
- const nested = nestedInput;
35533
- return {
35534
- parts: normalizeInputParts(nested.parts ?? nested.prompt),
35535
- textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
35536
- metadata: normalizeInputMetadata(nested.metadata)
35537
- };
35538
- }
35539
- const directText = typeof record2.text === "string" ? record2.text : typeof record2.message === "string" ? record2.message : void 0;
35540
- if (directText !== void 0) {
35541
- return { parts: [{ type: "text", text: directText }], textFallback: directText };
35542
- }
35543
- const directParts = normalizeInputParts(record2.parts ?? record2.prompt);
35544
- return {
35545
- parts: directParts,
35546
- textFallback: typeof record2.textFallback === "string" ? record2.textFallback : void 0,
35547
- metadata: normalizeInputMetadata(record2.metadata)
35548
- };
35549
- }
35550
- function normalizeInputMetadata(value) {
35551
- if (!value || typeof value !== "object") return void 0;
35552
- const record2 = value;
35553
- const metadata = {};
35554
- if (record2.source === "dashboard" || record2.source === "shortcut_api" || record2.source === "provider_script" || record2.source === "session_replay") {
35555
- metadata.source = record2.source;
35556
- }
35557
- if (typeof record2.clientTimestamp === "number" && Number.isFinite(record2.clientTimestamp)) {
35558
- metadata.clientTimestamp = record2.clientTimestamp;
35559
- }
35560
- return Object.keys(metadata).length > 0 ? metadata : void 0;
35561
- }
35562
- function normalizeInputParts(value) {
35563
- if (!Array.isArray(value)) return [];
35564
- const parts = [];
35565
- for (const raw of value) {
35566
- if (typeof raw === "string") {
35567
- parts.push({ type: "text", text: raw });
35568
- continue;
35569
- }
35570
- if (!raw || typeof raw !== "object") continue;
35571
- const part = normalizeInputPartObject(raw);
35572
- if (part) parts.push(part);
35573
- }
35574
- return parts;
35575
- }
35576
- function normalizeInputPartObject(raw) {
35577
- const type = raw.type;
35578
- if (type === "text" && typeof raw.text === "string") {
35579
- return { type, text: raw.text };
35580
- }
35581
- if (type === "image" && typeof raw.mimeType === "string") {
35582
- return {
35583
- type,
35584
- mimeType: raw.mimeType,
35585
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35586
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35587
- ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
35588
- };
35589
- }
35590
- if (type === "audio" && typeof raw.mimeType === "string") {
35591
- return {
35592
- type,
35593
- mimeType: raw.mimeType,
35594
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35595
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35596
- ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
35597
- };
35598
- }
35599
- if (type === "video" && typeof raw.mimeType === "string") {
35600
- return {
35601
- type,
35602
- mimeType: raw.mimeType,
35603
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35604
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35605
- ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
35606
- };
35607
- }
35608
- if (type === "resource" && typeof raw.uri === "string") {
35609
- return {
35610
- type,
35611
- uri: raw.uri,
35612
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35613
- ...typeof raw.name === "string" ? { name: raw.name } : {},
35614
- ...typeof raw.text === "string" ? { text: raw.text } : {},
35615
- ...typeof raw.data === "string" ? { data: raw.data } : {}
35616
- };
35617
- }
35618
- if (type === "resource_link" && typeof raw.uri === "string") {
35619
- return {
35620
- type: "resource",
35621
- uri: raw.uri,
35622
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35623
- ...typeof raw.name === "string" ? { name: raw.name } : {}
35624
- };
35625
- }
35626
- return null;
35627
- }
35628
- function normalizeMessagePartObject(raw) {
35629
- const type = raw.type;
35630
- if (type === "text" && typeof raw.text === "string") {
35631
- return { type, text: raw.text };
35632
- }
35633
- if (type === "image" && typeof raw.mimeType === "string") {
35634
- return {
35635
- type,
35636
- mimeType: raw.mimeType,
35637
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35638
- ...typeof raw.data === "string" ? { data: raw.data } : {}
35639
- };
35640
- }
35641
- if (type === "audio" && typeof raw.mimeType === "string") {
35642
- return {
35643
- type,
35644
- mimeType: raw.mimeType,
35645
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35646
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35647
- ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
35648
- };
35649
- }
35650
- if (type === "video" && typeof raw.mimeType === "string") {
35651
- return {
35652
- type,
35653
- mimeType: raw.mimeType,
35654
- ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
35655
- ...typeof raw.data === "string" ? { data: raw.data } : {},
35656
- ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
35657
- };
35658
- }
35659
- if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
35660
- return {
35661
- type,
35662
- uri: raw.uri,
35663
- name: raw.name,
35664
- ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
35665
- ...typeof raw.size === "number" ? { size: raw.size } : {}
35666
- };
35667
- }
35668
- if (type === "resource" && raw.resource && typeof raw.resource === "object") {
35669
- const resource = raw.resource;
35670
- if (typeof resource.uri !== "string") return null;
35671
- return {
35672
- type,
35673
- resource: {
35674
- uri: resource.uri,
35675
- ...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
35676
- ...typeof resource.text === "string" ? { text: resource.text } : {},
35677
- ...typeof resource.blob === "string" ? { blob: resource.blob } : {}
35678
- }
35679
- };
35680
- }
35681
- return null;
35682
- }
35683
- function flattenInputParts(parts) {
35684
- return parts.map((part) => {
35685
- if (part.type === "text") return part.text;
35686
- if (part.type === "audio") return part.transcript || "";
35687
- if (part.type === "resource") return part.text || "";
35688
- return "";
35689
- }).filter((value) => value.length > 0).join("\n");
35690
- }
35691
- function flattenContent(content) {
35692
- if (typeof content === "string") return content;
35693
- return flattenMessageParts(normalizeMessageParts(content));
35694
- }
35695
35843
  init_logger();
35696
35844
  var NORMAL_TRACE_BUFFER_SIZE = 200;
35697
35845
  var DEV_TRACE_BUFFER_SIZE = 1e3;
@@ -35815,6 +35963,7 @@ ${effect.notification.body || ""}`.trim();
35815
35963
  function createInteractionId(prefix = "ix") {
35816
35964
  return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
35817
35965
  }
35966
+ init_chat_message_normalization();
35818
35967
  var RECENT_SEND_WINDOW_MS = 1200;
35819
35968
  var recentSendByTarget = /* @__PURE__ */ new Map();
35820
35969
  function hashSignatureParts2(parts) {
@@ -35944,7 +36093,7 @@ ${effect.notification.body || ""}`.trim();
35944
36093
  }
35945
36094
  function normalizeReadChatMessages(payload) {
35946
36095
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
35947
- return messages;
36096
+ return normalizeChatMessages(messages);
35948
36097
  }
35949
36098
  function deriveHistoryDedupKey(message) {
35950
36099
  const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
@@ -38274,6 +38423,7 @@ ${effect.notification.body || ""}`.trim();
38274
38423
  var import_node_module = require("module");
38275
38424
  init_provider_cli_adapter();
38276
38425
  init_logger();
38426
+ init_chat_message_normalization();
38277
38427
  var CachedDatabaseSync = null;
38278
38428
  function getDatabaseSync() {
38279
38429
  if (CachedDatabaseSync) return CachedDatabaseSync;
@@ -38768,8 +38918,8 @@ ${effect.notification.body || ""}`.trim();
38768
38918
  if (this.appliedEffectKeys.has(effectKey)) continue;
38769
38919
  this.appliedEffectKeys.add(effectKey);
38770
38920
  if (effect.persist !== false) {
38771
- const persisted = this.getPersistedEffectContent(effect);
38772
- if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
38921
+ const persistedMessage = buildPersistedProviderEffectMessage(effect);
38922
+ if (persistedMessage) this.appendRuntimeMessage(persistedMessage, effectKey);
38773
38923
  }
38774
38924
  if (effect.type === "message" && effect.message) {
38775
38925
  const content = typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content);
@@ -38893,44 +39043,53 @@ ${effect.notification.body || ""}`.trim();
38893
39043
  );
38894
39044
  }
38895
39045
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
38896
- const normalizedContent = String(content || "").trim();
38897
- if (!normalizedContent) return;
39046
+ this.appendRuntimeMessage(buildRuntimeSystemChatMessage({
39047
+ content,
39048
+ receivedAt,
39049
+ timestamp: receivedAt
39050
+ }), dedupKey);
39051
+ }
39052
+ appendRuntimeMessage(message, dedupKey) {
39053
+ const normalizedMessage = buildChatMessage({
39054
+ ...message,
39055
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp || Date.now(),
39056
+ timestamp: typeof message.timestamp === "number" ? message.timestamp : message.receivedAt || Date.now()
39057
+ });
39058
+ const normalizedContent = typeof normalizedMessage.content === "string" ? normalizedMessage.content.trim() : flattenContent(normalizedMessage.content).trim();
39059
+ if (!normalizedContent && (!Array.isArray(normalizedMessage.content) || normalizedMessage.content.length === 0)) return;
38898
39060
  if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
38899
39061
  this.runtimeMessages.push({
38900
39062
  key: dedupKey,
38901
- message: {
38902
- role: "system",
38903
- senderName: "System",
38904
- content: normalizedContent,
38905
- receivedAt,
38906
- timestamp: receivedAt
38907
- }
39063
+ message: normalizedMessage
38908
39064
  });
38909
39065
  if (this.runtimeMessages.length > 50) {
38910
39066
  this.runtimeMessages = this.runtimeMessages.slice(-50);
38911
39067
  }
38912
- this.historyWriter.appendNewMessages(
38913
- this.type,
38914
- [{
38915
- role: "system",
38916
- senderName: "System",
38917
- content: normalizedContent,
38918
- receivedAt,
38919
- historyDedupKey: dedupKey
38920
- }],
38921
- this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
38922
- this.instanceId,
38923
- this.providerSessionId
38924
- );
39068
+ if (normalizedContent) {
39069
+ this.historyWriter.appendNewMessages(
39070
+ this.type,
39071
+ [{
39072
+ role: normalizedMessage.role,
39073
+ senderName: normalizedMessage.senderName,
39074
+ kind: normalizedMessage.kind,
39075
+ content: normalizedContent,
39076
+ receivedAt: normalizedMessage.receivedAt || normalizedMessage.timestamp,
39077
+ historyDedupKey: dedupKey
39078
+ }],
39079
+ this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
39080
+ this.instanceId,
39081
+ this.providerSessionId
39082
+ );
39083
+ }
38925
39084
  }
38926
39085
  mergeConversationMessages(parsedMessages) {
38927
- if (this.runtimeMessages.length === 0) return parsedMessages;
38928
- return [...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
39086
+ if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
39087
+ return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
38929
39088
  const aTime = a.message.receivedAt || a.message.timestamp || 0;
38930
39089
  const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
38931
39090
  if (aTime !== bTime) return aTime - bTime;
38932
39091
  return a.index - b2.index;
38933
- }).map((entry) => entry.message);
39092
+ }).map((entry) => entry.message));
38934
39093
  }
38935
39094
  formatApprovalRequestMessage(modalMessage, buttons) {
38936
39095
  const lines = ["Approval requested"];
@@ -38999,6 +39158,7 @@ ${effect.notification.body || ""}`.trim();
38999
39158
  var import_stream = require("stream");
39000
39159
  var import_child_process5 = require("child_process");
39001
39160
  var import_sdk = (init_acp(), __toCommonJS(acp_exports));
39161
+ init_chat_message_normalization();
39002
39162
  init_logger();
39003
39163
  function getPromptCapabilityFlags(agentCapabilities) {
39004
39164
  const prompt = agentCapabilities?.promptCapabilities || {};
@@ -39164,24 +39324,21 @@ ${effect.notification.body || ""}`.trim();
39164
39324
  }
39165
39325
  getState() {
39166
39326
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
39167
- const recentMessages = this.messages.slice(-50).map((m) => {
39327
+ const recentMessages = normalizeChatMessages(this.messages.slice(-50).map((m) => {
39168
39328
  const content = this.truncateContent(m.content);
39169
- return {
39170
- role: m.role,
39171
- content,
39172
- timestamp: m.timestamp,
39173
- toolCalls: m.toolCalls
39174
- };
39175
- });
39329
+ return buildChatMessage({
39330
+ ...m,
39331
+ content
39332
+ });
39333
+ }));
39176
39334
  if (this.currentStatus === "generating" && (this.partialContent || this.partialBlocks.length > 0)) {
39177
39335
  const blocks = this.buildPartialBlocks();
39178
39336
  if (blocks.length > 0) {
39179
- recentMessages.push({
39180
- role: "assistant",
39337
+ recentMessages.push(buildAssistantChatMessage({
39181
39338
  content: blocks,
39182
39339
  timestamp: Date.now(),
39183
39340
  toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
39184
- });
39341
+ }));
39185
39342
  }
39186
39343
  }
39187
39344
  return {
@@ -39194,7 +39351,7 @@ ${effect.notification.body || ""}`.trim();
39194
39351
  id: this.sessionId || `${this.type}_${this.workingDir}`,
39195
39352
  title: `${this.provider.name} \xB7 ${dirName}`,
39196
39353
  status: this.currentStatus,
39197
- messages: recentMessages,
39354
+ messages: normalizeChatMessages(recentMessages),
39198
39355
  activeModal: this.currentStatus === "waiting_approval" ? {
39199
39356
  message: this.activeToolCalls.find((t) => t.status === "running")?.name || "Permission requested",
39200
39357
  buttons: ["Approve", "Reject"]
@@ -39726,11 +39883,10 @@ ${effect.notification.body || ""}`.trim();
39726
39883
  if (b2.type === "resource") return { type: "resource", resource: b2.resource };
39727
39884
  return { type: "text", text: flattenContent([b2]) };
39728
39885
  }) : [{ type: "text", text }];
39729
- this.messages.push({
39730
- role: "user",
39886
+ this.messages.push(buildUserChatMessage({
39731
39887
  content: contentBlocks && contentBlocks.length > 0 ? contentBlocks : text,
39732
39888
  timestamp: Date.now()
39733
- });
39889
+ }));
39734
39890
  this.currentStatus = "generating";
39735
39891
  this.partialContent = "";
39736
39892
  this.partialBlocks = [];
@@ -39900,11 +40056,11 @@ ${effect.notification.body || ""}`.trim();
39900
40056
  content = m.content.filter((p) => p.type === "text").map((p) => p.text || "").join("\n");
39901
40057
  }
39902
40058
  if (content.trim()) {
39903
- this.messages.push({
40059
+ this.messages.push(buildChatMessage({
39904
40060
  role: m.role || "assistant",
39905
40061
  content: content.trim(),
39906
40062
  timestamp: Date.now()
39907
- });
40063
+ }));
39908
40064
  this.partialContent = "";
39909
40065
  }
39910
40066
  }
@@ -39980,12 +40136,11 @@ ${effect.notification.body || ""}`.trim();
39980
40136
  return b2;
39981
40137
  }).filter((b2) => b2.type !== "text" || b2.type === "text" && b2.text.trim());
39982
40138
  if (finalBlocks.length > 0) {
39983
- this.messages.push({
39984
- role: "assistant",
40139
+ this.messages.push(buildAssistantChatMessage({
39985
40140
  content: finalBlocks.length === 1 && finalBlocks[0].type === "text" ? finalBlocks[0].text : finalBlocks,
39986
40141
  timestamp: Date.now(),
39987
40142
  toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : void 0
39988
- });
40143
+ }));
39989
40144
  }
39990
40145
  this.partialContent = "";
39991
40146
  this.partialBlocks = [];
@@ -40045,11 +40200,10 @@ ${effect.notification.body || ""}`.trim();
40045
40200
  appendSystemMessage(content, timestamp = Date.now()) {
40046
40201
  const normalizedContent = String(content || "").trim();
40047
40202
  if (!normalizedContent) return;
40048
- this.messages.push({
40049
- role: "system",
40203
+ this.messages.push(buildRuntimeSystemChatMessage({
40050
40204
  content: normalizedContent,
40051
40205
  timestamp
40052
- });
40206
+ }));
40053
40207
  if (this.messages.length > 200) {
40054
40208
  this.messages = this.messages.slice(-100);
40055
40209
  }
@@ -44678,6 +44832,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44678
44832
  }
44679
44833
  };
44680
44834
  init_logger();
44835
+ init_chat_message_normalization();
44681
44836
  var AgentStreamPoller = class {
44682
44837
  deps;
44683
44838
  timer = null;
@@ -44833,12 +44988,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44833
44988
  type: "message",
44834
44989
  id: effectId,
44835
44990
  persist: true,
44836
- message: {
44837
- role: "system",
44838
- senderName: "System",
44839
- kind: "system",
44991
+ message: buildRuntimeSystemChatMessage({
44840
44992
  content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel)
44841
- }
44993
+ })
44842
44994
  }
44843
44995
  ]
44844
44996
  };
@@ -45080,6 +45232,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45080
45232
  this.eventListeners = [];
45081
45233
  }
45082
45234
  };
45235
+ init_chat_message_normalization();
45083
45236
  var fs10 = __toESM2(require("fs"));
45084
45237
  var path18 = __toESM2(require("path"));
45085
45238
  var os18 = __toESM2(require("os"));