@acorex-platform/module-conversation-client 0.0.33 → 0.0.38

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.
Files changed (46) hide show
  1. package/fesm2022/{acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CDlDFzbl.mjs → acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-XTzQQhii.mjs} +745 -215
  2. package/fesm2022/acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-XTzQQhii.mjs.map +1 -0
  3. package/fesm2022/{acorex-platform-module-conversation-client-after-message-sent.command-yzW01skh.mjs → acorex-platform-module-conversation-client-after-message-sent.command-BMGagKtP.mjs} +2 -2
  4. package/fesm2022/{acorex-platform-module-conversation-client-after-message-sent.command-yzW01skh.mjs.map → acorex-platform-module-conversation-client-after-message-sent.command-BMGagKtP.mjs.map} +1 -1
  5. package/fesm2022/{acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-DhRvuCex.mjs → acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-D1SDsHvl.mjs} +3 -3
  6. package/fesm2022/{acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-DhRvuCex.mjs.map → acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-D1SDsHvl.mjs.map} +1 -1
  7. package/fesm2022/{acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BRW1cHN6.mjs → acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BV1YH96m.mjs} +2 -2
  8. package/fesm2022/{acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BRW1cHN6.mjs.map → acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BV1YH96m.mjs.map} +1 -1
  9. package/fesm2022/acorex-platform-module-conversation-client-chat-call-session-page.component-nE7xP4bF.mjs +1607 -0
  10. package/fesm2022/acorex-platform-module-conversation-client-chat-call-session-page.component-nE7xP4bF.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-conversation-client-chat-call-start-popup.component-DXkqkS50.mjs +92 -0
  12. package/fesm2022/acorex-platform-module-conversation-client-chat-call-start-popup.component-DXkqkS50.mjs.map +1 -0
  13. package/fesm2022/{acorex-platform-module-conversation-client-chat-conversation-info-media-view.component-CppNPfqe.mjs → acorex-platform-module-conversation-client-chat-conversation-info-media-view.component-SYCtAqcV.mjs} +2 -2
  14. package/fesm2022/{acorex-platform-module-conversation-client-chat-conversation-info-media-view.component-CppNPfqe.mjs.map → acorex-platform-module-conversation-client-chat-conversation-info-media-view.component-SYCtAqcV.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-module-conversation-client-chat-conversation-info-panel.component-BBL8iEqc.mjs → acorex-platform-module-conversation-client-chat-conversation-info-panel.component-51PtojIM.mjs} +14 -4
  16. package/fesm2022/acorex-platform-module-conversation-client-chat-conversation-info-panel.component-51PtojIM.mjs.map +1 -0
  17. package/fesm2022/{acorex-platform-module-conversation-client-comments-page.component-Djn8EikR.mjs → acorex-platform-module-conversation-client-comments-page.component-Dv_x3ztZ.mjs} +2 -2
  18. package/fesm2022/{acorex-platform-module-conversation-client-comments-page.component-Djn8EikR.mjs.map → acorex-platform-module-conversation-client-comments-page.component-Dv_x3ztZ.mjs.map} +1 -1
  19. package/fesm2022/acorex-platform-module-conversation-client-contracts-entities-message.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-module-conversation-client-contracts-entities-room.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-module-conversation-client-contracts-entity-catalog-acorex-platform-module-conversation-client-contracts-entity-catalog-Cy3LwYMZ.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-module-conversation-client-contracts-entity-catalog-message.entity-Dz7cO1P4.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-module-conversation-client-contracts-entity-catalog-room.entity-B9txvc3y.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-module-conversation-client-contracts.mjs.map +1 -1
  25. package/fesm2022/acorex-platform-module-conversation-client-emit-typing-indicator.command-BzsN1_ns.mjs.map +1 -1
  26. package/fesm2022/acorex-platform-module-conversation-client-local-entities.mjs.map +1 -1
  27. package/fesm2022/{acorex-platform-module-conversation-client-mark-conversation-unread.command-BoTNaBxS.mjs → acorex-platform-module-conversation-client-mark-conversation-unread.command-8NoSuUwe.mjs} +2 -2
  28. package/fesm2022/{acorex-platform-module-conversation-client-mark-conversation-unread.command-BoTNaBxS.mjs.map → acorex-platform-module-conversation-client-mark-conversation-unread.command-8NoSuUwe.mjs.map} +1 -1
  29. package/fesm2022/{acorex-platform-module-conversation-client-open-chat.command-VgeGqj-z.mjs → acorex-platform-module-conversation-client-open-chat.command-BgJ0Z36e.mjs} +5 -5
  30. package/fesm2022/acorex-platform-module-conversation-client-open-chat.command-BgJ0Z36e.mjs.map +1 -0
  31. package/fesm2022/{acorex-platform-module-conversation-client-retry-assist-response.command-DYIpLKDB.mjs → acorex-platform-module-conversation-client-retry-assist-response.command-lcNz4Hpu.mjs} +2 -2
  32. package/fesm2022/{acorex-platform-module-conversation-client-retry-assist-response.command-DYIpLKDB.mjs.map → acorex-platform-module-conversation-client-retry-assist-response.command-lcNz4Hpu.mjs.map} +1 -1
  33. package/fesm2022/acorex-platform-module-conversation-client-start-direct-chat.command-CfSIVHDu.mjs.map +1 -1
  34. package/fesm2022/{acorex-platform-module-conversation-client-sync-read-state.command-D97E8VvL.mjs → acorex-platform-module-conversation-client-sync-read-state.command-DxccFsD9.mjs} +26 -13
  35. package/fesm2022/acorex-platform-module-conversation-client-sync-read-state.command-DxccFsD9.mjs.map +1 -0
  36. package/fesm2022/acorex-platform-module-conversation-client.mjs +1 -1
  37. package/package.json +2 -2
  38. package/types/acorex-platform-module-conversation-client.d.ts +28 -1
  39. package/fesm2022/acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CDlDFzbl.mjs.map +0 -1
  40. package/fesm2022/acorex-platform-module-conversation-client-chat-call-session-page.component-C47tt1me.mjs +0 -1386
  41. package/fesm2022/acorex-platform-module-conversation-client-chat-call-session-page.component-C47tt1me.mjs.map +0 -1
  42. package/fesm2022/acorex-platform-module-conversation-client-chat-call-start-popup.component-EZjVSlhm.mjs +0 -89
  43. package/fesm2022/acorex-platform-module-conversation-client-chat-call-start-popup.component-EZjVSlhm.mjs.map +0 -1
  44. package/fesm2022/acorex-platform-module-conversation-client-chat-conversation-info-panel.component-BBL8iEqc.mjs.map +0 -1
  45. package/fesm2022/acorex-platform-module-conversation-client-open-chat.command-VgeGqj-z.mjs.map +0 -1
  46. package/fesm2022/acorex-platform-module-conversation-client-sync-read-state.command-D97E8VvL.mjs.map +0 -1
@@ -29,6 +29,7 @@ import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent } from '@acorex-plat
29
29
  import * as i2 from '@acorex/components/decorators';
30
30
  import { AXDecoratorModule } from '@acorex/components/decorators';
31
31
  import { AXDialogService } from '@acorex/components/dialog';
32
+ import { AXPopupService } from '@acorex/components/popup';
32
33
  import * as i3$1 from '@acorex/core/translation';
33
34
  import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
34
35
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
@@ -38,7 +39,6 @@ import * as i3 from '@acorex/components/loading';
38
39
  import { AXLoadingModule } from '@acorex/components/loading';
39
40
  import { AXToastService } from '@acorex/components/toast';
40
41
  import { AXPAiManagerService, AXPAiChatToolRunContextService, AXPAiPlatformRuntimeContextBuilder, AIMANAGEMENT_STRUCTURED_TEXT_COMPLETION_COMMAND_KEY, axpAiChatTextMessage, persistAiChatAttachmentImage, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AXPAiAssistChatModelCatalogService, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiDelegatedAgentResultSegments, axpAiParseSupervisorAgentToolName, AI_CHAT_GENERATED_SPEECH_REF_TYPE, AI_CHAT_GENERATED_IMAGE_REF_TYPE, axpAiChatMessageGetText, axpAiDelegatedAgentPromptPreview, axpAiChatToolOrAgentResultBodyJson, axpAiDelegatedAgentOutcomeResponsesPlainText } from '@acorex-platform/module-ai-management-client';
41
- import { AXPopupService } from '@acorex/components/popup';
42
42
  import { AXPRtcApiAbstract, AXERtcGatewayService } from '@acorex-platform/extension-rtc-core-gateway';
43
43
  import * as i2$1 from '@acorex/components/switch';
44
44
  import { AXSwitchModule } from '@acorex/components/switch';
@@ -53,7 +53,7 @@ import { AXCodeEditorModule } from '@acorex/components/code-editor';
53
53
  import { AXPLayoutThemeService } from '@acorex-platform/framework-client/themes/shared';
54
54
  import { AXPLayoutRendererComponent } from '@acorex-platform/framework-client/layout/builder';
55
55
  import { AXLocaleService } from '@acorex/core/locale';
56
- import { AXPInAppInboxConnectorService, AXPCommunicationManagementClient, AXPInAppInboxRealtimeService } from '@acorex-platform/module-communication-management-client';
56
+ import { AXPInAppInboxConnectorService, isInAppInboxUnread, AXPCommunicationManagementClient, AXPInAppInboxRealtimeService } from '@acorex-platform/module-communication-management-client';
57
57
  import { AXFabComponent, AXFabItemComponent } from '@acorex/components/fab';
58
58
  import * as i1$5 from '@acorex/components/wysiwyg';
59
59
  import { AXWysiwygModule } from '@acorex/components/wysiwyg';
@@ -814,10 +814,18 @@ function axmChatCallLogTranslateParams(info) {
814
814
  }
815
815
  if (info.isGroup) {
816
816
  params['joined'] = info.joinedUserNames?.length ? info.joinedUserNames.join(', ') : '—';
817
- params['absent'] = info.absentUserNames?.length ? info.absentUserNames.join(', ') : '—';
817
+ if (info.absentUserNames?.length) {
818
+ params['absent'] = info.absentUserNames.join(', ');
819
+ }
818
820
  }
819
821
  return params;
820
822
  }
823
+ /** Group call log attendance line — omits absent copy when nobody was absent. */
824
+ function axmChatCallLogGroupAttendanceKey(info) {
825
+ return info.absentUserNames?.length
826
+ ? '@conversation:chat.call.log.group-attendance'
827
+ : '@conversation:chat.call.log.group-attendance-joined-only';
828
+ }
821
829
  function axmCoerceSystemPayload(payload) {
822
830
  if (!payload) {
823
831
  return undefined;
@@ -1106,14 +1114,19 @@ function axmAssistPersistedMessageLooksComplete(message) {
1106
1114
  //#region ---- Imports ----
1107
1115
  //#endregion
1108
1116
  //#region ---- Unread rules ----
1117
+ /** True when the bubble is an assist-response row (streaming or terminal). */
1118
+ function axmIsAssistResponseMessage(message) {
1119
+ const meta = message.metadata;
1120
+ return meta?.['isAssistResponse'] === true || message.type === 'assist-response';
1121
+ }
1109
1122
  /**
1110
1123
  * True while an assist placeholder is still generating (not yet a deliverable reply).
1111
1124
  */
1112
1125
  function axmIsAssistStreamingMessage(message) {
1113
- const meta = message.metadata;
1114
- if (meta?.['isAssistResponse'] !== true && message.type !== 'assist-response') {
1126
+ if (!axmIsAssistResponseMessage(message)) {
1115
1127
  return false;
1116
1128
  }
1129
+ const meta = message.metadata;
1117
1130
  const status = axmReadAssistResponseStatus(message.metadata);
1118
1131
  if (status === 'streaming') {
1119
1132
  return true;
@@ -1139,6 +1152,14 @@ function axmMessageCountsTowardUnread(message, currentUserId) {
1139
1152
  function axmComputeConversationUnreadCount(messages, currentUserId) {
1140
1153
  return messages.filter((message) => axmMessageCountsTowardUnread(message, currentUserId)).length;
1141
1154
  }
1155
+ /**
1156
+ * `room.unreadCount` is a shared document field, not per-user.
1157
+ * A sender's last-message touch refetch often carries 0 and must not replace
1158
+ * a higher in-memory unread on the recipient.
1159
+ */
1160
+ function axmPreferLocalUnreadCount(localUnread, incomingUnread) {
1161
+ return Math.max(localUnread ?? 0, incomingUnread ?? 0);
1162
+ }
1142
1163
  //#endregion
1143
1164
 
1144
1165
  //#region ---- Imports ----
@@ -1757,6 +1778,8 @@ class AXMConversationEntityStoreService {
1757
1778
  this.persistChains = new Map();
1758
1779
  /** Avoids GET-by-id existence probes for assist rows already written in this session. */
1759
1780
  this.persistedMessageIds = new Set();
1781
+ /** Bumped on session reset so in-flight assist persists do not write into the next user. */
1782
+ this.persistGeneration = 0;
1760
1783
  /** In-memory snapshots to avoid redundant GetById after local writes. */
1761
1784
  this.conversationCache = new Map();
1762
1785
  this.messageCache = new Map();
@@ -1791,6 +1814,9 @@ class AXMConversationEntityStoreService {
1791
1814
  this.recomputeUnreadTotal();
1792
1815
  }
1793
1816
  clearSessionCaches() {
1817
+ this.persistGeneration += 1;
1818
+ this.persistChains.clear();
1819
+ this.persistedMessageIds.clear();
1794
1820
  this.conversationCache.clear();
1795
1821
  this.messageCache.clear();
1796
1822
  this.messageListCache.clear();
@@ -1835,21 +1861,18 @@ class AXMConversationEntityStoreService {
1835
1861
  return null;
1836
1862
  }
1837
1863
  const previous = this.getCachedConversation(scoped);
1838
- const fetched = await this.fetchConversationFromEntity(scoped);
1864
+ const fetched = await this.fetchConversationFromEntity(scoped, { cache: false });
1839
1865
  if (!fetched) {
1840
1866
  return null;
1841
1867
  }
1842
1868
  const currentUserId = this.session.user?.id?.trim();
1843
- const merged = previous
1844
- ? axmMergeConversationSnapshot(previous, fetched, currentUserId)
1845
- : fetched;
1846
- const previousUnread = previous?.unreadCount ?? 0;
1847
- const mergedUnread = merged.unreadCount ?? 0;
1848
- const next = previousUnread > mergedUnread ? { ...merged, unreadCount: previousUnread } : merged;
1869
+ const current = this.getCachedConversation(scoped) ?? previous;
1870
+ const merged = current ? axmMergeConversationSnapshot(current, fetched, currentUserId) : fetched;
1871
+ const next = current ? { ...merged, unreadCount: current.unreadCount ?? 0 } : merged;
1849
1872
  this.cacheConversation(next);
1850
1873
  return next;
1851
1874
  }
1852
- async fetchConversationFromEntity(conversationId) {
1875
+ async fetchConversationFromEntity(conversationId, options) {
1853
1876
  let room = null;
1854
1877
  try {
1855
1878
  room = await this.roomData.byKey(conversationId);
@@ -1858,7 +1881,9 @@ class AXMConversationEntityStoreService {
1858
1881
  room = null;
1859
1882
  }
1860
1883
  if (!room) {
1861
- this.conversationCache.delete(conversationId);
1884
+ if (options?.cache !== false) {
1885
+ this.conversationCache.delete(conversationId);
1886
+ }
1862
1887
  return null;
1863
1888
  }
1864
1889
  const currentUserId = this.session.user?.id?.trim();
@@ -1866,8 +1891,18 @@ class AXMConversationEntityStoreService {
1866
1891
  ? await axmHydrateRoomParticipants(room, (userIds) => this.userApi.getUsersByIds(userIds))
1867
1892
  : room;
1868
1893
  const conversation = axmRoomEntityToConversation(hydratedRoom, currentUserId);
1869
- this.cacheConversation(conversation);
1870
- return conversation;
1894
+ if (options?.cache === false) {
1895
+ return conversation;
1896
+ }
1897
+ const existing = this.getCachedConversation(conversationId);
1898
+ const next = existing
1899
+ ? {
1900
+ ...axmMergeConversationSnapshot(existing, conversation, currentUserId),
1901
+ unreadCount: axmPreferLocalUnreadCount(existing.unreadCount, conversation.unreadCount),
1902
+ }
1903
+ : conversation;
1904
+ this.cacheConversation(next);
1905
+ return next;
1871
1906
  }
1872
1907
  /** Persists auto-generated title after assist completes (never during streaming). */
1873
1908
  async persistAssistTitlePatch(room) {
@@ -1957,10 +1992,11 @@ class AXMConversationEntityStoreService {
1957
1992
  if (!scoped || message.deleted) {
1958
1993
  return;
1959
1994
  }
1960
- let list = this.messageListCache.get(scoped);
1995
+ const list = this.messageListCache.get(scoped);
1961
1996
  if (!list) {
1962
- list = [];
1963
- this.messageListCache.set(scoped, list);
1997
+ // Do not seed a stub list. A one-message cache would block the full history
1998
+ // fetch when the user later opens the thread.
1999
+ return;
1964
2000
  }
1965
2001
  if (list.some((entry) => entry.id === message.id)) {
1966
2002
  return;
@@ -1968,6 +2004,18 @@ class AXMConversationEntityStoreService {
1968
2004
  list.push(message);
1969
2005
  list.sort((a, b) => axmCompareMessagesChronologically(a, b));
1970
2006
  }
2007
+ mergeRealtimeMessagesIntoList(conversationId, messages) {
2008
+ const byId = new Map(messages.filter((message) => message.id).map((message) => [message.id, message]));
2009
+ for (const message of this.messageCache.values()) {
2010
+ if (!message.id || message.deleted || message.conversationId !== conversationId) {
2011
+ continue;
2012
+ }
2013
+ if (!byId.has(message.id)) {
2014
+ byId.set(message.id, message);
2015
+ }
2016
+ }
2017
+ return [...byId.values()].sort((a, b) => axmCompareMessagesChronologically(a, b));
2018
+ }
1971
2019
  async loadConversationMessages(conversationId, options) {
1972
2020
  const scoped = conversationId?.trim();
1973
2021
  if (!scoped) {
@@ -1978,7 +2026,9 @@ class AXMConversationEntityStoreService {
1978
2026
  if (!options?.force && skip === 0) {
1979
2027
  const cached = this.messageListCache.get(scoped);
1980
2028
  if (cached) {
1981
- return cached.slice(skip, skip + take);
2029
+ const merged = this.mergeRealtimeMessagesIntoList(scoped, cached);
2030
+ this.messageListCache.set(scoped, merged);
2031
+ return merged.slice(skip, skip + take);
1982
2032
  }
1983
2033
  }
1984
2034
  if (skip === 0 && !options?.force) {
@@ -2022,10 +2072,12 @@ class AXMConversationEntityStoreService {
2022
2072
  .map((m) => axmMessageEntityToMessage(m))
2023
2073
  .sort((a, b) => axmCompareMessagesChronologically(a, b));
2024
2074
  if (skip === 0) {
2025
- this.messageListCache.set(conversationId, mapped);
2026
- for (const message of mapped) {
2075
+ const merged = this.mergeRealtimeMessagesIntoList(conversationId, mapped);
2076
+ this.messageListCache.set(conversationId, merged);
2077
+ for (const message of merged) {
2027
2078
  this.cacheMessage(message);
2028
2079
  }
2080
+ return merged;
2029
2081
  }
2030
2082
  return mapped;
2031
2083
  }
@@ -2145,14 +2197,26 @@ class AXMConversationEntityStoreService {
2145
2197
  * Matches mock `putMessage` fire-and-forget used during assist streaming.
2146
2198
  */
2147
2199
  persistMessage(message) {
2200
+ const generation = this.persistGeneration;
2148
2201
  const previous = this.persistChains.get(message.id) ?? Promise.resolve();
2149
- const next = previous.then(() => this.persistMessageInternal(message));
2202
+ const next = previous.then(() => {
2203
+ if (this.persistGeneration !== generation) {
2204
+ return;
2205
+ }
2206
+ return this.persistMessageInternal(message, generation);
2207
+ });
2150
2208
  this.persistChains.set(message.id, next);
2151
2209
  return next;
2152
2210
  }
2153
- async persistMessageInternal(message) {
2211
+ async persistMessageInternal(message, generation) {
2212
+ if (this.persistGeneration !== generation) {
2213
+ return;
2214
+ }
2154
2215
  const fields = this.messageToEntityFields(message);
2155
2216
  if (this.persistedMessageIds.has(message.id)) {
2217
+ if (this.persistGeneration !== generation) {
2218
+ return;
2219
+ }
2156
2220
  await this.messageData.update(message.id, fields);
2157
2221
  return;
2158
2222
  }
@@ -2161,13 +2225,17 @@ class AXMConversationEntityStoreService {
2161
2225
  id: message.id,
2162
2226
  ...fields,
2163
2227
  });
2164
- this.persistedMessageIds.add(message.id);
2228
+ if (this.persistGeneration === generation) {
2229
+ this.persistedMessageIds.add(message.id);
2230
+ }
2165
2231
  return;
2166
2232
  }
2167
2233
  catch (createError) {
2168
2234
  try {
2169
2235
  await this.messageData.update(message.id, fields);
2170
- this.persistedMessageIds.add(message.id);
2236
+ if (this.persistGeneration === generation) {
2237
+ this.persistedMessageIds.add(message.id);
2238
+ }
2171
2239
  return;
2172
2240
  }
2173
2241
  catch {
@@ -2407,9 +2475,17 @@ class AXMConversationEntityStoreService {
2407
2475
  }
2408
2476
  const existing = this.conversationCache.get(scoped);
2409
2477
  const currentUserId = this.session.user?.id?.trim();
2410
- const merged = existing
2478
+ let merged = existing
2411
2479
  ? axmMergeConversationSnapshot(existing, conversation, currentUserId)
2412
2480
  : conversation;
2481
+ // Remote room snapshots use shared `unreadCount` (often the sender's 0).
2482
+ // Local writes (`markLocal`) may still decrease unread (open chat / mark as read).
2483
+ if (!markLocal && existing) {
2484
+ merged = {
2485
+ ...merged,
2486
+ unreadCount: axmPreferLocalUnreadCount(existing.unreadCount, merged.unreadCount),
2487
+ };
2488
+ }
2413
2489
  this.cacheConversation(merged);
2414
2490
  this.bus.publishConversationUpdate(merged, markLocal);
2415
2491
  }
@@ -2453,8 +2529,7 @@ class AXMConversationEntityStoreService {
2453
2529
  lastMessage: message,
2454
2530
  updatedAt: new Date(),
2455
2531
  };
2456
- this.cacheConversation(next);
2457
- this.bus.publishConversationUpdate(next, false);
2532
+ this.publishConversationUpdate(next, false);
2458
2533
  }
2459
2534
  publishTypingIndicator(indicator) {
2460
2535
  this.bus.publishTypingIndicator(indicator);
@@ -3081,7 +3156,7 @@ class AXMChatVoiceRecorderComponent {
3081
3156
  }
3082
3157
  </div>
3083
3158
  </div>
3084
- `, isInline: true, styles: [":host{display:block;width:100%}.voice-recorder{display:flex;flex-direction:column;width:100%;background:rgb(var(--ax-sys-color-lightest-surface))}.recorder-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.recorder-title{margin:0;font-size:.875rem;font-weight:600}.close-button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:50%;font-size:1rem;cursor:pointer;transition:all .2s;opacity:.7}.close-button:hover{background:rgb(var(--ax-sys-color-light-surface));opacity:1}.recorder-content{display:flex;align-items:center;width:100%;padding:1rem}.recorder-idle{display:flex;align-items:center;gap:1rem;width:100%}.record-button,.speech-to-text-button{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border:none;border-radius:50%;font-size:1.5rem;cursor:pointer;transition:all .2s}.record-button{background:rgb(var(--ax-sys-color-primary-500));color:rgb(var(--ax-sys-color-on-primary-surface));box-shadow:0 2px 8px rgba(var(--ax-sys-color-primary-500),.3)}.record-button:hover{background:rgb(var(--ax-sys-color-primary-600))}.speech-to-text-button{background:rgb(var(--ax-sys-color-secondary-surface));color:rgb(var(--ax-sys-color-on-secondary-surface));box-shadow:0 2px 8px rgba(var(--ax-sys-color-secondary-500),.2)}.speech-to-text-button:hover:not(:disabled){background:rgb(var(--ax-sys-color-secondary-600))}.speech-to-text-button:disabled{opacity:.6;cursor:not-allowed}.recorder-hint{font-size:.875rem;opacity:.7}.recorder-transcribing{display:flex;align-items:center;justify-content:center;gap:.75rem;width:100%;padding:.5rem 0}.recorder-transcribing-text{font-size:.875rem;font-weight:500;color:rgb(var(--ax-sys-color-on-light-surface))}.recorder-active{display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem}.recorder-info{display:flex;align-items:center;gap:1.5rem;flex:1}.recording-indicator{display:flex;align-items:center;gap:.5rem}.pulse-dot{width:12px;height:12px;background:rgb(var(--ax-sys-color-danger-500));border-radius:50%;animation:pulse 1.5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.recording-text{font-size:.875rem;font-weight:600;color:rgb(var(--ax-sys-color-danger-500))}.recording-time{font-size:1.25rem;font-weight:600;font-variant-numeric:tabular-nums;min-width:80px}.recorder-actions{display:flex;align-items:center;gap:.75rem}@media(max-width:768px){.voice-recorder{padding:.75rem}.record-button,.speech-to-text-button{width:48px;height:48px;font-size:1.25rem}.recorder-info{gap:1rem}.recording-time{font-size:1.125rem;font-variant-numeric:tabular-nums}.recorder-actions{gap:.5rem}}@media(max-width:480px){.recorder-hint{font-size:.8125rem}.recording-text{display:none}.recording-time{font-size:1rem;min-width:60px;font-variant-numeric:tabular-nums}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3159
+ `, isInline: true, styles: [":host{display:block;width:100%}.voice-recorder{display:flex;flex-direction:column;width:100%;background:rgb(var(--ax-sys-color-lightest-surface))}.recorder-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.recorder-title{margin:0;font-size:.875rem;font-weight:600}.close-button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:50%;font-size:1rem;cursor:pointer;transition:all .2s;opacity:.7}.close-button:hover{background:rgb(var(--ax-sys-color-light-surface));opacity:1}.recorder-content{display:flex;align-items:center;width:100%;padding:1rem}.recorder-idle{display:flex;align-items:center;gap:1rem;width:100%}.record-button,.speech-to-text-button{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border:none;border-radius:50%;font-size:1.5rem;cursor:pointer;transition:all .2s}.record-button{background:rgb(var(--ax-sys-color-primary-500));color:rgb(var(--ax-sys-color-on-primary-surface));box-shadow:0 2px 8px rgba(var(--ax-sys-color-primary-500),.3)}.record-button:hover{background:rgb(var(--ax-sys-color-primary-600))}.speech-to-text-button{background:rgb(var(--ax-sys-color-secondary-surface));color:rgb(var(--ax-sys-color-on-secondary-surface));box-shadow:0 2px 8px rgba(var(--ax-sys-color-secondary-500),.2)}.speech-to-text-button:hover:not(:disabled){background:rgb(var(--ax-sys-color-secondary-600))}.speech-to-text-button:disabled{opacity:.6;cursor:not-allowed}.recorder-hint{font-size:.875rem;opacity:.7}.recorder-transcribing{display:flex;align-items:center;justify-content:center;gap:.75rem;width:100%;padding:.5rem 0}.recorder-transcribing-text{font-size:.875rem;font-weight:500;color:rgb(var(--ax-sys-color-on-light-surface))}.recorder-active{display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem}.recorder-info{display:flex;align-items:center;gap:1.5rem;flex:1}.recording-indicator{display:flex;align-items:center;gap:.5rem}.pulse-dot{width:12px;height:12px;background:rgb(var(--ax-sys-color-danger-500));border-radius:50%;animation:pulse 1.5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.recording-text{font-size:.875rem;font-weight:600;color:rgb(var(--ax-sys-color-danger-500))}.recording-time{font-size:1.25rem;font-weight:600;font-variant-numeric:tabular-nums;min-width:80px}.recorder-actions{display:flex;align-items:center;gap:.75rem}@media(max-width:768px){.voice-recorder{padding:.75rem}.record-button,.speech-to-text-button{width:48px;height:48px;font-size:1.25rem}.recorder-info{gap:1rem}.recording-time{font-size:1.125rem;font-variant-numeric:tabular-nums}.recorder-actions{gap:.5rem}}@media(max-width:480px){.recorder-hint{font-size:.8125rem}.recording-text{display:none}.recording-time{font-size:1rem;min-width:60px;font-variant-numeric:tabular-nums}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3085
3160
  }
3086
3161
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatVoiceRecorderComponent, decorators: [{
3087
3162
  type: Component,
@@ -3374,7 +3449,7 @@ async function axmOpenChatCallStartDialog(options) {
3374
3449
  }
3375
3450
  // Capture DI before any await (dynamic import below).
3376
3451
  const popupService = options.popupService ?? inject(AXPopupService);
3377
- const comp = (await import('./acorex-platform-module-conversation-client-chat-call-start-popup.component-EZjVSlhm.mjs')).AXMChatCallStartPopupComponent;
3452
+ const comp = (await import('./acorex-platform-module-conversation-client-chat-call-start-popup.component-DXkqkS50.mjs')).AXMChatCallStartPopupComponent;
3378
3453
  const data = { conversation };
3379
3454
  await popupService.open(comp, {
3380
3455
  header: false,
@@ -4080,7 +4155,7 @@ class AXMAssistSuggestionChipsComponent {
4080
4155
  }
4081
4156
  </div>
4082
4157
  }
4083
- `, isInline: true, styles: [":host{display:block;width:100%}.axm-assist-suggestion-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:.75rem;padding:2rem}:host(.axm-assist-suggestion-chips-host--compact) .axm-assist-suggestion-chips{flex-direction:column;align-items:stretch;gap:.5rem;padding:0}:host(.axm-assist-suggestion-chips-host--compact) .axm-assist-suggestion-chips__chip{width:100%;justify-content:flex-start;text-align:start;min-height:2.25rem;padding-inline:.875rem;font-weight:500;line-height:1.35;border-radius:.75rem!important}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4158
+ `, isInline: true, styles: [":host{display:block;width:100%}.axm-assist-suggestion-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:.75rem;padding:2rem}:host(.axm-assist-suggestion-chips-host--compact) .axm-assist-suggestion-chips{flex-direction:column;align-items:stretch;gap:.5rem;padding:0}:host(.axm-assist-suggestion-chips-host--compact) .axm-assist-suggestion-chips__chip{width:100%;justify-content:flex-start;text-align:start;min-height:2.25rem;padding-inline:.875rem;font-weight:500;line-height:1.35;border-radius:.75rem!important}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4084
4159
  }
4085
4160
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssistSuggestionChipsComponent, decorators: [{
4086
4161
  type: Component,
@@ -4957,7 +5032,7 @@ async function axmOpenAssistDelegatedAgentDetailDialog(options) {
4957
5032
  options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.dialog-title-suffix'),
4958
5033
  options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.transcript-missing'),
4959
5034
  ]);
4960
- const comp = (await import('./acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-DhRvuCex.mjs'))
5035
+ const comp = (await import('./acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-D1SDsHvl.mjs'))
4961
5036
  .AXMAssistDelegatedAgentDetailPopupComponent;
4962
5037
  const data = {
4963
5038
  delegationCallId: callId,
@@ -4977,7 +5052,7 @@ async function axmOpenAssistDelegatedAgentDetailDialog(options) {
4977
5052
 
4978
5053
  //#region ---- Imports -----
4979
5054
  async function axmOpenAssistToolDetailDialog(options) {
4980
- const comp = (await import('./acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BRW1cHN6.mjs'))
5055
+ const comp = (await import('./acorex-platform-module-conversation-client-assist-tool-detail-popup.component-BV1YH96m.mjs'))
4981
5056
  .AXMAssistToolDetailPopupComponent;
4982
5057
  const data = {
4983
5058
  toolTitle: options.toolTitle.trim() || 'Tool',
@@ -5553,7 +5628,7 @@ class AXMNodeMessageRendererComponent {
5553
5628
  </div>
5554
5629
  }
5555
5630
  </div>
5556
- `, isInline: true, styles: [":host{display:block;inline-size:min(100%,28rem)}:host:has(.axm-user-form-renderer--assist-embed){inline-size:100%;max-inline-size:none}:host:has(.axm-user-form-renderer--assist-embed) .axm-user-form-renderer--assist-embed,:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep axp-layout-renderer{inline-size:100%;max-inline-size:100%}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host{min-block-size:16rem}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host:has(.axp-chart-widget-host__chart--heatmap){inline-size:100%;max-inline-size:100%;min-block-size:0;block-size:auto;overflow:visible}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--funnel{block-size:18rem;max-block-size:25rem;min-block-size:16rem}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--heatmap{inline-size:100%;max-inline-size:100%;block-size:auto;max-block-size:none;overflow:visible}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--radial{inline-size:min(100%,18rem);block-size:auto;min-block-size:12rem;margin-inline:auto}\n"], dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$2.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$2.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5631
+ `, isInline: true, styles: [":host{display:block;inline-size:min(100%,28rem)}:host:has(.axm-user-form-renderer--assist-embed){inline-size:100%;max-inline-size:none}:host:has(.axm-user-form-renderer--assist-embed) .axm-user-form-renderer--assist-embed,:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep axp-layout-renderer{inline-size:100%;max-inline-size:100%}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host{min-block-size:16rem}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host:has(.axp-chart-widget-host__chart--heatmap){inline-size:100%;max-inline-size:100%;min-block-size:0;block-size:auto;overflow:visible}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--funnel{block-size:18rem;max-block-size:25rem;min-block-size:16rem}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--heatmap{inline-size:100%;max-inline-size:100%;block-size:auto;max-block-size:none;overflow:visible}:host:has(.axm-user-form-renderer--assist-embed) ::ng-deep .axp-chart-widget-host__chart--radial{inline-size:min(100%,18rem);block-size:auto;min-block-size:12rem;margin-inline:auto}\n"], dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$2.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$2.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5557
5632
  }
5558
5633
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMNodeMessageRendererComponent, decorators: [{
5559
5634
  type: Component,
@@ -6399,7 +6474,7 @@ class AXMAssistMessageRendererComponent {
6399
6474
  });
6400
6475
  }
6401
6476
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssistMessageRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6402
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMAssistMessageRendererComponent, isStandalone: true, selector: "axm-assist-message-renderer", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"axm-assist-renderer\">\n @if (showDebugUi() && useTranscriptUi() && !isStreaming()) {\n <div class=\"axm-assist-bot\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\">\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div class=\"axm-assist-bot__line\" [class.axm-assist-bot__line--user]=\"line.role === 'user'\" [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\">\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"seg.content.fileId\" />\n } @else if (line.role === 'user' && seg.type === 'text') {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(seg.content)\">\n <ax-conversation-text-renderer [message]=\"syntheticTextMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'think' && showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(seg.content)\">\n <axp-markdown-viewer [markdown]=\"seg.content\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'text') {\n @let parsedLine = parseAssistLineText(seg.content);\n @let displayBody = assistTranscriptAssistantTextBodyForDisplay(line, parsedLine.body);\n @let partitionedLine = partitionAnswerText(displayBody);\n @if (showDebugUi() && parsedLine.thinking) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsedLine.thinking)\">\n <axp-markdown-viewer [markdown]=\"parsedLine.thinking ?? ''\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (partitionedLine.markdown.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(partitionedLine.markdown)\">\n <axp-markdown-viewer [markdown]=\"partitionedLine.markdown\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n @for (renderable of partitionedLine.renderable; track $index) {\n @if (renderable.type === 'node' && axmAssistWidgetNodeFromUnknown(renderable.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 100 + $index, renderable.content)\" />\n </div>\n }\n }\n } @else if (line.role === 'assistant' && (seg.type === 'agent' || seg.type === 'tool') && isDelegatedAgentCommand(seg.content.command)) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n @if (resolveToolModelLabel(seg.content.command, seg.callId); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments, delegatedAgentLabelForCall(seg.callId))\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n @if (resolveToolModelLabel(seg.content.command, seg.callId); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments, delegatedAgentLabelForCall(seg.callId))\"\n ></ax-button>\n </div>\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track outSegIndex; let outSegIndex = $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @let partitionedOut = partitionAnswerText(parsedOut.body);\n @if (partitionedOut.markdown.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(partitionedOut.markdown)\">\n <axp-markdown-viewer [markdown]=\"partitionedOut.markdown\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n @for (renderable of partitionedOut.renderable; track renderableIndex; let renderableIndex = $index) {\n @if (renderable.type === 'node' && axmAssistWidgetNodeFromUnknown(renderable.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + outSegIndex * 10 + renderableIndex, renderable.content)\" />\n </div>\n }\n }\n }\n @case ('think') {\n @if (showDebugUi()) {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(outSeg.content)\">\n {{ outSeg.content }}\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"outSeg.content.fileId\" />\n }\n @case ('node') {\n @let assistNodeWidget = axmAssistWidgetNodeFromUnknown(outSeg.content);\n @if (assistNodeWidget) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + outSegIndex, outSeg.content)\" />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(agentFallbackText)\">\n <axp-markdown-viewer [markdown]=\"agentFallbackText\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n } @else if (line.role === 'assistant' && seg.type === 'tool' && showDebugUi()) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments)\"\n ></ax-button>\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'node') {\n @let assistNodeWidget = axmAssistWidgetNodeFromUnknown(seg.content);\n @if (assistNodeWidget) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file' && !assistHideTranscriptAnswerSegments()) {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"seg.content.fileId\" />\n } @else if (line.role === 'tool' && (seg.type === 'tool_result' || seg.type === 'agent_result')) {\n <!-- merged into the corresponding tool/agent accordion -->\n } @else if (line.role === 'system' && seg.type === 'text' && showDebugUi()) {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(seg.content)\">\n <ax-conversation-text-renderer [message]=\"syntheticTextMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n } @else {\n @if (showDebugUi() || line.role !== 'assistant') {\n <div class=\"axm-assist-bot__fallback axm-assist-bot__segment\" [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\">\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n </div>\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n } @else if (!showDebugUi() && showNonDebugStreamPanel()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\">\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span class=\"axm-assist-renderer__activity-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n <span class=\"axm-assist-renderer__activity-label text-xs text-muted italic\">{{ assistActivityMessageKey() | translate | async }}</span>\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n @if (isStreaming() && !assistAnswerMarkdown()) {\n <div class=\"axm-assist-renderer__waiting\">\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n </div>\n }\n </div>\n } @else if (showDebugUi()) {\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span class=\"axm-assist-renderer__activity-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n <span class=\"axm-assist-renderer__activity-label text-xs text-muted italic\">{{ assistActivityMessageKey() | translate | async }}</span>\n </div>\n @if (streamThink().trim()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(streamThink())\">\n <axp-markdown-viewer [markdown]=\"streamThink()\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n @if (toolCalls().length) {\n <div class=\"axm-assist-renderer__tools\">\n @for (tc of toolCalls(); track tc.id) {\n @if (isDelegatedAgentCommand(tc.name)) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n @if (tc.state === 'running') {\n <span class=\"axm-assist-renderer__agent-live-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n } @else {\n <span class=\"inline-block w-3 h-3 rounded-full bg-success-500 shrink-0\" aria-hidden=\"true\"></span>\n }\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n @if (resolveToolModelLabel(tc.name, tc.id); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [disabled]=\"tc.state === 'running'\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div class=\"axm-assist-renderer__agent-live-stream\" [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\">\n {{ tc.nestedStreamText }}\n </div>\n }\n } @else {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n @if (tc.state === 'running') {\n <span class=\"axm-assist-renderer__agent-live-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n } @else {\n <span class=\"inline-block w-3 h-3 rounded-full bg-success-500 shrink-0\" aria-hidden=\"true\"></span>\n }\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [disabled]=\"tc.state === 'running'\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && !assistAnswerMarkdown() && !streamThink().trim() && !toolCalls().length) {\n <div class=\"axm-assist-renderer__waiting\">\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n </div>\n }\n </div>\n } @else if (!useTranscriptUi()) {\n @if (parsed().thinking) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsed().thinking)\">\n <axp-markdown-viewer [markdown]=\"parsed().thinking ?? ''\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (toolCalls().length) {\n <div class=\"axm-assist-renderer__tools\">\n @for (tc of toolCalls(); track tc.id) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light axm-assist-renderer__tool-title-icon\" [class.fa-people-group]=\"isDelegatedAgentCommand(tc.name)\" [class.fa-screwdriver-wrench]=\"!isDelegatedAgentCommand(tc.name)\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n @if (isDelegatedAgentCommand(tc.name) && resolveToolModelLabel(tc.name, tc.id); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n }\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer class=\"axm-assist-renderer__run-meta-wrap\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\">\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell axm-assist-renderer__run-meta-accordion mb-0!\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-chart-line axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.run-meta.title' | translate | async }}\n </span>\n <!-- @if (dbg.modelTitle || dbg.modelEntityId) {\n <span class=\"axm-assist-renderer__run-meta-header-sub\">{{ dbg.modelTitle || dbg.modelEntityId }}</span>\n } -->\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__run-meta axm-assist-renderer__run-meta--panel\">\n <div class=\"axm-assist-renderer__run-meta-grid\">\n @if (dbg.modelTitle || dbg.modelEntityId) {\n <div class=\"axm-assist-renderer__meta-tile axm-assist-renderer__meta-tile--wide\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.model' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value\">{{ dbg.modelTitle || dbg.modelEntityId }}</div>\n <!-- @if (dbg.modelTitle && dbg.modelEntityId) {\n <div class=\"axm-assist-renderer__meta-tile-sub\">{{ dbg.modelEntityId }}</div>\n } -->\n </div>\n }\n @if (dbg.durationMs != null) {\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.duration' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ formatAssistRunDuration(dbg.durationMs) }}\n </div>\n </div>\n }\n @if (dbg.usage; as totals) {\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@ai-management:chat.usage-prompt' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.promptTokens | number }}\n @if (totals.cachedPromptTokens) {\n <span class=\"axm-assist-renderer__meta-tile-note\">(+{{ totals.cachedPromptTokens | number }} {{ '@ai-management:chat.usage-cached' | translate | async }})</span>\n }\n </div>\n </div>\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@ai-management:chat.usage-completion' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.completionTokens | number }}\n </div>\n </div>\n <div class=\"axm-assist-renderer__meta-tile axm-assist-renderer__meta-tile--accent\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.total-tokens' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.totalTokens | number }}\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </footer>\n }\n\n <ng-template #assistUnifiedAnswerBlock>\n @if (assistAnswerMarkdown()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(assistAnswerMarkdown())\">\n <axp-markdown-viewer [markdown]=\"assistAnswerMarkdown()\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n <!-- @if (isStreaming()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } -->\n }\n @if (!isStreaming()) {\n @for (item of assistPayloadAppendItems(); track $index; let itemIndex = $index) {\n @switch (item.kind) {\n @case ('node') {\n @if (axmAssistWidgetNodeFromUnknown(item.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticAppendNodeMessage(itemIndex, item.content)\" />\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"item.fileId\" />\n }\n @case ('followUp') {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-assist-suggestion-chips [items]=\"item.items\" />\n </div>\n }\n }\n }\n }\n </ng-template>\n\n @if (showRetryScreen()) {\n <ax-alert class=\"axm-assist-renderer__retry-alert\" color=\"danger\" role=\"alert\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.retry.aria.panel' | translate | async) ?? ''\">\n <ax-icon><i [class]=\"assistRetryAlertIcon()\"></i></ax-icon>\n <ax-title>{{ assistRetryTitleKey() | translate | async }}</ax-title>\n <ax-content>\n <div class=\"axm-assist-renderer__retry-alert-body\">\n <div class=\"axm-assist-renderer__retry-alert-text\">\n <p class=\"axm-assist-renderer__retry-description\">\n {{ assistRetryDescriptionKey() | translate | async }}\n </p>\n @if (assistResponseError()) {\n <p class=\"axm-assist-renderer__retry-error-detail\">\n {{ assistResponseError() }}\n </p>\n }\n </div>\n\n <ax-button class=\"axm-assist-renderer__retry-action ax-sm\" color=\"danger\" look=\"solid\" [disabled]=\"isRetrying()\" [text]=\"('@conversation:chat.assist-renderer.retry.action' | translate | async) ?? ''\" (onClick)=\"onRetryAssistResponse()\">\n <i class=\"fa-light fa-arrows-rotate\" prefix></i>\n </ax-button>\n </div>\n </ax-content>\n </ax-alert>\n }\n</div>\n", styles: ["@layer properties;.axm-assist-renderer{display:flex;flex-direction:column;gap:.25rem}.axm-assist-renderer axm-assist-suggestion-chips>div{padding:0;padding-top:calc(var(--spacing, .25rem) * 4)}.axm-assist-renderer .axm-assist-renderer__cursor{display:inline-block;inline-size:6px;block-size:1em;margin-inline-start:2px;background:rgb(var(--ax-sys-color-primary-500));border-radius:1px;animation:axm-blink .8s steps(2) infinite;vertical-align:text-bottom}.axm-assist-renderer .axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-assist-renderer .axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-block:.15rem}.axm-assist-renderer .axm-assist-renderer__activity-label{line-height:1.45}.axm-assist-renderer .axm-assist-renderer__text{white-space:pre-line;word-break:break-word;line-height:1.85;font-size:.95rem;letter-spacing:.002em;text-wrap:pretty}.axm-assist-renderer .axm-assist-renderer__markdown .axp-markdown-viewer__content :is(p,ul,ol){margin-block:.45rem}.axm-assist-renderer .axm-assist-renderer__markdown .axp-markdown-viewer__content li{line-height:1.8}.axm-assist-renderer .axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer .axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer .axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer .axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer .axm-assist-renderer__accordion-header{display:flex;cursor:pointer;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);--tw-border-style: none;border-style:none;padding:.5rem .75rem;background:transparent;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer .axm-assist-renderer__accordion-header-main{display:flex;flex-direction:column;min-inline-size:0;gap:.1rem}.axm-assist-renderer .axm-assist-renderer__accordion-header-title{display:inline-flex;align-items:center;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.8125rem;line-height:1.25;color:rgb(var(--ax-sys-color-on-surface));gap:.4rem}.axm-assist-renderer .axm-assist-renderer__header-trailing{display:inline-flex;flex-shrink:0;align-items:center;gap:.35rem}.axm-assist-renderer .axm-assist-renderer__delegated-agent-detail-link{text-decoration-line:underline;padding:.25rem;padding-top:0}.axm-assist-renderer .axm-assist-renderer__badge{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;overflow:hidden;border-radius:calc(infinity * 1px);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap;max-width:min(100%,14rem);padding:.1875rem .65rem;font-size:.6875rem;line-height:1.3;letter-spacing:.03em}.axm-assist-renderer .axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer .axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer .axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer .axm-assist-renderer__thinking-chevron{display:inline-block;flex-shrink:0;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1}.axm-assist-renderer .axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.axm-assist-renderer .axm-assist-renderer__thinking-body{padding:.625rem .75rem .75rem;font-size:.78rem;color:rgb(var(--ax-sys-color-neutral-700));word-break:break-word;line-height:1.55}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content{font-size:inherit;color:inherit;line-height:inherit}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content :is(p,ul,ol){margin-block:.35rem}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content li{line-height:inherit}.axm-assist-renderer .axm-assist-renderer__tools{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-assist-renderer .axm-assist-renderer__tool-row{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.5rem .65rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));border:1px solid rgb(var(--ax-sys-color-border-lighter-surface))}.axm-assist-renderer .axm-assist-renderer__tool-row-main{display:flex;min-width:0px;align-items:center;gap:.45rem}.axm-assist-renderer .axm-assist-renderer__tool-row-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.axm-assist-renderer .axm-assist-renderer__tool-model-label{flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);max-width:9rem;letter-spacing:.01em;color:rgb(var(--ax-sys-color-neutral-600));opacity:.78}.axm-assist-renderer .axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer .axm-assist-renderer__tool-body{display:flex;flex-direction:column;padding:.625rem .75rem .75rem;gap:.35rem}.axm-assist-renderer .axm-assist-renderer__tool-section-label{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-transform:uppercase;font-size:.625rem;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer .axm-assist-renderer__tool-pre{margin:0;overflow:auto;border-radius:var(--radius-md, .375rem);max-block-size:10rem;background:rgb(var(--ax-sys-color-light-surface));padding:.5rem;font-family:var(--ax-font-mono, monospace);font-size:.675rem;line-height:1.45;word-break:break-word}.axm-assist-renderer .axm-assist-renderer__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer .axm-assist-renderer__run-meta-header-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));max-width:100%}.axm-assist-renderer .axm-assist-renderer__run-meta{display:flex;flex-direction:column;margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));gap:.45rem}.axm-assist-renderer .axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer .axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer .axm-assist-renderer__meta-tile{min-width:0px;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer .axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer .axm-assist-renderer__meta-tile-label{--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);text-transform:uppercase;font-size:.6rem;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer .axm-assist-renderer__meta-tile-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.78rem;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer .axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.axm-assist-renderer .axm-assist-renderer__meta-tile-sub{margin-block-start:.15rem;font-size:.65rem;line-height:1.3;color:rgb(var(--ax-sys-color-neutral-700));font-family:var(--ax-font-mono, ui-monospace, monospace);word-break:break-all}.axm-assist-renderer .axm-assist-renderer__meta-tile-note{display:inline;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);margin-inline-start:.2rem;font-size:.65rem;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer .axm-assist-renderer__tool-editor-wrap{overflow:hidden;border-radius:var(--radius-md, .375rem);background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.axm-assist-renderer .axm-assist-renderer__dot{inline-size:6px;block-size:6px;border-radius:50%;background:rgb(var(--ax-sys-color-neutral-500));animation:axm-blink 1.2s ease-in-out infinite}.axm-assist-renderer .axm-assist-renderer__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer .axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer .axm-assist-renderer__agent-live-block{display:flex;flex-direction:column;border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;gap:.65rem;max-inline-size:min(42rem,100%)}.axm-assist-renderer .axm-assist-renderer__agent-live-block--in-accordion{background:rgb(var(--ax-sys-color-light-surface));border-radius:.5rem;padding:.5rem .55rem .55rem;max-inline-size:none}.axm-assist-renderer .axm-assist-renderer__agent-live-header{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.axm-assist-renderer .axm-assist-renderer__agent-live-title{flex:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.8125rem;color:rgb(var(--ax-sys-color-on-surface));min-inline-size:0}.axm-assist-renderer .axm-assist-renderer__agent-live-prompt{align-self:flex-end;font-size:.8125rem;line-height:1.55;word-break:break-word;padding:.5rem .75rem;border-radius:1.25rem;background:rgb(var(--ax-sys-color-lightest-surface));max-inline-size:min(92%,36rem)}.axm-assist-renderer .axm-assist-renderer__agent-live-stream{font-size:.8125rem;line-height:1.55;white-space:pre-line;word-break:break-word;padding-block-start:.15rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-name{flex:1;overflow:hidden;text-overflow:ellipsis;font-family:var(--ax-font-mono, monospace);font-size:.7rem;min-inline-size:0}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-status{flex-shrink:0;color:rgb(var(--ax-sys-color-neutral-600))}.axm-assist-renderer .axm-assist-renderer__retry-alert-body{display:flex;align-items:flex-start;gap:.75rem}.axm-assist-renderer .axm-assist-renderer__retry-alert-text{display:flex;flex:1;flex-direction:column;min-inline-size:0;gap:.3rem}.axm-assist-renderer .axm-assist-renderer__retry-description{margin:0;font-size:.8125rem;line-height:1.5;opacity:.92}.axm-assist-renderer .axm-assist-renderer__retry-error-detail{margin:.15rem 0 0;font-size:.75rem;line-height:1.45;font-family:var(--ax-font-mono, ui-monospace, monospace);word-break:break-word;opacity:.88}.axm-assist-renderer .axm-assist-renderer__retry-action{flex-shrink:0;align-self:center}.axm-assist-bot,.axm-assist-bot .axm-assist-bot__final-line{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}.axm-assist-bot .axm-assist-bot__segment{unicode-bidi:isolate;font-size:.95rem;line-height:1.8;letter-spacing:.002em;color:rgb(var(--ax-sys-color-on-surface));text-wrap:pretty}.axm-assist-bot .axm-assist-bot__segment:has(axm-chat-user-form-renderer){inline-size:100%;max-inline-size:100%}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-bot .axm-assist-bot__line--user{align-self:flex-end}.axm-assist-bot .axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot .axm-assist-bot__tool-result{border-radius:var(--radius-lg, .5rem);background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot .axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXConversationTextRendererComponent, selector: "ax-conversation-text-renderer", inputs: ["message"] }, { kind: "component", type: AXMNodeMessageRendererComponent, selector: "axm-chat-user-form-renderer", inputs: ["message", "node"], outputs: ["formSubmitted"] }, { kind: "component", type: AXMAssistBotFileLineComponent, selector: "axm-assist-bot-file-line", inputs: ["parentMessage", "fileId"] }, { kind: "component", type: AXMAssistSuggestionChipsComponent, selector: "axm-assist-suggestion-chips", inputs: ["items", "compact", "sendInPlace", "disabled"], outputs: ["conversationCreated"] }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i1$3.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i1$3.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i1$3.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i1$3.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "ngmodule", type: AXAlertModule }, { kind: "component", type: i2$2.AXAlertComponent, selector: "ax-alert", inputs: ["color", "timeOut"], outputs: ["colorChange", "onClosed", "timeOutChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXCodeEditorModule }, { kind: "component", type: i5.AXCodeEditorComponent, selector: "ax-code-editor", inputs: ["disabled", "value", "state", "name", "id", "language", "readonly", "placeholder", "lineNumbers", "lineWrapping", "tabSize", "indentWithTab", "theme", "extensions", "ariaLabel", "focusOnReady", "formatOnSave", "minRow", "customCompletions"], outputs: ["onValueChanged", "valueChange", "stateChange", "readonlyChange", "disabledChange", "ready", "save"] }, { kind: "component", type: AXPMarkdownViewerComponent, selector: "axp-markdown-viewer", inputs: ["markdown"] }, { kind: "directive", type: AXPMarkdownTemplateDirective, selector: "ng-template[axpMarkdownTemplate]", inputs: ["axpMarkdownTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6477
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMAssistMessageRendererComponent, isStandalone: true, selector: "axm-assist-message-renderer", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"axm-assist-renderer\">\n @if (showDebugUi() && useTranscriptUi() && !isStreaming()) {\n <div class=\"axm-assist-bot\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\">\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div class=\"axm-assist-bot__line\" [class.axm-assist-bot__line--user]=\"line.role === 'user'\" [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\">\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"seg.content.fileId\" />\n } @else if (line.role === 'user' && seg.type === 'text') {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(seg.content)\">\n <ax-conversation-text-renderer [message]=\"syntheticTextMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'think' && showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(seg.content)\">\n <axp-markdown-viewer [markdown]=\"seg.content\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'text') {\n @let parsedLine = parseAssistLineText(seg.content);\n @let displayBody = assistTranscriptAssistantTextBodyForDisplay(line, parsedLine.body);\n @let partitionedLine = partitionAnswerText(displayBody);\n @if (showDebugUi() && parsedLine.thinking) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsedLine.thinking)\">\n <axp-markdown-viewer [markdown]=\"parsedLine.thinking ?? ''\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (partitionedLine.markdown.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(partitionedLine.markdown)\">\n <axp-markdown-viewer [markdown]=\"partitionedLine.markdown\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n @for (renderable of partitionedLine.renderable; track $index) {\n @if (renderable.type === 'node' && axmAssistWidgetNodeFromUnknown(renderable.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 100 + $index, renderable.content)\" />\n </div>\n }\n }\n } @else if (line.role === 'assistant' && (seg.type === 'agent' || seg.type === 'tool') && isDelegatedAgentCommand(seg.content.command)) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n @if (resolveToolModelLabel(seg.content.command, seg.callId); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments, delegatedAgentLabelForCall(seg.callId))\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n @if (resolveToolModelLabel(seg.content.command, seg.callId); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments, delegatedAgentLabelForCall(seg.callId))\"\n ></ax-button>\n </div>\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track outSegIndex; let outSegIndex = $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @let partitionedOut = partitionAnswerText(parsedOut.body);\n @if (partitionedOut.markdown.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(partitionedOut.markdown)\">\n <axp-markdown-viewer [markdown]=\"partitionedOut.markdown\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n @for (renderable of partitionedOut.renderable; track renderableIndex; let renderableIndex = $index) {\n @if (renderable.type === 'node' && axmAssistWidgetNodeFromUnknown(renderable.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + outSegIndex * 10 + renderableIndex, renderable.content)\" />\n </div>\n }\n }\n }\n @case ('think') {\n @if (showDebugUi()) {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(outSeg.content)\">\n {{ outSeg.content }}\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"outSeg.content.fileId\" />\n }\n @case ('node') {\n @let assistNodeWidget = axmAssistWidgetNodeFromUnknown(outSeg.content);\n @if (assistNodeWidget) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + outSegIndex, outSeg.content)\" />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(agentFallbackText)\">\n <axp-markdown-viewer [markdown]=\"agentFallbackText\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n } @else if (line.role === 'assistant' && seg.type === 'tool' && showDebugUi()) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(seg.content.command) }}</span>\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openTranscriptToolDetail(seg.callId, seg.content.command, seg.content.arguments)\"\n ></ax-button>\n </div>\n } @else if (line.role === 'assistant' && seg.type === 'node') {\n @let assistNodeWidget = axmAssistWidgetNodeFromUnknown(seg.content);\n @if (assistNodeWidget) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file' && !assistHideTranscriptAnswerSegments()) {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"seg.content.fileId\" />\n } @else if (line.role === 'tool' && (seg.type === 'tool_result' || seg.type === 'agent_result')) {\n <!-- merged into the corresponding tool/agent accordion -->\n } @else if (line.role === 'system' && seg.type === 'text' && showDebugUi()) {\n <div class=\"axm-assist-bot__segment\" [attr.dir]=\"segmentDir(seg.content)\">\n <ax-conversation-text-renderer [message]=\"syntheticTextMessage(lineIndex, segIndex, seg.content)\" />\n </div>\n } @else {\n @if (showDebugUi() || line.role !== 'assistant') {\n <div class=\"axm-assist-bot__fallback axm-assist-bot__segment\" [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\">\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n </div>\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n } @else if (!showDebugUi() && showNonDebugStreamPanel()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\">\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span class=\"axm-assist-renderer__activity-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n <span class=\"axm-assist-renderer__activity-label text-xs text-muted italic\">{{ assistActivityMessageKey() | translate | async }}</span>\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n @if (isStreaming() && !assistAnswerMarkdown()) {\n <div class=\"axm-assist-renderer__waiting\">\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n </div>\n }\n </div>\n } @else if (showDebugUi()) {\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span class=\"axm-assist-renderer__activity-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n <span class=\"axm-assist-renderer__activity-label text-xs text-muted italic\">{{ assistActivityMessageKey() | translate | async }}</span>\n </div>\n @if (streamThink().trim()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(streamThink())\">\n <axp-markdown-viewer [markdown]=\"streamThink()\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n @if (toolCalls().length) {\n <div class=\"axm-assist-renderer__tools\">\n @for (tc of toolCalls(); track tc.id) {\n @if (isDelegatedAgentCommand(tc.name)) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n @if (tc.state === 'running') {\n <span class=\"axm-assist-renderer__agent-live-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n } @else {\n <span class=\"inline-block w-3 h-3 rounded-full bg-success-500 shrink-0\" aria-hidden=\"true\"></span>\n }\n <i class=\"fa-light fa-people-group axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n @if (resolveToolModelLabel(tc.name, tc.id); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [disabled]=\"tc.state === 'running'\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div class=\"axm-assist-renderer__agent-live-stream\" [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\">\n {{ tc.nestedStreamText }}\n </div>\n }\n } @else {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n @if (tc.state === 'running') {\n <span class=\"axm-assist-renderer__agent-live-spin inline-block w-3 h-3 rounded-full border-2 border-primary-500 border-t-transparent fa-spin shrink-0\" aria-hidden=\"true\"></span>\n } @else {\n <span class=\"inline-block w-3 h-3 rounded-full bg-success-500 shrink-0\" aria-hidden=\"true\"></span>\n }\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [disabled]=\"tc.state === 'running'\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && !assistAnswerMarkdown() && !streamThink().trim() && !toolCalls().length) {\n <div class=\"axm-assist-renderer__waiting\">\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n <span class=\"axm-assist-renderer__dot\"></span>\n </div>\n }\n </div>\n } @else if (!useTranscriptUi()) {\n @if (parsed().thinking) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell mb-0!\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-brain axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.sections.thinking' | translate | async }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsed().thinking)\">\n <axp-markdown-viewer [markdown]=\"parsed().thinking ?? ''\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (toolCalls().length) {\n <div class=\"axm-assist-renderer__tools\">\n @for (tc of toolCalls(); track tc.id) {\n <div class=\"axm-assist-renderer__tool-row\">\n <div class=\"axm-assist-renderer__tool-row-main\">\n <i class=\"fa-light axm-assist-renderer__tool-title-icon\" [class.fa-people-group]=\"isDelegatedAgentCommand(tc.name)\" [class.fa-screwdriver-wrench]=\"!isDelegatedAgentCommand(tc.name)\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__tool-row-title\">{{ resolveToolDisplayTitle(tc.name) }}</span>\n @if (isDelegatedAgentCommand(tc.name) && resolveToolModelLabel(tc.name, tc.id); as modelLabel) {\n <span class=\"axm-assist-renderer__tool-model-label\">{{ modelLabel }}</span>\n }\n </div>\n <ax-button\n look=\"outline\"\n color=\"primary\"\n class=\"ax-xs\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\"\n (onClick)=\"openLegacyToolDetail(tc)\"\n ></ax-button>\n </div>\n }\n </div>\n }\n <ng-container *ngTemplateOutlet=\"assistUnifiedAnswerBlock\" />\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer class=\"axm-assist-renderer__run-meta-wrap\" role=\"region\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\">\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__thinking-accordion axm-assist-renderer__collapse-shell axm-assist-renderer__run-meta-accordion mb-0!\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader role=\"button\" [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\">\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\" [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\" aria-hidden=\"true\"></i>\n <i class=\"fa-light fa-chart-line axm-assist-renderer__tool-title-icon\" aria-hidden=\"true\"></i>\n {{ '@conversation:chat.assist-renderer.run-meta.title' | translate | async }}\n </span>\n <!-- @if (dbg.modelTitle || dbg.modelEntityId) {\n <span class=\"axm-assist-renderer__run-meta-header-sub\">{{ dbg.modelTitle || dbg.modelEntityId }}</span>\n } -->\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__run-meta axm-assist-renderer__run-meta--panel\">\n <div class=\"axm-assist-renderer__run-meta-grid\">\n @if (dbg.modelTitle || dbg.modelEntityId) {\n <div class=\"axm-assist-renderer__meta-tile axm-assist-renderer__meta-tile--wide\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.model' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value\">{{ dbg.modelTitle || dbg.modelEntityId }}</div>\n <!-- @if (dbg.modelTitle && dbg.modelEntityId) {\n <div class=\"axm-assist-renderer__meta-tile-sub\">{{ dbg.modelEntityId }}</div>\n } -->\n </div>\n }\n @if (dbg.durationMs != null) {\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.duration' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ formatAssistRunDuration(dbg.durationMs) }}\n </div>\n </div>\n }\n @if (dbg.usage; as totals) {\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@ai-management:chat.usage-prompt' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.promptTokens | number }}\n @if (totals.cachedPromptTokens) {\n <span class=\"axm-assist-renderer__meta-tile-note\">(+{{ totals.cachedPromptTokens | number }} {{ '@ai-management:chat.usage-cached' | translate | async }})</span>\n }\n </div>\n </div>\n <div class=\"axm-assist-renderer__meta-tile\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@ai-management:chat.usage-completion' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.completionTokens | number }}\n </div>\n </div>\n <div class=\"axm-assist-renderer__meta-tile axm-assist-renderer__meta-tile--accent\">\n <div class=\"axm-assist-renderer__meta-tile-label\">\n {{ '@conversation:chat.assist-renderer.run-meta.total-tokens' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__meta-tile-value axm-assist-renderer__meta-tile-value--mono\">\n {{ totals.totalTokens | number }}\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </footer>\n }\n\n <ng-template #assistUnifiedAnswerBlock>\n @if (assistAnswerMarkdown()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(assistAnswerMarkdown())\">\n <axp-markdown-viewer [markdown]=\"assistAnswerMarkdown()\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor [ngModel]=\"markdownCodeValue(segment)\" [readonly]=\"true\" [language]=\"markdownCodeLanguage(segment)\" [lineNumbers]=\"true\" class=\"axm-assist-renderer__tool-editor\"></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n <!-- @if (isStreaming()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } -->\n }\n @if (!isStreaming()) {\n @for (item of assistPayloadAppendItems(); track $index; let itemIndex = $index) {\n @switch (item.kind) {\n @case ('node') {\n @if (axmAssistWidgetNodeFromUnknown(item.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticAppendNodeMessage(itemIndex, item.content)\" />\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-file-line [parentMessage]=\"message()\" [fileId]=\"item.fileId\" />\n }\n @case ('followUp') {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-assist-suggestion-chips [items]=\"item.items\" />\n </div>\n }\n }\n }\n }\n </ng-template>\n\n @if (showRetryScreen()) {\n <ax-alert class=\"axm-assist-renderer__retry-alert\" color=\"danger\" role=\"alert\" [attr.aria-label]=\"('@conversation:chat.assist-renderer.retry.aria.panel' | translate | async) ?? ''\">\n <ax-icon><i [class]=\"assistRetryAlertIcon()\"></i></ax-icon>\n <ax-title>{{ assistRetryTitleKey() | translate | async }}</ax-title>\n <ax-content>\n <div class=\"axm-assist-renderer__retry-alert-body\">\n <div class=\"axm-assist-renderer__retry-alert-text\">\n <p class=\"axm-assist-renderer__retry-description\">\n {{ assistRetryDescriptionKey() | translate | async }}\n </p>\n @if (assistResponseError()) {\n <p class=\"axm-assist-renderer__retry-error-detail\">\n {{ assistResponseError() }}\n </p>\n }\n </div>\n\n <ax-button class=\"axm-assist-renderer__retry-action ax-sm\" color=\"danger\" look=\"solid\" [disabled]=\"isRetrying()\" [text]=\"('@conversation:chat.assist-renderer.retry.action' | translate | async) ?? ''\" (onClick)=\"onRetryAssistResponse()\">\n <i class=\"fa-light fa-arrows-rotate\" prefix></i>\n </ax-button>\n </div>\n </ax-content>\n </ax-alert>\n }\n</div>\n", styles: ["@layer properties;.axm-assist-renderer{display:flex;flex-direction:column;gap:.25rem}.axm-assist-renderer axm-assist-suggestion-chips>div{padding:0;padding-top:calc(var(--spacing, .25rem) * 4)}.axm-assist-renderer .axm-assist-renderer__cursor{display:inline-block;inline-size:6px;block-size:1em;margin-inline-start:2px;background:rgb(var(--ax-sys-color-primary-500));border-radius:1px;animation:axm-blink .8s steps(2) infinite;vertical-align:text-bottom}.axm-assist-renderer .axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-assist-renderer .axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-block:.15rem}.axm-assist-renderer .axm-assist-renderer__activity-label{line-height:1.45}.axm-assist-renderer .axm-assist-renderer__text{white-space:pre-line;word-break:break-word;line-height:1.85;font-size:.95rem;letter-spacing:.002em;text-wrap:pretty}.axm-assist-renderer .axm-assist-renderer__markdown .axp-markdown-viewer__content :is(p,ul,ol){margin-block:.45rem}.axm-assist-renderer .axm-assist-renderer__markdown .axp-markdown-viewer__content li{line-height:1.8}.axm-assist-renderer .axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer .axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer .axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer .axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer .axm-assist-renderer__accordion-header{display:flex;cursor:pointer;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);--tw-border-style: none;border-style:none;padding:.5rem .75rem;background:transparent;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer .axm-assist-renderer__accordion-header-main{display:flex;flex-direction:column;min-inline-size:0;gap:.1rem}.axm-assist-renderer .axm-assist-renderer__accordion-header-title{display:inline-flex;align-items:center;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.8125rem;line-height:1.25;color:rgb(var(--ax-sys-color-on-surface));gap:.4rem}.axm-assist-renderer .axm-assist-renderer__header-trailing{display:inline-flex;flex-shrink:0;align-items:center;gap:.35rem}.axm-assist-renderer .axm-assist-renderer__delegated-agent-detail-link{text-decoration-line:underline;padding:.25rem;padding-top:0}.axm-assist-renderer .axm-assist-renderer__badge{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;overflow:hidden;border-radius:calc(infinity * 1px);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap;max-width:min(100%,14rem);padding:.1875rem .65rem;font-size:.6875rem;line-height:1.3;letter-spacing:.03em}.axm-assist-renderer .axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer .axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer .axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer .axm-assist-renderer__thinking-chevron{display:inline-block;flex-shrink:0;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1}.axm-assist-renderer .axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.axm-assist-renderer .axm-assist-renderer__thinking-body{padding:.625rem .75rem .75rem;font-size:.78rem;color:rgb(var(--ax-sys-color-neutral-700));word-break:break-word;line-height:1.55}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content{font-size:inherit;color:inherit;line-height:inherit}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content :is(p,ul,ol){margin-block:.35rem}.axm-assist-renderer .axm-assist-renderer__thinking-body.axm-assist-renderer__markdown .axp-markdown-viewer__content li{line-height:inherit}.axm-assist-renderer .axm-assist-renderer__tools{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-assist-renderer .axm-assist-renderer__tool-row{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.5rem .65rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));border:1px solid rgb(var(--ax-sys-color-border-lighter-surface))}.axm-assist-renderer .axm-assist-renderer__tool-row-main{display:flex;min-width:0px;align-items:center;gap:.45rem}.axm-assist-renderer .axm-assist-renderer__tool-row-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.axm-assist-renderer .axm-assist-renderer__tool-model-label{flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);max-width:9rem;letter-spacing:.01em;color:rgb(var(--ax-sys-color-neutral-600));opacity:.78}.axm-assist-renderer .axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer .axm-assist-renderer__tool-body{display:flex;flex-direction:column;padding:.625rem .75rem .75rem;gap:.35rem}.axm-assist-renderer .axm-assist-renderer__tool-section-label{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-transform:uppercase;font-size:.625rem;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer .axm-assist-renderer__tool-pre{margin:0;overflow:auto;border-radius:var(--radius-md, .375rem);max-block-size:10rem;background:rgb(var(--ax-sys-color-light-surface));padding:.5rem;font-family:var(--ax-font-mono, monospace);font-size:.675rem;line-height:1.45;word-break:break-word}.axm-assist-renderer .axm-assist-renderer__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer .axm-assist-renderer__run-meta-header-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));max-width:100%}.axm-assist-renderer .axm-assist-renderer__run-meta{display:flex;flex-direction:column;margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));gap:.45rem}.axm-assist-renderer .axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer .axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer .axm-assist-renderer__meta-tile{min-width:0px;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer .axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer .axm-assist-renderer__meta-tile-label{--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);text-transform:uppercase;font-size:.6rem;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer .axm-assist-renderer__meta-tile-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.78rem;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer .axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.axm-assist-renderer .axm-assist-renderer__meta-tile-sub{margin-block-start:.15rem;font-size:.65rem;line-height:1.3;color:rgb(var(--ax-sys-color-neutral-700));font-family:var(--ax-font-mono, ui-monospace, monospace);word-break:break-all}.axm-assist-renderer .axm-assist-renderer__meta-tile-note{display:inline;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);margin-inline-start:.2rem;font-size:.65rem;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer .axm-assist-renderer__tool-editor-wrap{overflow:hidden;border-radius:var(--radius-md, .375rem);background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer .axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.axm-assist-renderer .axm-assist-renderer__dot{inline-size:6px;block-size:6px;border-radius:50%;background:rgb(var(--ax-sys-color-neutral-500));animation:axm-blink 1.2s ease-in-out infinite}.axm-assist-renderer .axm-assist-renderer__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer .axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer .axm-assist-renderer__agent-live-block{display:flex;flex-direction:column;border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;gap:.65rem;max-inline-size:min(42rem,100%)}.axm-assist-renderer .axm-assist-renderer__agent-live-block--in-accordion{background:rgb(var(--ax-sys-color-light-surface));border-radius:.5rem;padding:.5rem .55rem .55rem;max-inline-size:none}.axm-assist-renderer .axm-assist-renderer__agent-live-header{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.axm-assist-renderer .axm-assist-renderer__agent-live-title{flex:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);font-size:.8125rem;color:rgb(var(--ax-sys-color-on-surface));min-inline-size:0}.axm-assist-renderer .axm-assist-renderer__agent-live-prompt{align-self:flex-end;font-size:.8125rem;line-height:1.55;word-break:break-word;padding:.5rem .75rem;border-radius:1.25rem;background:rgb(var(--ax-sys-color-lightest-surface));max-inline-size:min(92%,36rem)}.axm-assist-renderer .axm-assist-renderer__agent-live-stream{font-size:.8125rem;line-height:1.55;white-space:pre-line;word-break:break-word;padding-block-start:.15rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-name{flex:1;overflow:hidden;text-overflow:ellipsis;font-family:var(--ax-font-mono, monospace);font-size:.7rem;min-inline-size:0}.axm-assist-renderer .axm-assist-renderer__agent-live-nested-status{flex-shrink:0;color:rgb(var(--ax-sys-color-neutral-600))}.axm-assist-renderer .axm-assist-renderer__retry-alert-body{display:flex;align-items:flex-start;gap:.75rem}.axm-assist-renderer .axm-assist-renderer__retry-alert-text{display:flex;flex:1;flex-direction:column;min-inline-size:0;gap:.3rem}.axm-assist-renderer .axm-assist-renderer__retry-description{margin:0;font-size:.8125rem;line-height:1.5;opacity:.92}.axm-assist-renderer .axm-assist-renderer__retry-error-detail{margin:.15rem 0 0;font-size:.75rem;line-height:1.45;font-family:var(--ax-font-mono, ui-monospace, monospace);word-break:break-word;opacity:.88}.axm-assist-renderer .axm-assist-renderer__retry-action{flex-shrink:0;align-self:center}.axm-assist-bot,.axm-assist-bot .axm-assist-bot__final-line{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}.axm-assist-bot .axm-assist-bot__segment{unicode-bidi:isolate;font-size:.95rem;line-height:1.8;letter-spacing:.002em;color:rgb(var(--ax-sys-color-on-surface));text-wrap:pretty}.axm-assist-bot .axm-assist-bot__segment:has(axm-chat-user-form-renderer){inline-size:100%;max-inline-size:100%}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot .axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-bot .axm-assist-bot__line--user{align-self:flex-end}.axm-assist-bot .axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot .axm-assist-bot__tool-result{border-radius:var(--radius-lg, .5rem);background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot .axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXConversationTextRendererComponent, selector: "ax-conversation-text-renderer", inputs: ["message"] }, { kind: "component", type: AXMNodeMessageRendererComponent, selector: "axm-chat-user-form-renderer", inputs: ["message", "node"], outputs: ["formSubmitted"] }, { kind: "component", type: AXMAssistBotFileLineComponent, selector: "axm-assist-bot-file-line", inputs: ["parentMessage", "fileId"] }, { kind: "component", type: AXMAssistSuggestionChipsComponent, selector: "axm-assist-suggestion-chips", inputs: ["items", "compact", "sendInPlace", "disabled"], outputs: ["conversationCreated"] }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i1$3.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i1$3.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i1$3.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i1$3.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "ngmodule", type: AXAlertModule }, { kind: "component", type: i2$2.AXAlertComponent, selector: "ax-alert", inputs: ["color", "timeOut"], outputs: ["colorChange", "onClosed", "timeOutChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXCodeEditorModule }, { kind: "component", type: i5.AXCodeEditorComponent, selector: "ax-code-editor", inputs: ["disabled", "value", "state", "name", "id", "language", "readonly", "placeholder", "lineNumbers", "lineWrapping", "tabSize", "indentWithTab", "theme", "extensions", "ariaLabel", "focusOnReady", "formatOnSave", "minRow", "customCompletions"], outputs: ["onValueChanged", "valueChange", "stateChange", "readonlyChange", "disabledChange", "ready", "save"] }, { kind: "component", type: AXPMarkdownViewerComponent, selector: "axp-markdown-viewer", inputs: ["markdown"] }, { kind: "directive", type: AXPMarkdownTemplateDirective, selector: "ng-template[axpMarkdownTemplate]", inputs: ["axpMarkdownTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6403
6478
  }
6404
6479
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssistMessageRendererComponent, decorators: [{
6405
6480
  type: Component,
@@ -6448,12 +6523,80 @@ const AXM_CONVERSATION_BOT_RENDERER = {
6448
6523
  icon: 'fa-light fa-sparkles',
6449
6524
  };
6450
6525
 
6526
+ //#region ----- Imports -----
6527
+ //#endregion
6528
+ //#region ----- Service -----
6529
+ /**
6530
+ * Tracks callIds with an open or accepted session so duplicate invite packets
6531
+ * do not reopen the incoming-call UI or restart the ringer.
6532
+ */
6533
+ class AXMChatCallActiveSessionService {
6534
+ constructor() {
6535
+ this.activeCallIds = new Set();
6536
+ this.participantIdsByCall = new Map();
6537
+ /** True while any call-session popup is open (blocks chat route selection takeover). */
6538
+ this.engaged = signal(false, /* @ts-ignore */
6539
+ ...(ngDevMode ? [{ debugName: "engaged" }] : /* istanbul ignore next */ []));
6540
+ }
6541
+ engage(callId) {
6542
+ const id = callId?.trim();
6543
+ if (id) {
6544
+ this.activeCallIds.add(id);
6545
+ this.#syncEngaged();
6546
+ }
6547
+ }
6548
+ release(callId) {
6549
+ const id = callId?.trim();
6550
+ if (id) {
6551
+ this.activeCallIds.delete(id);
6552
+ this.participantIdsByCall.delete(id);
6553
+ this.#syncEngaged();
6554
+ }
6555
+ }
6556
+ #syncEngaged() {
6557
+ this.engaged.set(this.activeCallIds.size > 0);
6558
+ }
6559
+ isEngaged(callId) {
6560
+ const id = callId?.trim();
6561
+ return Boolean(id && this.activeCallIds.has(id));
6562
+ }
6563
+ addParticipant(callId, userId) {
6564
+ const scopedCallId = callId?.trim();
6565
+ const scopedUserId = userId?.trim();
6566
+ if (!scopedCallId || !scopedUserId) {
6567
+ return;
6568
+ }
6569
+ const members = this.participantIdsByCall.get(scopedCallId) ?? new Set();
6570
+ members.add(scopedUserId);
6571
+ this.participantIdsByCall.set(scopedCallId, members);
6572
+ }
6573
+ addParticipants(callId, userIds) {
6574
+ for (const userId of userIds) {
6575
+ this.addParticipant(callId, userId);
6576
+ }
6577
+ }
6578
+ getParticipantIds(callId) {
6579
+ const scopedCallId = callId?.trim();
6580
+ if (!scopedCallId) {
6581
+ return [];
6582
+ }
6583
+ return [...(this.participantIdsByCall.get(scopedCallId) ?? [])];
6584
+ }
6585
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6586
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, providedIn: 'root' }); }
6587
+ }
6588
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, decorators: [{
6589
+ type: Injectable,
6590
+ args: [{ providedIn: 'root' }]
6591
+ }] });
6592
+
6451
6593
  //#region ----- Imports -----
6452
6594
  //#endregion
6453
6595
  //#region ----- Dialog -----
6454
6596
  /**
6455
6597
  * Opens the LiveKit-backed call session as an in-app popup.
6456
- * Must be called from an injection context when `popupService` is omitted.
6598
+ * Must be called from an injection context when `popupService` or
6599
+ * `activeCallSessions` are omitted.
6457
6600
  */
6458
6601
  async function axmOpenChatCallSessionDialog(options) {
6459
6602
  const conversation = options.conversation;
@@ -6461,24 +6604,33 @@ async function axmOpenChatCallSessionDialog(options) {
6461
6604
  return;
6462
6605
  }
6463
6606
  const popupService = options.popupService ?? inject(AXPopupService);
6464
- const comp = (await import('./acorex-platform-module-conversation-client-chat-call-session-page.component-C47tt1me.mjs')).AXMChatCallSessionPageComponent;
6607
+ const activeCallSessions = options.activeCallSessions ?? inject(AXMChatCallActiveSessionService);
6608
+ const comp = (await import('./acorex-platform-module-conversation-client-chat-call-session-page.component-nE7xP4bF.mjs')).AXMChatCallSessionPageComponent;
6609
+ const scopedCallId = options.callId?.trim() || createRandomUuid();
6610
+ activeCallSessions.engage(scopedCallId);
6465
6611
  const data = {
6466
6612
  sessionConversation: conversation,
6467
6613
  sessionMedia: options.media === 'video' ? 'video' : 'voice',
6468
6614
  sessionPhase: options.phase ?? 'outgoing-waiting',
6469
- sessionCallId: options.callId?.trim() || undefined,
6615
+ sessionCallId: scopedCallId,
6470
6616
  sessionInitiatorUserId: options.initiatorUserId?.trim() || undefined,
6471
6617
  };
6472
- await popupService.open(comp, {
6473
- header: false,
6474
- closeButton: false,
6475
- footer: false,
6476
- size: 'full',
6477
- closeOnBackdropClick: false,
6478
- panelClass: ['animate-fadeIn', 'animate-fast'],
6479
- contextElement: axmChatCallDarkThemeContextElement(),
6480
- data,
6481
- });
6618
+ try {
6619
+ await popupService.open(comp, {
6620
+ header: false,
6621
+ closeButton: false,
6622
+ footer: false,
6623
+ size: 'full',
6624
+ closeOnBackdropClick: false,
6625
+ panelClass: ['animate-fadeIn', 'animate-fast'],
6626
+ contextElement: axmChatCallDarkThemeContextElement(),
6627
+ data,
6628
+ });
6629
+ }
6630
+ catch (error) {
6631
+ activeCallSessions.release(scopedCallId);
6632
+ throw error;
6633
+ }
6482
6634
  }
6483
6635
  //#endregion
6484
6636
 
@@ -6497,6 +6649,7 @@ class AXMChatCallLogMessageRendererComponent {
6497
6649
  this.settings = inject(AXPSettingsService);
6498
6650
  this.conversationService = inject(AXConversationService);
6499
6651
  this.popupService = inject(AXPopupService);
6652
+ this.activeCallSessions = inject(AXMChatCallActiveSessionService);
6500
6653
  this.toastService = inject(AXToastService);
6501
6654
  this.rtcApi = inject(AXPRtcApiAbstract, { optional: true });
6502
6655
  this.destroyRef = inject(DestroyRef);
@@ -6543,6 +6696,14 @@ class AXMChatCallLogMessageRendererComponent {
6543
6696
  (info.joinedUserNames?.length || info.absentUserNames?.length));
6544
6697
  }, /* @ts-ignore */
6545
6698
  ...(ngDevMode ? [{ debugName: "showGroupAttendance" }] : /* istanbul ignore next */ []));
6699
+ this.groupAttendanceKey = computed(() => {
6700
+ const info = this.log();
6701
+ if (!info) {
6702
+ return '@conversation:chat.call.log.group-attendance-joined-only';
6703
+ }
6704
+ return axmChatCallLogGroupAttendanceKey(info);
6705
+ }, /* @ts-ignore */
6706
+ ...(ngDevMode ? [{ debugName: "groupAttendanceKey" }] : /* istanbul ignore next */ []));
6546
6707
  /**
6547
6708
  * Call direction relative to the viewer (drives arrow ↙ / ↗).
6548
6709
  * Based on who initiated the call — not who last acted (decline/cancel).
@@ -6627,6 +6788,7 @@ class AXMChatCallLogMessageRendererComponent {
6627
6788
  conversation,
6628
6789
  media: this.log()?.media === 'video' ? 'video' : 'voice',
6629
6790
  popupService: this.popupService,
6791
+ activeCallSessions: this.activeCallSessions,
6630
6792
  });
6631
6793
  }
6632
6794
  finally {
@@ -6661,13 +6823,13 @@ class AXMChatCallLogMessageRendererComponent {
6661
6823
  this.translateParams.set(params);
6662
6824
  }
6663
6825
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallLogMessageRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6664
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatCallLogMessageRendererComponent, isStandalone: true, selector: "axm-chat-call-log-message-renderer", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "contextmenu": "onContextMenu($event)" } }, ngImport: i0, template: "@if (log(); as info) {\n <div\n class=\"axm-chat-call-log\"\n [attr.dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\"\n [class.axm-chat-call-log--video]=\"isVideo()\"\n [class.axm-chat-call-log--success]=\"iconTone() === 'success'\"\n [class.axm-chat-call-log--danger]=\"iconTone() === 'danger'\"\n [class.axm-chat-call-log--own]=\"isOwnBubble()\"\n [class.axm-chat-call-log--outgoing]=\"callDirection() === 'outgoing'\"\n [class.axm-chat-call-log--incoming]=\"callDirection() === 'incoming'\"\n >\n <!-- ----- Call-back action (Telegram phone button) ----- -->\n <button\n type=\"button\"\n class=\"axm-chat-call-log__callback\"\n [disabled]=\"callbackBusy()\"\n [attr.aria-label]=\"'@conversation:chat.call.log.callback' | translate | async\"\n (click)=\"onCallbackClick($event)\"\n >\n <i [class]=\"'fa-solid ' + callbackIconClass()\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"axm-chat-call-log__body\">\n <!-- ----- Telegram-style status headline ----- -->\n <span class=\"axm-chat-call-log__title\">{{\n headlineKey() | translate: { params: translateParams() } | async\n }}</span>\n\n <div class=\"axm-chat-call-log__meta\">\n <!-- ----- Status marker + call/ring duration (bubble already shows message time) ----- -->\n <span class=\"axm-chat-call-log__status\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + statusIconClass()\"></i>\n </span>\n @if (translateParams()['duration']; as duration) {\n <span class=\"axm-chat-call-log__meta-text\">{{ duration }}</span>\n }\n </div>\n\n @if (showGroupAttendance()) {\n <!-- ----- Group attendance summary when the call completed ----- -->\n <span class=\"axm-chat-call-log__detail\">{{\n '@conversation:chat.call.log.group-attendance'\n | translate: { params: translateParams() }\n | async\n }}</span>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;width:100%;min-width:12.5rem;max-width:100%;color:inherit}.axm-chat-call-log{--axm-call-log-status: rgb(var(--ax-sys-color-success-500));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-primary-500));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-on-primary-surface));box-sizing:border-box;width:100%;min-width:12.5rem;color:inherit;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.875rem}.axm-chat-call-log[dir=ltr]{flex-direction:row-reverse;justify-content:space-between}.axm-chat-call-log__body{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;min-width:0;text-align:start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__body{flex:1 1 auto;align-items:flex-start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__body{align-items:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log--danger{--axm-call-log-status: rgb(var(--ax-sys-color-danger-500))}.axm-chat-call-log--success{--axm-call-log-status: rgb(var(--ax-sys-color-success-500))}.axm-chat-call-log--own{--axm-call-log-status: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-primary-surface))}.axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}.axm-chat-call-log__title{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__meta{display:inline-flex;align-items:center;gap:.35rem;min-width:0;color:inherit;opacity:.7;font-size:.75rem;line-height:1.35}.axm-chat-call-log__status{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--axm-call-log-status);font-size:.7rem;line-height:1}.axm-chat-call-log__arrow{display:inline-block;transform-origin:center}.axm-chat-call-log__arrow--in{transform:rotate(-45deg)}.axm-chat-call-log__arrow--out{transform:rotate(45deg)}.axm-chat-call-log__meta-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__detail{font-size:.75rem;color:inherit;opacity:.85;line-height:1.35}.axm-chat-call-log__callback{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:none;border-radius:9999px;background:var(--axm-call-log-callback-ring);color:var(--axm-call-log-callback-surface);font-size:1.1rem;line-height:1;cursor:pointer}.axm-chat-call-log__callback:hover:not(:disabled){filter:brightness(.94)}.axm-chat-call-log__callback:active:not(:disabled){filter:brightness(.88)}.axm-chat-call-log__callback:disabled{opacity:.55;cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6826
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatCallLogMessageRendererComponent, isStandalone: true, selector: "axm-chat-call-log-message-renderer", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "contextmenu": "onContextMenu($event)" } }, ngImport: i0, template: "@if (log(); as info) {\n <div\n class=\"axm-chat-call-log\"\n [attr.dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\"\n [class.axm-chat-call-log--video]=\"isVideo()\"\n [class.axm-chat-call-log--success]=\"iconTone() === 'success'\"\n [class.axm-chat-call-log--danger]=\"iconTone() === 'danger'\"\n [class.axm-chat-call-log--own]=\"isOwnBubble()\"\n [class.axm-chat-call-log--outgoing]=\"callDirection() === 'outgoing'\"\n [class.axm-chat-call-log--incoming]=\"callDirection() === 'incoming'\"\n >\n <!-- ----- Call-back action (Telegram phone button) ----- -->\n <button\n type=\"button\"\n class=\"axm-chat-call-log__callback\"\n [disabled]=\"callbackBusy()\"\n [attr.aria-label]=\"'@conversation:chat.call.log.callback' | translate | async\"\n (click)=\"onCallbackClick($event)\"\n >\n <i [class]=\"'fa-solid ' + callbackIconClass()\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"axm-chat-call-log__body\">\n <!-- ----- Telegram-style status headline ----- -->\n <span class=\"axm-chat-call-log__title\">{{\n headlineKey() | translate: { params: translateParams() } | async\n }}</span>\n\n <div class=\"axm-chat-call-log__meta\">\n <!-- ----- Status marker + call/ring duration (bubble already shows message time) ----- -->\n <span class=\"axm-chat-call-log__status\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + statusIconClass()\"></i>\n </span>\n @if (translateParams()['duration']; as duration) {\n <span class=\"axm-chat-call-log__meta-text\">{{ duration }}</span>\n }\n </div>\n\n @if (showGroupAttendance()) {\n <!-- ----- Group attendance summary when the call completed ----- -->\n <span class=\"axm-chat-call-log__detail\">{{\n groupAttendanceKey() | translate: { params: translateParams() } | async\n }}</span>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;width:100%;min-width:12.5rem;max-width:100%;color:inherit}.axm-chat-call-log{--axm-call-log-status: rgb(var(--ax-sys-color-success-500));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-primary-500));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-on-primary-surface));box-sizing:border-box;width:100%;min-width:12.5rem;color:inherit;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.875rem}.axm-chat-call-log[dir=ltr]{flex-direction:row-reverse;justify-content:space-between}.axm-chat-call-log__body{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;min-width:0;text-align:start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__body{flex:1 1 auto;align-items:flex-start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__body{align-items:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log--danger{--axm-call-log-status: rgb(var(--ax-sys-color-danger-500))}.axm-chat-call-log--success{--axm-call-log-status: rgb(var(--ax-sys-color-success-500))}.axm-chat-call-log--own{--axm-call-log-status: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-primary-surface))}.axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}.axm-chat-call-log__title{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__meta{display:inline-flex;align-items:center;gap:.35rem;min-width:0;color:inherit;opacity:.7;font-size:.75rem;line-height:1.35}.axm-chat-call-log__status{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--axm-call-log-status);font-size:.7rem;line-height:1}.axm-chat-call-log__arrow{display:inline-block;transform-origin:center}.axm-chat-call-log__arrow--in{transform:rotate(-45deg)}.axm-chat-call-log__arrow--out{transform:rotate(45deg)}.axm-chat-call-log__meta-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__detail{font-size:.75rem;color:inherit;opacity:.85;line-height:1.35}.axm-chat-call-log__callback{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:none;border-radius:9999px;background:var(--axm-call-log-callback-ring);color:var(--axm-call-log-callback-surface);font-size:1.1rem;line-height:1;cursor:pointer}.axm-chat-call-log__callback:hover:not(:disabled){filter:brightness(.94)}.axm-chat-call-log__callback:active:not(:disabled){filter:brightness(.88)}.axm-chat-call-log__callback:disabled{opacity:.55;cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6665
6827
  }
6666
6828
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallLogMessageRendererComponent, decorators: [{
6667
6829
  type: Component,
6668
6830
  args: [{ selector: 'axm-chat-call-log-message-renderer', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AXTranslationModule, AsyncPipe], host: {
6669
6831
  '(contextmenu)': 'onContextMenu($event)',
6670
- }, template: "@if (log(); as info) {\n <div\n class=\"axm-chat-call-log\"\n [attr.dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\"\n [class.axm-chat-call-log--video]=\"isVideo()\"\n [class.axm-chat-call-log--success]=\"iconTone() === 'success'\"\n [class.axm-chat-call-log--danger]=\"iconTone() === 'danger'\"\n [class.axm-chat-call-log--own]=\"isOwnBubble()\"\n [class.axm-chat-call-log--outgoing]=\"callDirection() === 'outgoing'\"\n [class.axm-chat-call-log--incoming]=\"callDirection() === 'incoming'\"\n >\n <!-- ----- Call-back action (Telegram phone button) ----- -->\n <button\n type=\"button\"\n class=\"axm-chat-call-log__callback\"\n [disabled]=\"callbackBusy()\"\n [attr.aria-label]=\"'@conversation:chat.call.log.callback' | translate | async\"\n (click)=\"onCallbackClick($event)\"\n >\n <i [class]=\"'fa-solid ' + callbackIconClass()\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"axm-chat-call-log__body\">\n <!-- ----- Telegram-style status headline ----- -->\n <span class=\"axm-chat-call-log__title\">{{\n headlineKey() | translate: { params: translateParams() } | async\n }}</span>\n\n <div class=\"axm-chat-call-log__meta\">\n <!-- ----- Status marker + call/ring duration (bubble already shows message time) ----- -->\n <span class=\"axm-chat-call-log__status\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + statusIconClass()\"></i>\n </span>\n @if (translateParams()['duration']; as duration) {\n <span class=\"axm-chat-call-log__meta-text\">{{ duration }}</span>\n }\n </div>\n\n @if (showGroupAttendance()) {\n <!-- ----- Group attendance summary when the call completed ----- -->\n <span class=\"axm-chat-call-log__detail\">{{\n '@conversation:chat.call.log.group-attendance'\n | translate: { params: translateParams() }\n | async\n }}</span>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;width:100%;min-width:12.5rem;max-width:100%;color:inherit}.axm-chat-call-log{--axm-call-log-status: rgb(var(--ax-sys-color-success-500));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-primary-500));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-on-primary-surface));box-sizing:border-box;width:100%;min-width:12.5rem;color:inherit;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.875rem}.axm-chat-call-log[dir=ltr]{flex-direction:row-reverse;justify-content:space-between}.axm-chat-call-log__body{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;min-width:0;text-align:start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__body{flex:1 1 auto;align-items:flex-start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__body{align-items:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log--danger{--axm-call-log-status: rgb(var(--ax-sys-color-danger-500))}.axm-chat-call-log--success{--axm-call-log-status: rgb(var(--ax-sys-color-success-500))}.axm-chat-call-log--own{--axm-call-log-status: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-primary-surface))}.axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}.axm-chat-call-log__title{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__meta{display:inline-flex;align-items:center;gap:.35rem;min-width:0;color:inherit;opacity:.7;font-size:.75rem;line-height:1.35}.axm-chat-call-log__status{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--axm-call-log-status);font-size:.7rem;line-height:1}.axm-chat-call-log__arrow{display:inline-block;transform-origin:center}.axm-chat-call-log__arrow--in{transform:rotate(-45deg)}.axm-chat-call-log__arrow--out{transform:rotate(45deg)}.axm-chat-call-log__meta-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__detail{font-size:.75rem;color:inherit;opacity:.85;line-height:1.35}.axm-chat-call-log__callback{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:none;border-radius:9999px;background:var(--axm-call-log-callback-ring);color:var(--axm-call-log-callback-surface);font-size:1.1rem;line-height:1;cursor:pointer}.axm-chat-call-log__callback:hover:not(:disabled){filter:brightness(.94)}.axm-chat-call-log__callback:active:not(:disabled){filter:brightness(.88)}.axm-chat-call-log__callback:disabled{opacity:.55;cursor:default}\n"] }]
6832
+ }, template: "@if (log(); as info) {\n <div\n class=\"axm-chat-call-log\"\n [attr.dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\"\n [class.axm-chat-call-log--video]=\"isVideo()\"\n [class.axm-chat-call-log--success]=\"iconTone() === 'success'\"\n [class.axm-chat-call-log--danger]=\"iconTone() === 'danger'\"\n [class.axm-chat-call-log--own]=\"isOwnBubble()\"\n [class.axm-chat-call-log--outgoing]=\"callDirection() === 'outgoing'\"\n [class.axm-chat-call-log--incoming]=\"callDirection() === 'incoming'\"\n >\n <!-- ----- Call-back action (Telegram phone button) ----- -->\n <button\n type=\"button\"\n class=\"axm-chat-call-log__callback\"\n [disabled]=\"callbackBusy()\"\n [attr.aria-label]=\"'@conversation:chat.call.log.callback' | translate | async\"\n (click)=\"onCallbackClick($event)\"\n >\n <i [class]=\"'fa-solid ' + callbackIconClass()\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"axm-chat-call-log__body\">\n <!-- ----- Telegram-style status headline ----- -->\n <span class=\"axm-chat-call-log__title\">{{\n headlineKey() | translate: { params: translateParams() } | async\n }}</span>\n\n <div class=\"axm-chat-call-log__meta\">\n <!-- ----- Status marker + call/ring duration (bubble already shows message time) ----- -->\n <span class=\"axm-chat-call-log__status\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + statusIconClass()\"></i>\n </span>\n @if (translateParams()['duration']; as duration) {\n <span class=\"axm-chat-call-log__meta-text\">{{ duration }}</span>\n }\n </div>\n\n @if (showGroupAttendance()) {\n <!-- ----- Group attendance summary when the call completed ----- -->\n <span class=\"axm-chat-call-log__detail\">{{\n groupAttendanceKey() | translate: { params: translateParams() } | async\n }}</span>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;width:100%;min-width:12.5rem;max-width:100%;color:inherit}.axm-chat-call-log{--axm-call-log-status: rgb(var(--ax-sys-color-success-500));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-primary-500));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-on-primary-surface));box-sizing:border-box;width:100%;min-width:12.5rem;color:inherit;display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:.875rem}.axm-chat-call-log[dir=ltr]{flex-direction:row-reverse;justify-content:space-between}.axm-chat-call-log__body{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;min-width:0;text-align:start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__body{flex:1 1 auto;align-items:flex-start}.axm-chat-call-log[dir=ltr] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__body{align-items:flex-start}.axm-chat-call-log[dir=rtl] .axm-chat-call-log__meta{align-self:stretch;justify-content:flex-start}.axm-chat-call-log--danger{--axm-call-log-status: rgb(var(--ax-sys-color-danger-500))}.axm-chat-call-log--success{--axm-call-log-status: rgb(var(--ax-sys-color-success-500))}.axm-chat-call-log--own{--axm-call-log-status: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-primary-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-primary-surface))}.axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}.axm-chat-call-log__title{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__meta{display:inline-flex;align-items:center;gap:.35rem;min-width:0;color:inherit;opacity:.7;font-size:.75rem;line-height:1.35}.axm-chat-call-log__status{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--axm-call-log-status);font-size:.7rem;line-height:1}.axm-chat-call-log__arrow{display:inline-block;transform-origin:center}.axm-chat-call-log__arrow--in{transform:rotate(-45deg)}.axm-chat-call-log__arrow--out{transform:rotate(45deg)}.axm-chat-call-log__meta-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-call-log__detail{font-size:.75rem;color:inherit;opacity:.85;line-height:1.35}.axm-chat-call-log__callback{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:none;border-radius:9999px;background:var(--axm-call-log-callback-ring);color:var(--axm-call-log-callback-surface);font-size:1.1rem;line-height:1;cursor:pointer}.axm-chat-call-log__callback:hover:not(:disabled){filter:brightness(.94)}.axm-chat-call-log__callback:active:not(:disabled){filter:brightness(.88)}.axm-chat-call-log__callback:disabled{opacity:.55;cursor:default}\n"] }]
6671
6833
  }], ctorParameters: () => [], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }] } });
6672
6834
 
6673
6835
  const AXM_CONVERSATION_CALL_LOG_RENDERER = {
@@ -6797,6 +6959,94 @@ function axmIsConversationParticipant(participants, userId) {
6797
6959
  }
6798
6960
  //#endregion
6799
6961
 
6962
+ //#region ----- Types -----
6963
+ //#endregion
6964
+ //#region ----- Private-to-group upgrade -----
6965
+ /** True when a private chat must fork into a new group instead of mutating the 1:1 room. */
6966
+ function axmShouldForkPrivateToGroup(roomType, existingParticipantCount, newUserIds) {
6967
+ if (roomType !== 'private') {
6968
+ return false;
6969
+ }
6970
+ const uniqueNewCount = new Set(newUserIds.map((id) => id.trim()).filter(Boolean)).size;
6971
+ return existingParticipantCount + uniqueNewCount > 2;
6972
+ }
6973
+ /** Participant ids for the forked group (inviter is added by createConversation). */
6974
+ function axmBuildForkedGroupParticipantIds(existingParticipantIds, newUserIds, inviterUserId) {
6975
+ const scopedInviter = inviterUserId.trim();
6976
+ const ids = new Set();
6977
+ for (const id of existingParticipantIds) {
6978
+ const scoped = id.trim();
6979
+ if (scoped && scoped !== scopedInviter) {
6980
+ ids.add(scoped);
6981
+ }
6982
+ }
6983
+ for (const id of newUserIds) {
6984
+ const scoped = id.trim();
6985
+ if (scoped && scoped !== scopedInviter) {
6986
+ ids.add(scoped);
6987
+ }
6988
+ }
6989
+ return [...ids];
6990
+ }
6991
+ /** Default group title when promoting a private chat (Telegram-style name list). */
6992
+ function axmBuildUpgradedGroupTitle(options) {
6993
+ const inviterId = options.inviterUserId.trim();
6994
+ const names = [];
6995
+ const seen = new Set();
6996
+ const pushName = (name) => {
6997
+ const trimmed = name?.trim();
6998
+ if (!trimmed) {
6999
+ return;
7000
+ }
7001
+ const key = trimmed.toLowerCase();
7002
+ if (seen.has(key)) {
7003
+ return;
7004
+ }
7005
+ seen.add(key);
7006
+ names.push(trimmed);
7007
+ };
7008
+ for (const participant of options.existingParticipants) {
7009
+ if (participant.id?.trim() === inviterId) {
7010
+ continue;
7011
+ }
7012
+ pushName(participant.name);
7013
+ }
7014
+ for (const user of options.newUsers) {
7015
+ if (user.id?.trim() === inviterId) {
7016
+ continue;
7017
+ }
7018
+ pushName(user.name);
7019
+ }
7020
+ return names.slice(0, 4).join(', ') || 'New Group';
7021
+ }
7022
+ function axmReadForkedFromConversationId(metadata) {
7023
+ if (!metadata || typeof metadata !== 'object') {
7024
+ return null;
7025
+ }
7026
+ const value = metadata['forkedFromConversationId'];
7027
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
7028
+ }
7029
+ function axmReadForkedForCallId(metadata) {
7030
+ if (!metadata || typeof metadata !== 'object') {
7031
+ return null;
7032
+ }
7033
+ const value = metadata['forkedForCallId'];
7034
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
7035
+ }
7036
+ function axmMatchesForkedGroupForCall(metadata, sourceConversationId, callId) {
7037
+ const forkedFrom = axmReadForkedFromConversationId(metadata);
7038
+ if (!forkedFrom || forkedFrom !== sourceConversationId.trim()) {
7039
+ return false;
7040
+ }
7041
+ const scopedCallId = callId?.trim();
7042
+ if (!scopedCallId) {
7043
+ return true;
7044
+ }
7045
+ const forkCallId = axmReadForkedForCallId(metadata);
7046
+ return !forkCallId || forkCallId === scopedCallId;
7047
+ }
7048
+ //#endregion
7049
+
6800
7050
  //#region ---- Imports ----
6801
7051
  const AXM_CONVERSATION_ASSIST_RESPONSE_PORT = new InjectionToken('AXM_CONVERSATION_ASSIST_RESPONSE_PORT');
6802
7052
  //#endregion
@@ -6844,6 +7094,23 @@ function buildConversationChatInAppCorrelationId(conversationId, messageId, send
6844
7094
  }
6845
7095
  return `conversation:${scopedConversationId}:${scopedMessageId}`;
6846
7096
  }
7097
+ function parseConversationChatInAppCorrelationId(correlationId) {
7098
+ const scoped = correlationId?.trim();
7099
+ if (!scoped?.startsWith('conversation:')) {
7100
+ return undefined;
7101
+ }
7102
+ const segments = scoped.split(':');
7103
+ if (segments.length < 3) {
7104
+ return undefined;
7105
+ }
7106
+ const conversationId = segments[1]?.trim();
7107
+ const messageId = segments[2]?.trim();
7108
+ if (!conversationId || !messageId) {
7109
+ return undefined;
7110
+ }
7111
+ const senderUserId = segments[3]?.trim() || undefined;
7112
+ return { conversationId, messageId, senderUserId };
7113
+ }
6847
7114
  /** Stable local-only inbox id until the server delivery id is known. */
6848
7115
  function buildConversationChatLocalInboxId(conversationId) {
6849
7116
  return `local:conversation-in-app:${conversationId.trim()}`;
@@ -6916,12 +7183,47 @@ class AXMConversationInAppNotificationSyncService {
6916
7183
  this.inboxConnector = inject(AXPInAppInboxConnectorService, { optional: true });
6917
7184
  this.lastSyncAt = new Map();
6918
7185
  this.syncChains = new Map();
7186
+ this.knownReadDeliveryIds = new Set();
7187
+ }
7188
+ /**
7189
+ * Marks the in-app inbox row for this conversation as read (best-effort).
7190
+ * Pass `force` when the user just opened the thread so a recent no-op cannot skip the write.
7191
+ */
7192
+ async markConversationInAppNotificationRead(conversationId, recipientUserId, options) {
7193
+ await this.runConversationInboxMutation(conversationId, recipientUserId, options, async () => {
7194
+ await this.inboxConnector.markReadByCorrelationIdPrefix(buildConversationChatInAppCorrelationPrefix(conversationId));
7195
+ this.rememberReadDeliveries(conversationId);
7196
+ });
6919
7197
  }
6920
7198
  /**
6921
- * Removes the in-app inbox row for this conversation (best-effort).
6922
- * Pass `force` when the user just opened the thread so a recent no-op cannot skip delete.
7199
+ * Removes the in-app inbox row for this conversation (muted rooms).
6923
7200
  */
6924
7201
  async dismissConversationInAppNotification(conversationId, recipientUserId, options) {
7202
+ await this.runConversationInboxMutation(conversationId, recipientUserId, options, async () => {
7203
+ await this.inboxConnector.dismissByCorrelationIdPrefix(buildConversationChatInAppCorrelationPrefix(conversationId));
7204
+ });
7205
+ }
7206
+ rememberReadDeliveries(conversationId) {
7207
+ const prefix = buildConversationChatInAppCorrelationPrefix(conversationId);
7208
+ for (const item of this.inboxConnector?.inboxList() ?? []) {
7209
+ if (item.correlationId?.trim().startsWith(prefix) || item.id === `local:conversation-in-app:${conversationId}`) {
7210
+ this.knownReadDeliveryIds.add(item.id);
7211
+ }
7212
+ }
7213
+ }
7214
+ hasRememberedReadDelivery(deliveryId) {
7215
+ return this.knownReadDeliveryIds.has(deliveryId);
7216
+ }
7217
+ rememberReadDeliveryId(deliveryId) {
7218
+ const scoped = deliveryId.trim();
7219
+ if (scoped) {
7220
+ this.knownReadDeliveryIds.add(scoped);
7221
+ }
7222
+ }
7223
+ clearRememberedReadDeliveries() {
7224
+ this.knownReadDeliveryIds.clear();
7225
+ }
7226
+ async runConversationInboxMutation(conversationId, recipientUserId, options, mutate) {
6925
7227
  if (!this.inboxConnector || !conversationId.trim() || !recipientUserId.trim()) {
6926
7228
  return;
6927
7229
  }
@@ -6932,7 +7234,7 @@ class AXMConversationInAppNotificationSyncService {
6932
7234
  return;
6933
7235
  }
6934
7236
  const previous = this.syncChains.get(key) ?? Promise.resolve();
6935
- const next = previous.then(() => this.dismissConversationInAppNotificationInternal(conversationId));
7237
+ const next = previous.then(() => this.runMutationInternal(mutate));
6936
7238
  this.syncChains.set(key, next.finally(() => {
6937
7239
  if (this.syncChains.get(key) === next) {
6938
7240
  this.syncChains.delete(key);
@@ -6941,9 +7243,9 @@ class AXMConversationInAppNotificationSyncService {
6941
7243
  await next;
6942
7244
  this.lastSyncAt.set(key, Date.now());
6943
7245
  }
6944
- async dismissConversationInAppNotificationInternal(conversationId) {
7246
+ async runMutationInternal(mutate) {
6945
7247
  try {
6946
- await this.inboxConnector.dismissByCorrelationIdPrefix(buildConversationChatInAppCorrelationPrefix(conversationId));
7248
+ await mutate();
6947
7249
  }
6948
7250
  catch {
6949
7251
  // Best-effort — opening the chat should still proceed.
@@ -7056,7 +7358,7 @@ class AXMChatEntityConversationFocusHandler {
7056
7358
  if (!userId) {
7057
7359
  return;
7058
7360
  }
7059
- void this.inAppSync.dismissConversationInAppNotification(conversationId, userId, { force: true });
7361
+ void this.inAppSync.markConversationInAppNotificationRead(conversationId, userId, { force: true });
7060
7362
  }
7061
7363
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatEntityConversationFocusHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7062
7364
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatEntityConversationFocusHandler }); }
@@ -7300,10 +7602,18 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7300
7602
  probeLastMessage: false,
7301
7603
  currentUserId,
7302
7604
  })));
7303
- for (const conversation of enriched) {
7304
- this.conversationStore.cacheConversation(conversation);
7305
- }
7306
- const sorted = axmSortConversationsByPinAndRecency(enriched);
7605
+ const withLocalUnread = enriched.map((conversation) => {
7606
+ const existing = this.conversationStore.getCachedConversation(conversation.id);
7607
+ const next = existing
7608
+ ? {
7609
+ ...conversation,
7610
+ unreadCount: axmPreferLocalUnreadCount(existing.unreadCount, conversation.unreadCount),
7611
+ }
7612
+ : conversation;
7613
+ this.conversationStore.cacheConversation(next);
7614
+ return next;
7615
+ });
7616
+ const sorted = axmSortConversationsByPinAndRecency(withLocalUnread);
7307
7617
  return this.roomQuery.paginate(sorted, pagination);
7308
7618
  }
7309
7619
  async updateConversation(conversationId, updates) {
@@ -7330,7 +7640,9 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7330
7640
  return conversation;
7331
7641
  }
7332
7642
  async deleteConversation(conversationId) {
7643
+ this.realtimeBus.markLocalRoomMutation(conversationId);
7333
7644
  await this.roomData.delete(conversationId);
7645
+ this.conversationStore.publishConversationDeleted(conversationId);
7334
7646
  return true;
7335
7647
  }
7336
7648
  //#endregion
@@ -7437,7 +7749,6 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7437
7749
  return room?.participants ?? [];
7438
7750
  }
7439
7751
  async addParticipants(conversationId, userIds) {
7440
- const currentUser = await this.userApi.getCurrentUser();
7441
7752
  const room = await this.roomData.byKey(conversationId);
7442
7753
  if (!room) {
7443
7754
  throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
@@ -7445,11 +7756,83 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7445
7756
  const newParticipants = await this.userApi.getUsersByIds(userIds);
7446
7757
  const existingIds = new Set(room.participants.map((p) => p.id));
7447
7758
  const merged = [...room.participants, ...newParticipants.filter((p) => !existingIds.has(p.id))];
7448
- await this.roomData.update(conversationId, {
7449
- participants: merged,
7450
- updatedAt: new Date(),
7759
+ return this.persistParticipants(conversationId, merged);
7760
+ }
7761
+ /**
7762
+ * Creates a new group from a private chat when a third participant accepts a call invite.
7763
+ * The private room is left unchanged; the inviter becomes group owner.
7764
+ */
7765
+ async forkPrivateToGroupForCall(sourceConversationId, acceptedUserIds, options) {
7766
+ const currentUser = await this.userApi.getCurrentUser();
7767
+ const room = await this.roomData.byKey(sourceConversationId);
7768
+ if (!room) {
7769
+ throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
7770
+ }
7771
+ if (room.type !== 'private') {
7772
+ throw this.createError('INVALID_CONVERSATION_TYPE', 'Only private chats can be upgraded to a group', 400);
7773
+ }
7774
+ const uniqueAcceptedUserIds = [...new Set(acceptedUserIds.map((id) => id.trim()).filter(Boolean))];
7775
+ return this.#forkPrivateConversationToGroup(room, uniqueAcceptedUserIds, currentUser, options?.callId);
7776
+ }
7777
+ async findForkedGroupFromPrivateChat(sourceConversationId, callId) {
7778
+ const scopedSourceId = sourceConversationId.trim();
7779
+ if (!scopedSourceId) {
7780
+ return null;
7781
+ }
7782
+ const currentUser = await this.userApi.getCurrentUser().catch(() => null);
7783
+ const currentUserId = currentUser?.id?.trim();
7784
+ const rooms = await this.roomQuery.loadChatRooms();
7785
+ const match = rooms.find((room) => room.type === 'group' &&
7786
+ axmMatchesForkedGroupForCall(room.metadata, scopedSourceId, callId) &&
7787
+ (!currentUserId || axmIsConversationParticipant(room.participants, currentUserId)));
7788
+ if (!match) {
7789
+ return null;
7790
+ }
7791
+ return this.roomQuery.enrichRoom(match, {
7792
+ probeLastMessage: false,
7793
+ currentUserId,
7451
7794
  });
7452
- const updatedRoom = await this.roomData.byKey(conversationId);
7795
+ }
7796
+ /**
7797
+ * Promotes a 1:1 chat into a new group when a third participant joins.
7798
+ * The private room is left unchanged; the inviter becomes group owner.
7799
+ */
7800
+ async #forkPrivateConversationToGroup(room, newUserIds, currentUser, callId) {
7801
+ const participantIds = axmBuildForkedGroupParticipantIds(room.participants.map((participant) => participant.id), newUserIds, currentUser.id);
7802
+ const newUsers = await this.userApi.getUsersByIds(newUserIds);
7803
+ const title = axmBuildUpgradedGroupTitle({
7804
+ existingParticipants: room.participants,
7805
+ newUsers,
7806
+ inviterUserId: currentUser.id,
7807
+ });
7808
+ const created = await this.createConversation({
7809
+ type: 'group',
7810
+ participantIds,
7811
+ title,
7812
+ metadata: {
7813
+ forkedFromConversationId: room.id,
7814
+ forkedByUserId: currentUser.id,
7815
+ ...(callId?.trim() ? { forkedForCallId: callId.trim() } : {}),
7816
+ },
7817
+ });
7818
+ const participants = created.participants.map((participant) => ({
7819
+ ...participant,
7820
+ role: participant.id === currentUser.id ? 'owner' : participant.role === 'admin' ? 'member' : participant.role ?? 'member',
7821
+ }));
7822
+ const now = new Date();
7823
+ this.realtimeBus.markLocalRoomMutation(created.id);
7824
+ await this.roomData.update(created.id, {
7825
+ participants,
7826
+ creatorId: currentUser.id,
7827
+ type: 'group',
7828
+ metadata: {
7829
+ forkedFromConversationId: room.id,
7830
+ forkedByUserId: currentUser.id,
7831
+ ...(callId?.trim() ? { forkedForCallId: callId.trim() } : {}),
7832
+ },
7833
+ updatedAt: now,
7834
+ });
7835
+ const updatedRoom = await this.roomData.byKey(created.id);
7453
7836
  if (!updatedRoom) {
7454
7837
  throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
7455
7838
  }
@@ -7458,6 +7841,7 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7458
7841
  currentUserId: currentUser.id,
7459
7842
  });
7460
7843
  this.conversationStore.publishConversationUpdate(conversation);
7844
+ this.conversationStore.publishConversationCreated(conversation);
7461
7845
  return conversation;
7462
7846
  }
7463
7847
  async removeParticipant(conversationId, userId) {
@@ -7466,11 +7850,7 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7466
7850
  throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
7467
7851
  }
7468
7852
  const participants = room.participants.filter((p) => p.id !== userId);
7469
- await this.roomData.update(conversationId, {
7470
- participants,
7471
- updatedAt: new Date(),
7472
- });
7473
- return this.getConversation(conversationId);
7853
+ return this.persistParticipants(conversationId, participants);
7474
7854
  }
7475
7855
  async leaveConversation(conversationId) {
7476
7856
  const currentUser = await this.userApi.getCurrentUser();
@@ -7482,11 +7862,29 @@ class AXMChatEntityConversationApi extends AXMChatConversationApi {
7482
7862
  throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
7483
7863
  }
7484
7864
  const participants = room.participants.map((p) => (p.id === update.userId ? { ...p, role: this.toParticipantRole(update.role) ?? p.role } : p));
7865
+ return this.persistParticipants(conversationId, participants);
7866
+ }
7867
+ async persistParticipants(conversationId, participants) {
7868
+ const currentUser = await this.userApi.getCurrentUser();
7869
+ this.realtimeBus.markLocalRoomMutation(conversationId);
7485
7870
  await this.roomData.update(conversationId, {
7486
7871
  participants,
7487
7872
  updatedAt: new Date(),
7488
7873
  });
7489
- return this.getConversation(conversationId);
7874
+ const updatedRoom = await this.roomData.byKey(conversationId);
7875
+ if (!updatedRoom) {
7876
+ throw this.createError('CONVERSATION_NOT_FOUND', 'Conversation not found', 404);
7877
+ }
7878
+ const conversation = await this.roomQuery.enrichRoom(updatedRoom, {
7879
+ probeLastMessage: false,
7880
+ currentUserId: currentUser.id,
7881
+ });
7882
+ if (!axmIsConversationParticipant(conversation.participants, currentUser.id)) {
7883
+ this.conversationStore.publishConversationDeleted(conversationId);
7884
+ return conversation;
7885
+ }
7886
+ this.conversationStore.publishConversationUpdate(conversation);
7887
+ return conversation;
7490
7888
  }
7491
7889
  //#endregion
7492
7890
  //#region ---- Stubs ----
@@ -7696,7 +8094,9 @@ class AXMChatEntityMessageApi extends AXMChatMessageApi {
7696
8094
  }
7697
8095
  async getMessages(conversationId, pagination) {
7698
8096
  await this.requireConversationParticipant(conversationId);
7699
- const entities = await this.loadConversationMessages(conversationId);
8097
+ const entities = await this.conversationStore.loadConversationMessages(conversationId, {
8098
+ force: pagination.page === 0,
8099
+ });
7700
8100
  const merged = this.mergePersistedMessages(conversationId, entities);
7701
8101
  return this.paginateAxMessages(merged, pagination);
7702
8102
  }
@@ -8055,6 +8455,125 @@ const AXM_CONVERSATION_TAB_BOT = {
8055
8455
  };
8056
8456
  //#endregion
8057
8457
 
8458
+ //#region ----- Imports -----
8459
+ //#endregion
8460
+ const CHAT_IN_APP_DEFINITION_KEY = 'conversation-chat-message';
8461
+ //#region ----- Chat ↔ inbox read bridge -----
8462
+ /**
8463
+ * Keeps chat unread and in-app chat notifications aligned:
8464
+ * focused / muted rooms clear the tray unread; marking a notification read marks the chat read.
8465
+ */
8466
+ class AXMConversationChatInboxBridgeService {
8467
+ //#endregion
8468
+ constructor() {
8469
+ //#region ----- Services & Dependencies -----
8470
+ this.inboxConnector = inject(AXPInAppInboxConnectorService, { optional: true });
8471
+ this.focus = inject(AXMConversationFocusService);
8472
+ this.inAppSync = inject(AXMConversationInAppNotificationSyncService);
8473
+ this.userApi = inject(AXMChatEntityUserApi);
8474
+ this.session = inject(AXPSessionService);
8475
+ this.commandService = inject(AXPCommandService);
8476
+ this.destroyRef = inject(DestroyRef);
8477
+ //#endregion
8478
+ //#region ----- State -----
8479
+ this.primed = false;
8480
+ this.reconcileChain = Promise.resolve();
8481
+ this.reverseSyncInFlight = new Set();
8482
+ this.session.user$
8483
+ .pipe(map((user) => user?.id?.trim() ?? null), distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
8484
+ .subscribe(() => {
8485
+ this.primed = false;
8486
+ this.inAppSync.clearRememberedReadDeliveries();
8487
+ this.reverseSyncInFlight.clear();
8488
+ });
8489
+ effect(() => {
8490
+ this.focus.focusedConversationIdSignal();
8491
+ this.inboxConnector?.inboxList();
8492
+ this.reconcileChain = this.reconcileChain
8493
+ .then(() => this.reconcile())
8494
+ .catch(() => undefined);
8495
+ });
8496
+ }
8497
+ async reconcile() {
8498
+ if (!this.inboxConnector) {
8499
+ return;
8500
+ }
8501
+ await this.inboxConnector.ensureReady();
8502
+ const items = this.inboxConnector.inboxList();
8503
+ const userId = this.session.user?.id?.trim();
8504
+ if (!userId) {
8505
+ return;
8506
+ }
8507
+ const chatItems = items.filter((item) => item.definitionKey === CHAT_IN_APP_DEFINITION_KEY);
8508
+ for (const item of chatItems) {
8509
+ const conversationId = this.conversationIdFromItem(item);
8510
+ if (!conversationId) {
8511
+ continue;
8512
+ }
8513
+ if (isInAppInboxUnread(item.readAt)) {
8514
+ if (this.focus.isFocused(conversationId)) {
8515
+ this.inAppSync.rememberReadDeliveryId(item.id);
8516
+ await this.inAppSync.markConversationInAppNotificationRead(conversationId, userId, {
8517
+ force: true,
8518
+ });
8519
+ continue;
8520
+ }
8521
+ const preferences = await this.userApi.getConversationPreferencesForRoom(conversationId);
8522
+ const muted = preferences.notifications === false ||
8523
+ (preferences.mutedUntil != null && preferences.mutedUntil.getTime() > Date.now());
8524
+ if (muted) {
8525
+ await this.inAppSync.dismissConversationInAppNotification(conversationId, userId, {
8526
+ force: true,
8527
+ });
8528
+ }
8529
+ continue;
8530
+ }
8531
+ if (!this.primed) {
8532
+ this.inAppSync.rememberReadDeliveryId(item.id);
8533
+ continue;
8534
+ }
8535
+ if (this.inAppSync.hasRememberedReadDelivery(item.id)) {
8536
+ continue;
8537
+ }
8538
+ this.inAppSync.rememberReadDeliveryId(item.id);
8539
+ await this.syncChatFromNotification(conversationId, userId);
8540
+ }
8541
+ this.primed = true;
8542
+ }
8543
+ conversationIdFromItem(item) {
8544
+ const parsed = parseConversationChatInAppCorrelationId(item.correlationId);
8545
+ if (parsed?.conversationId) {
8546
+ return parsed.conversationId;
8547
+ }
8548
+ const options = item.actions?.[0]?.command?.options;
8549
+ const conversationId = options?.['conversationId'];
8550
+ return typeof conversationId === 'string' && conversationId.trim() ? conversationId.trim() : null;
8551
+ }
8552
+ async syncChatFromNotification(conversationId, currentUserId) {
8553
+ if (this.reverseSyncInFlight.has(conversationId)) {
8554
+ return;
8555
+ }
8556
+ this.reverseSyncInFlight.add(conversationId);
8557
+ try {
8558
+ await this.commandService.execute(CONVERSATION_SYNC_READ_STATE_COMMAND, {
8559
+ conversationId,
8560
+ currentUserId,
8561
+ force: true,
8562
+ fromInbox: true,
8563
+ });
8564
+ }
8565
+ finally {
8566
+ this.reverseSyncInFlight.delete(conversationId);
8567
+ }
8568
+ }
8569
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMConversationChatInboxBridgeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8570
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMConversationChatInboxBridgeService, providedIn: 'root' }); }
8571
+ }
8572
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMConversationChatInboxBridgeService, decorators: [{
8573
+ type: Injectable,
8574
+ args: [{ providedIn: 'root' }]
8575
+ }], ctorParameters: () => [] });
8576
+
8058
8577
  //#region ---- Login catch-up for stale chat inbox rows ----
8059
8578
  /**
8060
8579
  * After conversations load, ensure chat inbox rows exist and match the room's
@@ -8090,6 +8609,9 @@ class AXMConversationChatInboxCatchUpService {
8090
8609
  if (axmIsAssistStreamingMessage(lastMessage)) {
8091
8610
  continue;
8092
8611
  }
8612
+ if ((conversation.unreadCount ?? 0) <= 0) {
8613
+ continue;
8614
+ }
8093
8615
  if (this.focus.isFocused(conversationId)) {
8094
8616
  continue;
8095
8617
  }
@@ -8483,6 +9005,7 @@ const AXM_CHAT_CONVERSATION_PROVIDERS = [
8483
9005
  AXMConversationSessionSyncService,
8484
9006
  provideAppStartUpTask(() => {
8485
9007
  const sync = inject(AXMConversationSessionSyncService);
9008
+ inject(AXMConversationChatInboxBridgeService);
8486
9009
  return {
8487
9010
  name: 'conversation-session-sync',
8488
9011
  priority: AXP_APP_STARTUP_PRIORITY.conversationSessionSync,
@@ -8612,7 +9135,7 @@ class AXMMiniChatHistoryComponent {
8612
9135
  }
8613
9136
  </div>
8614
9137
  </div>
8615
- `, isInline: true, styles: [":host{display:flex;min-height:0;flex:1;flex-direction:column}.axm-mini-chat-history__item{color:inherit}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPAvatarComponent, selector: "axp-avatar", inputs: ["size", "src", "fullName", "showTitle", "fallbackText", "placeholder"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9138
+ `, isInline: true, styles: [":host{display:flex;min-height:0;flex:1;flex-direction:column}.axm-mini-chat-history__item{color:inherit}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPAvatarComponent, selector: "axp-avatar", inputs: ["size", "src", "fullName", "showTitle", "fallbackText", "placeholder"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8616
9139
  }
8617
9140
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatHistoryComponent, decorators: [{
8618
9141
  type: Component,
@@ -8784,7 +9307,7 @@ class AXMMiniChatInboxHistoryComponent {
8784
9307
  }
8785
9308
  </div>
8786
9309
  </div>
8787
- `, isInline: true, styles: [":host{display:flex;min-height:0;flex:1;flex-direction:column}.axm-mini-chat-inbox-history__item{color:inherit}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPAvatarComponent, selector: "axp-avatar", inputs: ["size", "src", "fullName", "showTitle", "fallbackText", "placeholder"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9310
+ `, isInline: true, styles: [":host{display:flex;min-height:0;flex:1;flex-direction:column}.axm-mini-chat-inbox-history__item{color:inherit}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPAvatarComponent, selector: "axp-avatar", inputs: ["size", "src", "fullName", "showTitle", "fallbackText", "placeholder"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8788
9311
  }
8789
9312
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatInboxHistoryComponent, decorators: [{
8790
9313
  type: Component,
@@ -9436,6 +9959,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9436
9959
  }]
9437
9960
  }], ctorParameters: () => [], propDecorators: { compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], initialAssistId: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialAssistId", required: false }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: false }] }], entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], sendStarterPromptsInPlace: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendStarterPromptsInPlace", required: false }] }], conversationCreated: [{ type: i0.Output, args: ["conversationCreated"] }], host: [{ type: i0.ViewChild, args: ['host', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
9438
9961
 
9962
+ //#region ----- Imports -----
9963
+ //#endregion
9964
+ //#region ----- Dialog -----
9965
+ /**
9966
+ * Opens the conversation info panel popup for the given conversation.
9967
+ * Pass {@link AXMOpenChatConversationInfoPanelDialogOptions.popupService} and
9968
+ * {@link AXMOpenChatConversationInfoPanelDialogOptions.conversationService} from the
9969
+ * caller — popup content is created on the root view container, so `inject()` after
9970
+ * `await` or from overlay DI cannot see the chat feature's conversation service.
9971
+ */
9972
+ async function axmOpenChatConversationInfoPanelDialog(options) {
9973
+ const conversation = options.conversation;
9974
+ if (!conversation?.id?.trim()) {
9975
+ return;
9976
+ }
9977
+ const popupService = options.popupService ?? inject(AXPopupService);
9978
+ const conversationService = options.conversationService ?? inject(AXConversationService);
9979
+ const comp = (await import('./acorex-platform-module-conversation-client-chat-conversation-info-panel.component-51PtojIM.mjs')).AXMChatConversationInfoPanelComponent;
9980
+ await popupService.open(comp, {
9981
+ title: conversation.title,
9982
+ closeButton: true,
9983
+ size: 'sm',
9984
+ data: {
9985
+ conversation,
9986
+ conversationService,
9987
+ },
9988
+ });
9989
+ }
9990
+ //#endregion
9991
+
9439
9992
  //#region ---- Imports ----
9440
9993
  //#endregion
9441
9994
  //#region ---- Component ----
@@ -9466,6 +10019,7 @@ class AXMMiniChatComponent {
9466
10019
  constructor() {
9467
10020
  //#region ---- Services & Dependencies ----
9468
10021
  this.conversationService = inject(AXConversationService);
10022
+ this.popupService = inject(AXPopupService);
9469
10023
  this.conversationApi = inject(AXMChatConversationApi);
9470
10024
  this.destroyRef = inject(DestroyRef);
9471
10025
  //#endregion
@@ -9526,12 +10080,24 @@ class AXMMiniChatComponent {
9526
10080
  }
9527
10081
  //#endregion
9528
10082
  //#region ---- UI Handlers ----
10083
+ /** Opens the conversation info panel when the info-bar title/avatar area is clicked. */
10084
+ onInfoBarClick() {
10085
+ const conversation = this.conversationService.activeConversation();
10086
+ if (!conversation?.id?.trim()) {
10087
+ return;
10088
+ }
10089
+ void axmOpenChatConversationInfoPanelDialog({
10090
+ conversation,
10091
+ popupService: this.popupService,
10092
+ conversationService: this.conversationService,
10093
+ });
10094
+ }
9529
10095
  /** New-chat composer created and selected a conversation; surface it to the host. */
9530
10096
  onConversationCreated(conversationId) {
9531
10097
  this.conversationOpened.emit(conversationId);
9532
10098
  }
9533
10099
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9534
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMMiniChatComponent, isStandalone: true, selector: "axm-mini-chat", inputs: { chatId: { classPropertyName: "chatId", publicName: "chatId", isSignal: true, isRequired: false, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: false, transformFunction: null }, entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, assistId: { classPropertyName: "assistId", publicName: "assistId", isSignal: true, isRequired: false, transformFunction: null }, showInfoBar: { classPropertyName: "showInfoBar", publicName: "showInfoBar", isSignal: true, isRequired: false, transformFunction: null }, showComposer: { classPropertyName: "showComposer", publicName: "showComposer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { conversationOpened: "conversationOpened" }, ngImport: i0, template: "<div axConversationContainer class=\"axm-mini-chat flex h-full min-h-0 flex-col\">\n @if (showInfoBar() && hasActiveConversation()) {\n <ax-conversation-info-bar class=\"axm-mini-chat__info-bar shrink-0 shadow-sm\"></ax-conversation-info-bar>\n }\n\n <ax-conversation-message-list class=\"axm-mini-chat__messages min-h-0 flex-1 overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"axm-mini-chat__no-active block\">\n <axm-chat-empty-state-host [compact]=\"true\" [entityId]=\"entityId()\" [entityType]=\"entityType()\" [initialAssistId]=\"assistId()\" [sendStarterPromptsInPlace]=\"true\" (conversationCreated)=\"onConversationCreated($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty [compact]=\"true\" [sendStarterPromptsInPlace]=\"true\" />\n </ax-conversation-message-list>\n\n @if (showComposer() && hasActiveConversation()) {\n <ax-conversation-composer\n class=\"axm-mini-chat__composer shrink-0\"\n />\n }\n</div>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}.axm-mini-chat .axm-mini-chat__info-bar{border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-mini-chat .axm-mini-chat__composer{border-top:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__messages{background:radial-gradient(ellipse 120% 80% at 50% -20%,rgba(var(--ax-sys-color-primary-500),.07),transparent 55%),rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__no-active{width:100%;max-width:none;padding:0;margin:0}.axm-mini-chat ax-conversation-message-list .list-no-active{justify-content:center;align-items:stretch;min-height:100%;padding:1rem 1rem 1.25rem;gap:0;text-align:start;animation:none}.axm-mini-chat ax-conversation-message-list .list-empty{justify-content:flex-start;align-items:stretch;min-height:0;padding:.75rem .875rem 1rem;gap:0;text-align:start;animation:none}.axm-mini-chat .axm-chat-assist-composer-starter-prompts-host--compact .axm-chat-assist-welcome-empty{padding:0;gap:.5rem}.axm-mini-chat .axm-chat-empty-assist-composer-host--compact .axm-chat-empty-assist-composer__composer-row{box-shadow:0 1px 2px rgba(var(--ax-sys-color-on-surface),.04),0 4px 12px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{border-color:rgba(var(--ax-sys-color-border-light-surface),.95);background:rgba(var(--ax-sys-color-surface),.55);color:rgb(var(--ax-sys-color-on-surface));transition:background-color .16s ease,border-color .16s ease,transform .16s ease}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){border-color:rgba(var(--ax-sys-color-primary-500),.35);background:rgba(var(--ax-sys-color-primary-500),.08);transform:translateY(-1px)}@media(prefers-reduced-motion:reduce){.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{transition:none}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){transform:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXConversationInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["infoClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXConversationMessageListComponent, selector: "ax-conversation-message-list", outputs: ["messageAction"] }, { kind: "component", type: AXConversationComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "generationCancelled", "emojiClick", "attachClick", "voiceClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXMChatEmptyStateHostComponent, selector: "axm-chat-empty-state-host", inputs: ["compact", "initialAssistId", "entityId", "entityType", "sendStarterPromptsInPlace"], outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatAssistComposerStarterPromptsComponent, selector: "axm-chat-assist-composer-starter-prompts", inputs: ["sendStarterPromptsInPlace", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10100
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMMiniChatComponent, isStandalone: true, selector: "axm-mini-chat", inputs: { chatId: { classPropertyName: "chatId", publicName: "chatId", isSignal: true, isRequired: false, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: false, transformFunction: null }, entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, assistId: { classPropertyName: "assistId", publicName: "assistId", isSignal: true, isRequired: false, transformFunction: null }, showInfoBar: { classPropertyName: "showInfoBar", publicName: "showInfoBar", isSignal: true, isRequired: false, transformFunction: null }, showComposer: { classPropertyName: "showComposer", publicName: "showComposer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { conversationOpened: "conversationOpened" }, ngImport: i0, template: "<div axConversationContainer class=\"axm-mini-chat flex h-full min-h-0 flex-col\">\n @if (showInfoBar() && hasActiveConversation()) {\n <ax-conversation-info-bar class=\"axm-mini-chat__info-bar shrink-0 shadow-sm\" (infoClick)=\"onInfoBarClick()\"></ax-conversation-info-bar>\n }\n\n <ax-conversation-message-list class=\"axm-mini-chat__messages min-h-0 flex-1 overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"axm-mini-chat__no-active block\">\n <axm-chat-empty-state-host [compact]=\"true\" [entityId]=\"entityId()\" [entityType]=\"entityType()\" [initialAssistId]=\"assistId()\" [sendStarterPromptsInPlace]=\"true\" (conversationCreated)=\"onConversationCreated($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty [compact]=\"true\" [sendStarterPromptsInPlace]=\"true\" />\n </ax-conversation-message-list>\n\n @if (showComposer() && hasActiveConversation()) {\n <ax-conversation-composer\n class=\"axm-mini-chat__composer shrink-0\"\n />\n }\n</div>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}.axm-mini-chat .axm-mini-chat__info-bar{border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-mini-chat .axm-mini-chat__composer{border-top:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__messages{background:radial-gradient(ellipse 120% 80% at 50% -20%,rgba(var(--ax-sys-color-primary-500),.07),transparent 55%),rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__no-active{width:100%;max-width:none;padding:0;margin:0}.axm-mini-chat ax-conversation-message-list .list-no-active{justify-content:center;align-items:stretch;min-height:100%;padding:1rem 1rem 1.25rem;gap:0;text-align:start;animation:none}.axm-mini-chat ax-conversation-message-list .list-empty{justify-content:flex-start;align-items:stretch;min-height:0;padding:.75rem .875rem 1rem;gap:0;text-align:start;animation:none}.axm-mini-chat .axm-chat-assist-composer-starter-prompts-host--compact .axm-chat-assist-welcome-empty{padding:0;gap:.5rem}.axm-mini-chat .axm-chat-empty-assist-composer-host--compact .axm-chat-empty-assist-composer__composer-row{box-shadow:0 1px 2px rgba(var(--ax-sys-color-on-surface),.04),0 4px 12px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{border-color:rgba(var(--ax-sys-color-border-light-surface),.95);background:rgba(var(--ax-sys-color-surface),.55);color:rgb(var(--ax-sys-color-on-surface));transition:background-color .16s ease,border-color .16s ease,transform .16s ease}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){border-color:rgba(var(--ax-sys-color-primary-500),.35);background:rgba(var(--ax-sys-color-primary-500),.08);transform:translateY(-1px)}@media(prefers-reduced-motion:reduce){.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{transition:none}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){transform:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXConversationInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["infoClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXConversationMessageListComponent, selector: "ax-conversation-message-list", outputs: ["messageAction"] }, { kind: "component", type: AXConversationComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "generationCancelled", "emojiClick", "attachClick", "voiceClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXMChatEmptyStateHostComponent, selector: "axm-chat-empty-state-host", inputs: ["compact", "initialAssistId", "entityId", "entityType", "sendStarterPromptsInPlace"], outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatAssistComposerStarterPromptsComponent, selector: "axm-chat-assist-composer-starter-prompts", inputs: ["sendStarterPromptsInPlace", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9535
10101
  }
9536
10102
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatComponent, decorators: [{
9537
10103
  type: Component,
@@ -9544,7 +10110,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9544
10110
  AXTranslationModule,
9545
10111
  AXMChatEmptyStateHostComponent,
9546
10112
  AXMChatAssistComposerStarterPromptsComponent,
9547
- ], template: "<div axConversationContainer class=\"axm-mini-chat flex h-full min-h-0 flex-col\">\n @if (showInfoBar() && hasActiveConversation()) {\n <ax-conversation-info-bar class=\"axm-mini-chat__info-bar shrink-0 shadow-sm\"></ax-conversation-info-bar>\n }\n\n <ax-conversation-message-list class=\"axm-mini-chat__messages min-h-0 flex-1 overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"axm-mini-chat__no-active block\">\n <axm-chat-empty-state-host [compact]=\"true\" [entityId]=\"entityId()\" [entityType]=\"entityType()\" [initialAssistId]=\"assistId()\" [sendStarterPromptsInPlace]=\"true\" (conversationCreated)=\"onConversationCreated($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty [compact]=\"true\" [sendStarterPromptsInPlace]=\"true\" />\n </ax-conversation-message-list>\n\n @if (showComposer() && hasActiveConversation()) {\n <ax-conversation-composer\n class=\"axm-mini-chat__composer shrink-0\"\n />\n }\n</div>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}.axm-mini-chat .axm-mini-chat__info-bar{border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-mini-chat .axm-mini-chat__composer{border-top:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__messages{background:radial-gradient(ellipse 120% 80% at 50% -20%,rgba(var(--ax-sys-color-primary-500),.07),transparent 55%),rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__no-active{width:100%;max-width:none;padding:0;margin:0}.axm-mini-chat ax-conversation-message-list .list-no-active{justify-content:center;align-items:stretch;min-height:100%;padding:1rem 1rem 1.25rem;gap:0;text-align:start;animation:none}.axm-mini-chat ax-conversation-message-list .list-empty{justify-content:flex-start;align-items:stretch;min-height:0;padding:.75rem .875rem 1rem;gap:0;text-align:start;animation:none}.axm-mini-chat .axm-chat-assist-composer-starter-prompts-host--compact .axm-chat-assist-welcome-empty{padding:0;gap:.5rem}.axm-mini-chat .axm-chat-empty-assist-composer-host--compact .axm-chat-empty-assist-composer__composer-row{box-shadow:0 1px 2px rgba(var(--ax-sys-color-on-surface),.04),0 4px 12px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{border-color:rgba(var(--ax-sys-color-border-light-surface),.95);background:rgba(var(--ax-sys-color-surface),.55);color:rgb(var(--ax-sys-color-on-surface));transition:background-color .16s ease,border-color .16s ease,transform .16s ease}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){border-color:rgba(var(--ax-sys-color-primary-500),.35);background:rgba(var(--ax-sys-color-primary-500),.08);transform:translateY(-1px)}@media(prefers-reduced-motion:reduce){.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{transition:none}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){transform:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
10113
+ ], template: "<div axConversationContainer class=\"axm-mini-chat flex h-full min-h-0 flex-col\">\n @if (showInfoBar() && hasActiveConversation()) {\n <ax-conversation-info-bar class=\"axm-mini-chat__info-bar shrink-0 shadow-sm\" (infoClick)=\"onInfoBarClick()\"></ax-conversation-info-bar>\n }\n\n <ax-conversation-message-list class=\"axm-mini-chat__messages min-h-0 flex-1 overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"axm-mini-chat__no-active block\">\n <axm-chat-empty-state-host [compact]=\"true\" [entityId]=\"entityId()\" [entityType]=\"entityType()\" [initialAssistId]=\"assistId()\" [sendStarterPromptsInPlace]=\"true\" (conversationCreated)=\"onConversationCreated($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty [compact]=\"true\" [sendStarterPromptsInPlace]=\"true\" />\n </ax-conversation-message-list>\n\n @if (showComposer() && hasActiveConversation()) {\n <ax-conversation-composer\n class=\"axm-mini-chat__composer shrink-0\"\n />\n }\n</div>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}.axm-mini-chat .axm-mini-chat__info-bar{border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-mini-chat .axm-mini-chat__composer{border-top:1px solid rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__messages{background:radial-gradient(ellipse 120% 80% at 50% -20%,rgba(var(--ax-sys-color-primary-500),.07),transparent 55%),rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat .axm-mini-chat__no-active{width:100%;max-width:none;padding:0;margin:0}.axm-mini-chat ax-conversation-message-list .list-no-active{justify-content:center;align-items:stretch;min-height:100%;padding:1rem 1rem 1.25rem;gap:0;text-align:start;animation:none}.axm-mini-chat ax-conversation-message-list .list-empty{justify-content:flex-start;align-items:stretch;min-height:0;padding:.75rem .875rem 1rem;gap:0;text-align:start;animation:none}.axm-mini-chat .axm-chat-assist-composer-starter-prompts-host--compact .axm-chat-assist-welcome-empty{padding:0;gap:.5rem}.axm-mini-chat .axm-chat-empty-assist-composer-host--compact .axm-chat-empty-assist-composer__composer-row{box-shadow:0 1px 2px rgba(var(--ax-sys-color-on-surface),.04),0 4px 12px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{border-color:rgba(var(--ax-sys-color-border-light-surface),.95);background:rgba(var(--ax-sys-color-surface),.55);color:rgb(var(--ax-sys-color-on-surface));transition:background-color .16s ease,border-color .16s ease,transform .16s ease}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){border-color:rgba(var(--ax-sys-color-primary-500),.35);background:rgba(var(--ax-sys-color-primary-500),.08);transform:translateY(-1px)}@media(prefers-reduced-motion:reduce){.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip{transition:none}.axm-mini-chat .axm-assist-suggestion-chips-host--compact .axm-assist-suggestion-chips__chip:hover:not([disabled]){transform:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
9548
10114
  }], ctorParameters: () => [], propDecorators: { chatId: [{ type: i0.Input, args: [{ isSignal: true, alias: "chatId", required: false }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: false }] }], entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], assistId: [{ type: i0.Input, args: [{ isSignal: true, alias: "assistId", required: false }] }], showInfoBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showInfoBar", required: false }] }], showComposer: [{ type: i0.Input, args: [{ isSignal: true, alias: "showComposer", required: false }] }], conversationOpened: [{ type: i0.Output, args: ["conversationOpened"] }] } });
9549
10115
 
9550
10116
  //#region ---- Imports ----
@@ -9682,7 +10248,7 @@ class AXMMiniChatPanelComponent {
9682
10248
  });
9683
10249
  }
9684
10250
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9685
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMMiniChatPanelComponent, isStandalone: true, selector: "axm-mini-chat-panel", inputs: { scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: false, transformFunction: null }, entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, assistId: { classPropertyName: "assistId", publicName: "assistId", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, showInfoBar: { classPropertyName: "showInfoBar", publicName: "showInfoBar", isSignal: true, isRequired: false, transformFunction: null }, showComposer: { classPropertyName: "showComposer", publicName: "showComposer", isSignal: true, isRequired: false, transformFunction: null }, requestClose: { classPropertyName: "requestClose", publicName: "requestClose", isSignal: true, isRequired: true, transformFunction: null }, initialView: { classPropertyName: "initialView", publicName: "initialView", isSignal: true, isRequired: false, transformFunction: null }, initialConversationId: { classPropertyName: "initialConversationId", publicName: "initialConversationId", isSignal: true, isRequired: false, transformFunction: null }, startWithNewChat: { classPropertyName: "startWithNewChat", publicName: "startWithNewChat", isSignal: true, isRequired: false, transformFunction: null }, onSessionChange: { classPropertyName: "onSessionChange", publicName: "onSessionChange", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"axm-mini-chat-panel flex h-full min-h-0 flex-col\">\n <div class=\"axm-mini-chat-panel__header flex shrink-0 items-center justify-between gap-2 px-3.5 py-2.5\">\n <div class=\"flex min-w-0 flex-1 flex-col\">\n @if (view() === 'history') {\n <span class=\"text-sm font-semibold truncate\">\n {{ '@conversation:mini-chat.history-title' | translate | async }}\n </span>\n } @else if (headerTitle()) {\n <span class=\"text-sm font-semibold truncate\">{{ headerTitle() }}</span>\n } @else {\n <span class=\"text-sm font-semibold truncate\">\n {{ '@conversation:mini-chat.new-chat' | translate | async }}\n </span>\n }\n </div>\n <div class=\"flex shrink-0 items-center gap-1\">\n @if (view() !== 'history') {\n <ax-button look=\"blank\" [iconOnly]=\"true\" (onClick)=\"openHistory()\" aria-label=\"Chat history\">\n <ax-prefix><ax-icon icon=\"fa-light fa-clock-rotate-left\"></ax-icon></ax-prefix>\n </ax-button>\n }\n <ax-button look=\"blank\" [iconOnly]=\"true\" (onClick)=\"closePanel()\" aria-label=\"Close\">\n <ax-prefix><ax-icon icon=\"fa-light fa-xmark\"></ax-icon></ax-prefix>\n </ax-button>\n </div>\n </div>\n\n @if (view() === 'history') {\n <div class=\"axm-mini-chat-panel__history relative flex min-h-0 flex-1 flex-col\">\n @if (isInboxScope()) {\n <axm-mini-chat-inbox-history\n (conversationSelected)=\"selectChat($event)\"\n (hasConversationsChange)=\"onHistoryHasConversationsChange($event)\"\n (newChatRequested)=\"startNewChat()\"\n />\n } @else {\n <axm-mini-chat-history\n [entityId]=\"entityId()!\"\n [entityType]=\"entityType()!\"\n (conversationSelected)=\"selectChat($event)\"\n (hasConversationsChange)=\"onHistoryHasConversationsChange($event)\"\n (newChatRequested)=\"startNewChat()\"\n />\n }\n @if (historyHasItems()) {\n <div class=\"axm-mini-chat-panel__history-fab\">\n <ax-button\n class=\"rounded-full shadow-lg\"\n color=\"primary\"\n [iconOnly]=\"true\"\n (onClick)=\"startNewChat()\"\n [attr.aria-label]=\"('@conversation:mini-chat.new-chat' | translate | async) ?? 'New chat'\"\n >\n <ax-prefix><ax-icon icon=\"fa-light fa-plus\"></ax-icon></ax-prefix>\n </ax-button>\n </div>\n }\n </div>\n } @else {\n <div class=\"axm-mini-chat-panel__body flex min-h-0 flex-1 flex-col\">\n <axm-mini-chat\n class=\"flex min-h-0 flex-1 flex-col\"\n [chatId]=\"selectedChatId()\"\n [entityId]=\"entityId()\"\n [entityType]=\"entityType()\"\n [assistId]=\"assistId()\"\n [showInfoBar]=\"showInfoBar()\"\n [showComposer]=\"showComposer()\"\n (conversationOpened)=\"onConversationOpened($event)\"\n />\n </div>\n }\n</div>\n", styles: [".axm-mini-chat-panel-shell{pointer-events:none;box-sizing:border-box}.axm-mini-chat-panel-shell .ax-overlay-pane{pointer-events:auto;--tw-border-style: none;border-style:none;background-color:transparent;flex:0 0 auto;width:min(92vw,26rem)!important;height:min(72vh,30rem)!important;max-width:calc(100vw - 1.5rem)}.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--default{inset:0;width:100%;max-height:100%;display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-end;padding-right:max(1.5rem,env(safe-area-inset-right,0px));padding-bottom:max(5.5rem,calc(1.5rem + env(safe-area-inset-bottom,0px)));padding-left:max(.75rem,env(safe-area-inset-left,0px));padding-top:max(.5rem,env(safe-area-inset-top,0px))}.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--anchored,.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--fixed{inset:unset;width:auto;height:auto;display:block;padding:0}.axm-mini-chat-panel{box-sizing:border-box;height:100%;overflow:hidden;border-radius:1rem;border:1px solid rgba(var(--ax-sys-color-border-light-surface),.9);background:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 0 0 1px rgba(var(--ax-sys-color-on-surface),.03),0 16px 48px -12px rgba(var(--ax-sys-color-on-surface),.18),0 4px 16px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat-panel .axm-mini-chat-panel__header{min-height:2.75rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface));background:linear-gradient(180deg,rgba(var(--ax-sys-color-surface),.45),rgba(var(--ax-sys-color-lightest-surface),.2))}.axm-mini-chat-panel .axm-mini-chat-panel__header ax-button{opacity:.72;transition:opacity .16s ease}.axm-mini-chat-panel .axm-mini-chat-panel__header ax-button:hover{opacity:1}.axm-mini-chat-panel .axm-mini-chat-panel__history-fab{pointer-events:none;position:sticky;display:flex;justify-content:flex-end;bottom:0;z-index:1;padding:.75rem}.axm-mini-chat-panel .axm-mini-chat-panel__history-fab ax-button{pointer-events:auto}@media(max-width:600px){.axm-mini-chat-panel-shell{pointer-events:auto;position:fixed;box-sizing:border-box;display:flex;flex-direction:column;inset:0!important;width:100%!important;height:100%!important;max-width:100%!important;max-height:100%!important;padding:0!important}.axm-mini-chat-panel-shell .ax-overlay-pane{pointer-events:auto;position:relative;--tw-border-style: none;border-style:none;inset:unset!important;left:unset!important;top:unset!important;right:unset!important;bottom:unset!important;transform:none!important;width:100%!important;height:100%!important;max-width:100%!important;max-height:100%!important;min-height:100dvh;flex:1 1 auto!important;background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat-panel-shell .axm-mini-chat-panel{height:100%;min-height:100dvh;border-radius:0;border:none;box-shadow:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXMMiniChatComponent, selector: "axm-mini-chat", inputs: ["chatId", "entityId", "entityType", "assistId", "showInfoBar", "showComposer"], outputs: ["conversationOpened"] }, { kind: "component", type: AXMMiniChatHistoryComponent, selector: "axm-mini-chat-history", inputs: ["entityId", "entityType"], outputs: ["conversationSelected", "newChatRequested", "hasConversationsChange"] }, { kind: "component", type: AXMMiniChatInboxHistoryComponent, selector: "axm-mini-chat-inbox-history", outputs: ["conversationSelected", "newChatRequested", "hasConversationsChange"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10251
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMMiniChatPanelComponent, isStandalone: true, selector: "axm-mini-chat-panel", inputs: { scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: false, transformFunction: null }, entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, assistId: { classPropertyName: "assistId", publicName: "assistId", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, showInfoBar: { classPropertyName: "showInfoBar", publicName: "showInfoBar", isSignal: true, isRequired: false, transformFunction: null }, showComposer: { classPropertyName: "showComposer", publicName: "showComposer", isSignal: true, isRequired: false, transformFunction: null }, requestClose: { classPropertyName: "requestClose", publicName: "requestClose", isSignal: true, isRequired: true, transformFunction: null }, initialView: { classPropertyName: "initialView", publicName: "initialView", isSignal: true, isRequired: false, transformFunction: null }, initialConversationId: { classPropertyName: "initialConversationId", publicName: "initialConversationId", isSignal: true, isRequired: false, transformFunction: null }, startWithNewChat: { classPropertyName: "startWithNewChat", publicName: "startWithNewChat", isSignal: true, isRequired: false, transformFunction: null }, onSessionChange: { classPropertyName: "onSessionChange", publicName: "onSessionChange", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"axm-mini-chat-panel flex h-full min-h-0 flex-col\">\n <div class=\"axm-mini-chat-panel__header flex shrink-0 items-center justify-between gap-2 px-3.5 py-2.5\">\n <div class=\"flex min-w-0 flex-1 flex-col\">\n @if (view() === 'history') {\n <span class=\"text-sm font-semibold truncate\">\n {{ '@conversation:mini-chat.history-title' | translate | async }}\n </span>\n } @else if (headerTitle()) {\n <span class=\"text-sm font-semibold truncate\">{{ headerTitle() }}</span>\n } @else {\n <span class=\"text-sm font-semibold truncate\">\n {{ '@conversation:mini-chat.new-chat' | translate | async }}\n </span>\n }\n </div>\n <div class=\"flex shrink-0 items-center gap-1\">\n @if (view() !== 'history') {\n <ax-button look=\"blank\" [iconOnly]=\"true\" (onClick)=\"openHistory()\" aria-label=\"Chat history\">\n <ax-prefix><ax-icon icon=\"fa-light fa-clock-rotate-left\"></ax-icon></ax-prefix>\n </ax-button>\n }\n <ax-button look=\"blank\" [iconOnly]=\"true\" (onClick)=\"closePanel()\" aria-label=\"Close\">\n <ax-prefix><ax-icon icon=\"fa-light fa-xmark\"></ax-icon></ax-prefix>\n </ax-button>\n </div>\n </div>\n\n @if (view() === 'history') {\n <div class=\"axm-mini-chat-panel__history relative flex min-h-0 flex-1 flex-col\">\n @if (isInboxScope()) {\n <axm-mini-chat-inbox-history\n (conversationSelected)=\"selectChat($event)\"\n (hasConversationsChange)=\"onHistoryHasConversationsChange($event)\"\n (newChatRequested)=\"startNewChat()\"\n />\n } @else {\n <axm-mini-chat-history\n [entityId]=\"entityId()!\"\n [entityType]=\"entityType()!\"\n (conversationSelected)=\"selectChat($event)\"\n (hasConversationsChange)=\"onHistoryHasConversationsChange($event)\"\n (newChatRequested)=\"startNewChat()\"\n />\n }\n @if (historyHasItems()) {\n <div class=\"axm-mini-chat-panel__history-fab\">\n <ax-button\n class=\"rounded-full shadow-lg\"\n color=\"primary\"\n [iconOnly]=\"true\"\n (onClick)=\"startNewChat()\"\n [attr.aria-label]=\"('@conversation:mini-chat.new-chat' | translate | async) ?? 'New chat'\"\n >\n <ax-prefix><ax-icon icon=\"fa-light fa-plus\"></ax-icon></ax-prefix>\n </ax-button>\n </div>\n }\n </div>\n } @else {\n <div class=\"axm-mini-chat-panel__body flex min-h-0 flex-1 flex-col\">\n <axm-mini-chat\n class=\"flex min-h-0 flex-1 flex-col\"\n [chatId]=\"selectedChatId()\"\n [entityId]=\"entityId()\"\n [entityType]=\"entityType()\"\n [assistId]=\"assistId()\"\n [showInfoBar]=\"showInfoBar()\"\n [showComposer]=\"showComposer()\"\n (conversationOpened)=\"onConversationOpened($event)\"\n />\n </div>\n }\n</div>\n", styles: [".axm-mini-chat-panel-shell{pointer-events:none;box-sizing:border-box}.axm-mini-chat-panel-shell .ax-overlay-pane{pointer-events:auto;--tw-border-style: none;border-style:none;background-color:transparent;flex:0 0 auto;width:min(92vw,26rem)!important;height:min(72vh,30rem)!important;max-width:calc(100vw - 1.5rem)}.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--default{inset:0;width:100%;max-height:100%;display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-end;padding-right:max(1.5rem,env(safe-area-inset-right,0px));padding-bottom:max(5.5rem,calc(1.5rem + env(safe-area-inset-bottom,0px)));padding-left:max(.75rem,env(safe-area-inset-left,0px));padding-top:max(.5rem,env(safe-area-inset-top,0px))}.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--anchored,.axm-mini-chat-panel-shell.axm-mini-chat-panel-shell--fixed{inset:unset;width:auto;height:auto;display:block;padding:0}.axm-mini-chat-panel{box-sizing:border-box;height:100%;overflow:hidden;border-radius:1rem;border:1px solid rgba(var(--ax-sys-color-border-light-surface),.9);background:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 0 0 1px rgba(var(--ax-sys-color-on-surface),.03),0 16px 48px -12px rgba(var(--ax-sys-color-on-surface),.18),0 4px 16px -4px rgba(var(--ax-sys-color-on-surface),.08)}.axm-mini-chat-panel .axm-mini-chat-panel__header{min-height:2.75rem;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface));background:linear-gradient(180deg,rgba(var(--ax-sys-color-surface),.45),rgba(var(--ax-sys-color-lightest-surface),.2))}.axm-mini-chat-panel .axm-mini-chat-panel__header ax-button{opacity:.72;transition:opacity .16s ease}.axm-mini-chat-panel .axm-mini-chat-panel__header ax-button:hover{opacity:1}.axm-mini-chat-panel .axm-mini-chat-panel__history-fab{pointer-events:none;position:sticky;display:flex;justify-content:flex-end;bottom:0;z-index:1;padding:.75rem}.axm-mini-chat-panel .axm-mini-chat-panel__history-fab ax-button{pointer-events:auto}@media(max-width:600px){.axm-mini-chat-panel-shell{pointer-events:auto;position:fixed;box-sizing:border-box;display:flex;flex-direction:column;inset:0!important;width:100%!important;height:100%!important;max-width:100%!important;max-height:100%!important;padding:0!important}.axm-mini-chat-panel-shell .ax-overlay-pane{pointer-events:auto;position:relative;--tw-border-style: none;border-style:none;inset:unset!important;left:unset!important;top:unset!important;right:unset!important;bottom:unset!important;transform:none!important;width:100%!important;height:100%!important;max-width:100%!important;max-height:100%!important;min-height:100dvh;flex:1 1 auto!important;background:rgb(var(--ax-sys-color-lightest-surface))}.axm-mini-chat-panel-shell .axm-mini-chat-panel{height:100%;min-height:100dvh;border-radius:0;border:none;box-shadow:none}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXMMiniChatComponent, selector: "axm-mini-chat", inputs: ["chatId", "entityId", "entityType", "assistId", "showInfoBar", "showComposer"], outputs: ["conversationOpened"] }, { kind: "component", type: AXMMiniChatHistoryComponent, selector: "axm-mini-chat-history", inputs: ["entityId", "entityType"], outputs: ["conversationSelected", "newChatRequested", "hasConversationsChange"] }, { kind: "component", type: AXMMiniChatInboxHistoryComponent, selector: "axm-mini-chat-inbox-history", outputs: ["conversationSelected", "newChatRequested", "hasConversationsChange"] }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9686
10252
  }
9687
10253
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatPanelComponent, decorators: [{
9688
10254
  type: Component,
@@ -9927,21 +10493,26 @@ class AXMMiniChatPanelService {
9927
10493
  }
9928
10494
  disposeOverlayOnly() {
9929
10495
  this.removeDismissHandlers();
9930
- if (this.overlayRef) {
9931
- this.overlayRef.dispose();
9932
- this.overlayRef = null;
9933
- }
10496
+ const ref = this.overlayRef;
10497
+ this.overlayRef = null;
9934
10498
  this.anchorElement = null;
9935
10499
  this.panelOpen.set(false);
9936
- if (this.savedActiveConversationId !== undefined) {
9937
- this.restoreActiveConversation();
10500
+ if (ref) {
10501
+ ref.dispose();
9938
10502
  }
10503
+ this.finishOverlayClose();
9939
10504
  }
9940
10505
  handleOverlayDisposed() {
9941
10506
  this.removeDismissHandlers();
9942
10507
  this.overlayRef = null;
9943
10508
  this.anchorElement = null;
9944
10509
  this.panelOpen.set(false);
10510
+ this.finishOverlayClose();
10511
+ }
10512
+ finishOverlayClose() {
10513
+ if (this.savedActiveConversationId !== undefined) {
10514
+ this.restoreActiveConversation();
10515
+ }
9945
10516
  }
9946
10517
  bindDismissHandlers(overlayElement, anchor) {
9947
10518
  this.removeDismissHandlers();
@@ -10045,33 +10616,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10045
10616
  args: [{ providedIn: 'root' }]
10046
10617
  }] });
10047
10618
 
10048
- //#region ----- Imports -----
10049
- //#endregion
10050
- //#region ----- Dialog -----
10051
- /**
10052
- * Opens the conversation info panel popup for the given conversation.
10053
- * Must be called from an injection context when optional services are omitted.
10054
- */
10055
- async function axmOpenChatConversationInfoPanelDialog(options) {
10056
- const conversation = options.conversation;
10057
- if (!conversation?.id?.trim()) {
10058
- return;
10059
- }
10060
- const popupService = options.popupService ?? inject(AXPopupService);
10061
- const conversationService = options.conversationService ?? inject(AXConversationService);
10062
- const comp = (await import('./acorex-platform-module-conversation-client-chat-conversation-info-panel.component-BBL8iEqc.mjs')).AXMChatConversationInfoPanelComponent;
10063
- await popupService.open(comp, {
10064
- title: conversation.title,
10065
- closeButton: true,
10066
- size: 'sm',
10067
- data: {
10068
- conversation,
10069
- conversationService,
10070
- },
10071
- });
10072
- }
10073
- //#endregion
10074
-
10075
10619
  const AXM_CHAT_SIDEBAR_ACTION_PROVIDER = new InjectionToken('AXM_CHAT_SIDEBAR_ACTION_PROVIDER');
10076
10620
 
10077
10621
  /**
@@ -10170,7 +10714,7 @@ class AXMChatSidebarNewActionsComponent {
10170
10714
  </ax-fab>
10171
10715
  }
10172
10716
  </div>
10173
- `, isInline: true, styles: [":host{display:block;transform:translateY(9rem);transition:transform .2s}:host-context(.group:hover),:host(.fab-menu-open){transform:translateY(0)}@media(max-width:600px){:host{transform:translateY(0)}}.new-conversation-button-container-inner{display:flex;justify-content:end;align-items:center;padding-inline-end:.25rem}.new-conversation-fab,.new-conversation-direct-button{z-index:1}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXFabItemComponent, selector: "ax-fab-item", inputs: ["label"], outputs: ["onClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10717
+ `, isInline: true, styles: [":host{display:block;transform:translateY(9rem);transition:transform .2s}:host-context(.group:hover),:host(.fab-menu-open){transform:translateY(0)}@media(max-width:600px){:host{transform:translateY(0)}}.new-conversation-button-container-inner{display:flex;justify-content:end;align-items:center;padding-inline-end:.25rem}.new-conversation-fab,.new-conversation-direct-button{z-index:1}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXFabItemComponent, selector: "ax-fab-item", inputs: ["label"], outputs: ["onClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10174
10718
  }
10175
10719
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatSidebarNewActionsComponent, decorators: [{
10176
10720
  type: Component,
@@ -10215,8 +10759,10 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
10215
10759
  super(...arguments);
10216
10760
  //#region ---- Services & Dependencies ----
10217
10761
  this.conversationService = inject(AXConversationService);
10762
+ this.popupService = inject(AXPopupService);
10218
10763
  this.chatConversationApi = inject(AXMChatConversationApi);
10219
10764
  this.miniChatPanelService = inject(AXMMiniChatPanelService);
10765
+ this.activeCallSessions = inject(AXMChatCallActiveSessionService);
10220
10766
  this.composerService = inject(AXConversationComposerService);
10221
10767
  this.infoBarService = inject(AXConversationInfoBarService);
10222
10768
  /** Eagerly resolves tenant debug mode for assist debug download action visibility. */
@@ -10249,6 +10795,9 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
10249
10795
  if (this.miniChatPanelService.panelOpen()) {
10250
10796
  return;
10251
10797
  }
10798
+ if (this.activeCallSessions.engaged()) {
10799
+ return;
10800
+ }
10252
10801
  if (!this.#isChatPageShowing()) {
10253
10802
  this.chatConversationApi.reportFocusedConversation(null);
10254
10803
  return;
@@ -10354,6 +10903,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
10354
10903
  }
10355
10904
  void axmOpenChatConversationInfoPanelDialog({
10356
10905
  conversation,
10906
+ popupService: this.popupService,
10357
10907
  conversationService: this.conversationService,
10358
10908
  });
10359
10909
  }
@@ -10397,7 +10947,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
10397
10947
  return axmIsConversationChatUrl(this.routerUrl());
10398
10948
  }
10399
10949
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
10400
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "keydown.escape": "onContainerEscape()" }, properties: { "tabindex": "\"-1\"" } }, usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container axConversationContainer>\n <!-- ----- Desktop sidebar only; mobile uses full-screen list + back navigation ----- -->\n @if (!deviceService.isMobileDevice()) {\n <axp-layout-start-side class=\"border-e h-full\">\n <axp-layout-content class=\"flex flex-col min-h-0 max-w-80\">\n <div class=\"h-full flex flex-col shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <!-- ----- Chat content: list on mobile when idle; conversation + back when selected ----- -->\n\n <axp-page-content class=\"h-full overflow-hidden p-0! flex min-h-0 flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"flex h-full min-h-0 flex-1 flex-col\">\n <ax-conversation-info-bar class=\"shadow-md\">\n <ax-prefix>\n <!-- ----- Back to conversation list on mobile ----- -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" class=\"axm-chat__back\" [attr.aria-label]=\"('@conversation:chat.actions.back-to-chats' | translate | async) ?? ''\" (onClick)=\"openChatList()\">\n <ax-prefix>\n <ax-icon class=\"axm-chat__back-icon\" icon=\"fa-light fa-chevron-left\"></ax-icon>\n </ax-prefix>\n <!--->\n <!-- ----- Unread count from other chats ----- -->\n @if (backBadgeCount() > 0) {\n <ax-badge size=\"sm\" look=\"solid\" color=\"primary\" [text]=\"'' + backBadgeCount()\"></ax-badge>\n }\n </ax-button>\n }\n <!-- ----- Close chat on desktop ----- -->\n @else {\n <ax-button class=\"rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark text-xl\"></ax-icon>\n </ax-button>\n }\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"min-h-0 flex-1 overflow-hidden\">\n <div ax-conversation-message-list-no-active class=\"block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-state-host (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"block\">\n <ax-conversation-composer />\n </axp-page-footer>\n</axp-page-layout>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}axm-chat #axp-page-header{display:none}axm-chat #axp-page-footer-container{padding:0}axm-chat .date-separator{z-index:50!important}axm-chat .message-bubble{padding:.75rem .75rem .25rem!important}axm-chat .message-bubble:has(.axm-chat-call-log){text-align:start}axm-chat .message-bubble .axm-chat-call-log,axm-chat .message-bubble axm-chat-call-log-message-renderer{width:100%;min-width:12.5rem}axm-chat .message-bubble-received .axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}axm-chat .axm-chat__back{display:inline-flex;align-items:center;gap:var(--spacing, .25rem)}axm-chat .axm-chat__back-icon:where(:dir(rtl),[dir=rtl],[dir=rtl] *){rotate:180deg}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXConversationSidebarComponent, selector: "ax-conversation-sidebar", outputs: ["conversationSelected"] }, { kind: "component", type: AXConversationInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["infoClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXConversationMessageListComponent, selector: "ax-conversation-message-list", outputs: ["messageAction"] }, { kind: "component", type: AXConversationComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "generationCancelled", "emojiClick", "attachClick", "voiceClick"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXMChatSidebarNewActionsComponent, selector: "axm-chat-sidebar-new-actions", outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatEmptyStateHostComponent, selector: "axm-chat-empty-state-host", inputs: ["compact", "initialAssistId", "entityId", "entityType", "sendStarterPromptsInPlace"], outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatAssistComposerStarterPromptsComponent, selector: "axm-chat-assist-composer-starter-prompts", inputs: ["sendStarterPromptsInPlace", "compact"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10950
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "keydown.escape": "onContainerEscape()" }, properties: { "tabindex": "\"-1\"" } }, usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container axConversationContainer>\n <!-- ----- Desktop sidebar only; mobile uses full-screen list + back navigation ----- -->\n @if (!deviceService.isMobileDevice()) {\n <axp-layout-start-side class=\"border-e h-full\">\n <axp-layout-content class=\"flex flex-col min-h-0 max-w-80\">\n <div class=\"h-full flex flex-col shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <!-- ----- Chat content: list on mobile when idle; conversation + back when selected ----- -->\n\n <axp-page-content class=\"h-full overflow-hidden p-0! flex min-h-0 flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"flex h-full min-h-0 flex-1 flex-col\">\n <ax-conversation-info-bar class=\"shadow-md\" (infoClick)=\"onInfoBarClick()\">\n <ax-prefix>\n <!-- ----- Back to conversation list on mobile ----- -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" class=\"axm-chat__back\" [attr.aria-label]=\"('@conversation:chat.actions.back-to-chats' | translate | async) ?? ''\" (onClick)=\"openChatList()\">\n <ax-prefix>\n <ax-icon class=\"axm-chat__back-icon\" icon=\"fa-light fa-chevron-left\"></ax-icon>\n </ax-prefix>\n <!--->\n <!-- ----- Unread count from other chats ----- -->\n @if (backBadgeCount() > 0) {\n <ax-badge size=\"sm\" look=\"solid\" color=\"primary\" [text]=\"'' + backBadgeCount()\"></ax-badge>\n }\n </ax-button>\n }\n <!-- ----- Close chat on desktop ----- -->\n <!-- @else {\n <ax-button class=\"rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark text-xl\"></ax-icon>\n </ax-button>\n } -->\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"min-h-0 flex-1 overflow-hidden\">\n <div ax-conversation-message-list-no-active class=\"block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-state-host (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"block\">\n <ax-conversation-composer />\n </axp-page-footer>\n</axp-page-layout>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}axm-chat #axp-page-header{display:none}axm-chat #axp-page-footer-container{padding:0}axm-chat .date-separator{z-index:50!important}axm-chat .message-bubble:has(.axm-chat-call-log){text-align:start}axm-chat .message-bubble .axm-chat-call-log,axm-chat .message-bubble axm-chat-call-log-message-renderer{width:100%;min-width:12.5rem}axm-chat .message-bubble-received .axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}axm-chat .axm-chat__back{display:inline-flex;align-items:center;gap:var(--spacing, .25rem)}axm-chat .axm-chat__back-icon:where(:dir(rtl),[dir=rtl],[dir=rtl] *){rotate:180deg}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXConversationSidebarComponent, selector: "ax-conversation-sidebar", outputs: ["conversationSelected"] }, { kind: "component", type: AXConversationInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["infoClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXConversationMessageListComponent, selector: "ax-conversation-message-list", outputs: ["messageAction"] }, { kind: "component", type: AXConversationComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "generationCancelled", "emojiClick", "attachClick", "voiceClick"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXMChatSidebarNewActionsComponent, selector: "axm-chat-sidebar-new-actions", outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatEmptyStateHostComponent, selector: "axm-chat-empty-state-host", inputs: ["compact", "initialAssistId", "entityId", "entityType", "sendStarterPromptsInPlace"], outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatAssistComposerStarterPromptsComponent, selector: "axm-chat-assist-composer-starter-prompts", inputs: ["sendStarterPromptsInPlace", "compact"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10401
10951
  }
10402
10952
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatComponent, decorators: [{
10403
10953
  type: Component,
@@ -10421,7 +10971,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10421
10971
  ], host: {
10422
10972
  '(keydown.escape)': 'onContainerEscape()',
10423
10973
  '[tabindex]': '"-1"',
10424
- }, template: "<axp-page-layout #container axConversationContainer>\n <!-- ----- Desktop sidebar only; mobile uses full-screen list + back navigation ----- -->\n @if (!deviceService.isMobileDevice()) {\n <axp-layout-start-side class=\"border-e h-full\">\n <axp-layout-content class=\"flex flex-col min-h-0 max-w-80\">\n <div class=\"h-full flex flex-col shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <!-- ----- Chat content: list on mobile when idle; conversation + back when selected ----- -->\n\n <axp-page-content class=\"h-full overflow-hidden p-0! flex min-h-0 flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"flex h-full min-h-0 flex-1 flex-col\">\n <ax-conversation-info-bar class=\"shadow-md\">\n <ax-prefix>\n <!-- ----- Back to conversation list on mobile ----- -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" class=\"axm-chat__back\" [attr.aria-label]=\"('@conversation:chat.actions.back-to-chats' | translate | async) ?? ''\" (onClick)=\"openChatList()\">\n <ax-prefix>\n <ax-icon class=\"axm-chat__back-icon\" icon=\"fa-light fa-chevron-left\"></ax-icon>\n </ax-prefix>\n <!--->\n <!-- ----- Unread count from other chats ----- -->\n @if (backBadgeCount() > 0) {\n <ax-badge size=\"sm\" look=\"solid\" color=\"primary\" [text]=\"'' + backBadgeCount()\"></ax-badge>\n }\n </ax-button>\n }\n <!-- ----- Close chat on desktop ----- -->\n @else {\n <ax-button class=\"rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark text-xl\"></ax-icon>\n </ax-button>\n }\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"min-h-0 flex-1 overflow-hidden\">\n <div ax-conversation-message-list-no-active class=\"block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-state-host (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"block\">\n <ax-conversation-composer />\n </axp-page-footer>\n</axp-page-layout>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}axm-chat #axp-page-header{display:none}axm-chat #axp-page-footer-container{padding:0}axm-chat .date-separator{z-index:50!important}axm-chat .message-bubble{padding:.75rem .75rem .25rem!important}axm-chat .message-bubble:has(.axm-chat-call-log){text-align:start}axm-chat .message-bubble .axm-chat-call-log,axm-chat .message-bubble axm-chat-call-log-message-renderer{width:100%;min-width:12.5rem}axm-chat .message-bubble-received .axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}axm-chat .axm-chat__back{display:inline-flex;align-items:center;gap:var(--spacing, .25rem)}axm-chat .axm-chat__back-icon:where(:dir(rtl),[dir=rtl],[dir=rtl] *){rotate:180deg}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
10974
+ }, template: "<axp-page-layout #container axConversationContainer>\n <!-- ----- Desktop sidebar only; mobile uses full-screen list + back navigation ----- -->\n @if (!deviceService.isMobileDevice()) {\n <axp-layout-start-side class=\"border-e h-full\">\n <axp-layout-content class=\"flex flex-col min-h-0 max-w-80\">\n <div class=\"h-full flex flex-col shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <!-- ----- Chat content: list on mobile when idle; conversation + back when selected ----- -->\n\n <axp-page-content class=\"h-full overflow-hidden p-0! flex min-h-0 flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"group\">\n <ax-suffix>\n <div class=\"flex h-14 shrink-0 items-center justify-end overflow-hidden\">\n <axm-chat-sidebar-new-actions (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"flex h-full min-h-0 flex-1 flex-col\">\n <ax-conversation-info-bar class=\"shadow-md\" (infoClick)=\"onInfoBarClick()\">\n <ax-prefix>\n <!-- ----- Back to conversation list on mobile ----- -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" class=\"axm-chat__back\" [attr.aria-label]=\"('@conversation:chat.actions.back-to-chats' | translate | async) ?? ''\" (onClick)=\"openChatList()\">\n <ax-prefix>\n <ax-icon class=\"axm-chat__back-icon\" icon=\"fa-light fa-chevron-left\"></ax-icon>\n </ax-prefix>\n <!--->\n <!-- ----- Unread count from other chats ----- -->\n @if (backBadgeCount() > 0) {\n <ax-badge size=\"sm\" look=\"solid\" color=\"primary\" [text]=\"'' + backBadgeCount()\"></ax-badge>\n }\n </ax-button>\n }\n <!-- ----- Close chat on desktop ----- -->\n <!-- @else {\n <ax-button class=\"rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark text-xl\"></ax-icon>\n </ax-button>\n } -->\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"min-h-0 flex-1 overflow-hidden\">\n <div ax-conversation-message-list-no-active class=\"block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-state-host (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"block\">\n <ax-conversation-composer />\n </axp-page-footer>\n</axp-page-layout>\n", styles: ["ax-conversation-avatar .ax-conversation-avatar-status{display:none}axm-chat #axp-page-header{display:none}axm-chat #axp-page-footer-container{padding:0}axm-chat .date-separator{z-index:50!important}axm-chat .message-bubble:has(.axm-chat-call-log){text-align:start}axm-chat .message-bubble .axm-chat-call-log,axm-chat .message-bubble axm-chat-call-log-message-renderer{width:100%;min-width:12.5rem}axm-chat .message-bubble-received .axm-chat-call-log:not(.axm-chat-call-log--own){--axm-call-log-callback-ring: rgb(var(--ax-sys-color-on-lightest-surface));--axm-call-log-callback-surface: rgb(var(--ax-sys-color-lightest-surface))}axm-chat .axm-chat__back{display:inline-flex;align-items:center;gap:var(--spacing, .25rem)}axm-chat .axm-chat__back-icon:where(:dir(rtl),[dir=rtl],[dir=rtl] *){rotate:180deg}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
10425
10975
  }] });
10426
10976
 
10427
10977
  var chat_component = /*#__PURE__*/Object.freeze({
@@ -11405,7 +11955,7 @@ class AXMCommentComponent {
11405
11955
  return axmExtractTextFromPayload(comment.payload);
11406
11956
  }
11407
11957
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11408
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-comment size-full flex flex-col overflow-hidden\">\n <div class=\"axm-comment__list flex-1 min-h-0 overflow-y-auto\">\n <ax-comment-container>\n @if (isLoading()) {\n <div class=\"axm-comment__skeleton\">\n <ax-skeleton class=\"size-10 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-4 w-32 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-4/5 rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"axm-comment__view\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [repliesExpanded]=\"isRepliesExpanded(comment.id!)\"\n (repliesExpandedChange)=\"\n onRepliesExpandedChange(comment.id!, $event)\n \"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #user\n [size]=\"36\"\n [userId]=\"comment.senderId\"\n [axpUserCard]=\"comment.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"comment.senderId\">{{\n user.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ comment.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.title())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(comment.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(comment))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(comment)\"\n [like]=\"isLikedByUser(comment)\"\n >\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.title())\"\n ></ax-comment-reply-text>\n\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item\n [id]=\"reply.id\"\n [class.highlighted]=\"highlightedCommentId() === reply.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #replyUser\n [size]=\"36\"\n [userId]=\"reply.senderId\"\n [axpUserCard]=\"reply.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"reply.senderId\">{{\n replyUser.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ reply.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"\n editMessage(comment, reply, replyUser.title())\n \"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(reply.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(reply))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(reply)\"\n [like]=\"isLikedByUser(reply)\"\n >\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, replyUser.title())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n }\n <!-- ----- Empty state when no comments exist ----- -->\n @else {\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.title'\n \"\n [description]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.description'\n \"\n >\n </axp-state-message>\n }\n </ax-comment-container>\n </div>\n\n <div class=\"axm-comment__composer\">\n @if (isReplyingMode() || isEditingMode()) {\n <div class=\"axm-comment__context\">\n <button\n type=\"button\"\n class=\"axm-comment__context-main\"\n (click)=\"scrollMain()\"\n >\n <i\n class=\"fa-light axm-comment__context-icon\"\n [class.fa-reply]=\"isReplyingMode()\"\n [class.fa-pen]=\"isEditingMode()\"\n ></i>\n <div class=\"axm-comment__context-copy\">\n <p class=\"axm-comment__context-label\">\n @if (isReplyingMode()) {\n {{\n '@conversation:comments.actions.reply-to' | translate | async\n }}\n <span>{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{\n '@conversation:comments.actions.edit-message'\n | translate\n | async\n }}\n }\n </p>\n <div\n class=\"axm-comment__context-preview\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(getCommentText(activeReplyComment()!))\n : sanitizeHtml(getCommentText(activeEditComment()!))\n \"\n ></div>\n </div>\n </button>\n <button\n type=\"button\"\n class=\"axm-comment__context-close\"\n (click)=\"resetReplyEditState()\"\n [attr.aria-label]=\"\n ('@conversation:comments.actions.cancel.title'\n | translate\n | async) ?? 'Cancel'\n \"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"axm-comment__editor\">\n <ax-wysiwyg-container\n #w\n [look]=\"wysiwygOptions().look\"\n [(ngModel)]=\"commentContent\"\n >\n <ax-wysiwyg-view class=\"min-h-24\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-prefix>\n <ax-suffix>\n <ax-button\n look=\"solid\"\n color=\"primary\"\n class=\"ax-sm\"\n [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"\n '@conversation:comments.actions.send.title' | translate | async\n \"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}.axm-comment{min-height:0px;height:calc(100vh - 210px);background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.875rem;padding:1.25rem 1.25rem 1.5rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__composer{flex-shrink:0;background-color:rgb(var(--ax-sys-color-surface-surface))}.axm-comment .axm-comment__context{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.625rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-bottom:none;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.35);font-size:.8125rem;line-height:1.4}.axm-comment .axm-comment__context-main{display:flex;min-width:0px;flex:1;cursor:pointer;align-items:center;gap:.625rem}.axm-comment .axm-comment__context-icon{flex-shrink:0;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-copy{display:flex;min-width:0px;flex-direction:column;gap:.125rem}.axm-comment .axm-comment__context-label{margin:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-close{flex-shrink:0;cursor:pointer;border-radius:var(--radius-md, .375rem);--tw-border-style: none;border-style:none;padding:.25rem;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1}.axm-comment .axm-comment__context-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.8)}.axm-comment .axm-comment__editor{overflow:hidden;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background-color:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 1px 2px #0f172a0a}.axm-comment .axm-comment__author{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}.axm-comment .axm-comment__date{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128))}.axm-comment .axm-comment__menu-btn{opacity:0;transition:opacity .15s ease}ax-comment-item{border-radius:.75rem;transition:background-color .2s ease}ax-comment-item:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.45)}ax-comment-item:hover .axm-comment__menu-btn{opacity:1}ax-comment-item.highlighted{animation:axm-comment-highlight 2.5s cubic-bezier(.4,0,.2,1) forwards}ax-wysiwyg-container{flex-shrink:0}ax-wysiwyg-container .ax-editor-container{border:none!important;border-radius:0!important;box-shadow:none!important}ax-wysiwyg-container .ax-error-message{padding-inline-start:.75rem}@keyframes axm-comment-highlight{0%{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}10%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5);box-shadow:inset 3px 0 rgb(var(--ax-sys-color-primary-surface))}35%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.3);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lighter-surface),.8)}60%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lightest-surface),.6)}to{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$5.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder", "initialLine"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$5.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$5.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$5.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$5.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$5.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$5.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$5.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$3.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXCommentModule }, { kind: "component", type: i4$1.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4$1.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4$1.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount", "repliesExpanded"], outputs: ["repliesExpandedChange"] }, { kind: "component", type: i4$1.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4$1.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4$1.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4$1.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId", "showPresence", "displayName", "displayAvatar"] }, { kind: "directive", type: AXPUserCardDirective, selector: "[axpUserCard]", inputs: ["axpUserCard", "axpUserCardDisabled", "axpUserCardTrigger"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type: i9.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
11958
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-comment size-full flex flex-col overflow-hidden\">\n <div class=\"axm-comment__list flex-1 min-h-0 overflow-y-auto\">\n <ax-comment-container>\n @if (isLoading()) {\n <div class=\"axm-comment__skeleton\">\n <ax-skeleton class=\"size-10 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-4 w-32 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-4/5 rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"axm-comment__view\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [repliesExpanded]=\"isRepliesExpanded(comment.id!)\"\n (repliesExpandedChange)=\"\n onRepliesExpandedChange(comment.id!, $event)\n \"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #user\n [size]=\"36\"\n [userId]=\"comment.senderId\"\n [axpUserCard]=\"comment.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"comment.senderId\">{{\n user.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ comment.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.title())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(comment.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(comment))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(comment)\"\n [like]=\"isLikedByUser(comment)\"\n >\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.title())\"\n ></ax-comment-reply-text>\n\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item\n [id]=\"reply.id\"\n [class.highlighted]=\"highlightedCommentId() === reply.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #replyUser\n [size]=\"36\"\n [userId]=\"reply.senderId\"\n [axpUserCard]=\"reply.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"reply.senderId\">{{\n replyUser.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ reply.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"\n editMessage(comment, reply, replyUser.title())\n \"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(reply.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(reply))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(reply)\"\n [like]=\"isLikedByUser(reply)\"\n >\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, replyUser.title())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n }\n <!-- ----- Empty state when no comments exist ----- -->\n @else {\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.title'\n \"\n [description]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.description'\n \"\n >\n </axp-state-message>\n }\n </ax-comment-container>\n </div>\n\n <div class=\"axm-comment__composer\">\n @if (isReplyingMode() || isEditingMode()) {\n <div class=\"axm-comment__context\">\n <button\n type=\"button\"\n class=\"axm-comment__context-main\"\n (click)=\"scrollMain()\"\n >\n <i\n class=\"fa-light axm-comment__context-icon\"\n [class.fa-reply]=\"isReplyingMode()\"\n [class.fa-pen]=\"isEditingMode()\"\n ></i>\n <div class=\"axm-comment__context-copy\">\n <p class=\"axm-comment__context-label\">\n @if (isReplyingMode()) {\n {{\n '@conversation:comments.actions.reply-to' | translate | async\n }}\n <span>{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{\n '@conversation:comments.actions.edit-message'\n | translate\n | async\n }}\n }\n </p>\n <div\n class=\"axm-comment__context-preview\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(getCommentText(activeReplyComment()!))\n : sanitizeHtml(getCommentText(activeEditComment()!))\n \"\n ></div>\n </div>\n </button>\n <button\n type=\"button\"\n class=\"axm-comment__context-close\"\n (click)=\"resetReplyEditState()\"\n [attr.aria-label]=\"\n ('@conversation:comments.actions.cancel.title'\n | translate\n | async) ?? 'Cancel'\n \"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"axm-comment__editor\">\n <ax-wysiwyg-container\n #w\n [look]=\"wysiwygOptions().look\"\n [(ngModel)]=\"commentContent\"\n >\n <ax-wysiwyg-view class=\"min-h-24\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-prefix>\n <ax-suffix>\n <ax-button\n look=\"solid\"\n color=\"primary\"\n class=\"ax-sm\"\n [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"\n '@conversation:comments.actions.send.title' | translate | async\n \"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}.axm-comment{min-height:0px;height:calc(100vh - 210px);background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.875rem;padding:1.25rem 1.25rem 1.5rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__composer{flex-shrink:0;background-color:rgb(var(--ax-sys-color-surface-surface))}.axm-comment .axm-comment__context{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.625rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-bottom:none;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.35);font-size:.8125rem;line-height:1.4}.axm-comment .axm-comment__context-main{display:flex;min-width:0px;flex:1;cursor:pointer;align-items:center;gap:.625rem}.axm-comment .axm-comment__context-icon{flex-shrink:0;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-copy{display:flex;min-width:0px;flex-direction:column;gap:.125rem}.axm-comment .axm-comment__context-label{margin:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-close{flex-shrink:0;cursor:pointer;border-radius:var(--radius-md, .375rem);--tw-border-style: none;border-style:none;padding:.25rem;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1}.axm-comment .axm-comment__context-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.8)}.axm-comment .axm-comment__editor{overflow:hidden;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background-color:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 1px 2px #0f172a0a}.axm-comment .axm-comment__author{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}.axm-comment .axm-comment__date{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128))}.axm-comment .axm-comment__menu-btn{opacity:0;transition:opacity .15s ease}ax-comment-item{border-radius:.75rem;transition:background-color .2s ease}ax-comment-item:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.45)}ax-comment-item:hover .axm-comment__menu-btn{opacity:1}ax-comment-item.highlighted{animation:axm-comment-highlight 2.5s cubic-bezier(.4,0,.2,1) forwards}ax-wysiwyg-container{flex-shrink:0}ax-wysiwyg-container .ax-editor-container{border:none!important;border-radius:0!important;box-shadow:none!important}ax-wysiwyg-container .ax-error-message{padding-inline-start:.75rem}@keyframes axm-comment-highlight{0%{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}10%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5);box-shadow:inset 3px 0 rgb(var(--ax-sys-color-primary-surface))}35%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.3);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lighter-surface),.8)}60%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lightest-surface),.6)}to{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$5.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder", "initialLine"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$5.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$5.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$5.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$5.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$5.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$5.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$5.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$3.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXCommentModule }, { kind: "component", type: i4$1.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4$1.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4$1.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount", "repliesExpanded"], outputs: ["repliesExpandedChange"] }, { kind: "component", type: i4$1.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4$1.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4$1.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4$1.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId", "showPresence", "displayName", "displayAvatar"] }, { kind: "directive", type: AXPUserCardDirective, selector: "[axpUserCard]", inputs: ["axpUserCard", "axpUserCardDisabled", "axpUserCardTrigger"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type: i9.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
11409
11959
  trigger('fadeIn', [
11410
11960
  transition(':enter', [
11411
11961
  style({ opacity: 0, transform: 'translateY(10px)' }),
@@ -11692,7 +12242,7 @@ class AXMCommentPopupComponent extends AXBasePageComponent {
11692
12242
  // Angular
11693
12243
  CommonModule }, { kind: "ngmodule", type:
11694
12244
  // ACoreX
11695
- AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
12245
+ AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
11696
12246
  // Comment
11697
12247
  AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None }); }
11698
12248
  }
@@ -11797,7 +12347,7 @@ class AXMMiniChatHeaderSlotComponent {
11797
12347
  });
11798
12348
  }
11799
12349
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatHeaderSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11800
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: AXMMiniChatHeaderSlotComponent, isStandalone: true, selector: "axm-mini-chat-header-slot", viewQueries: [{ propertyName: "chatButtonRef", first: true, predicate: ["chatButton"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #chatButton\n (onClick)=\"onToggleClick()\"\n>\n <ax-icon>\n <i class=\"fa-regular fa-robot\"></i>\n </ax-icon>\n</ax-button>\n", styles: ["axm-mini-chat-header-slot{position:relative}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
12350
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: AXMMiniChatHeaderSlotComponent, isStandalone: true, selector: "axm-mini-chat-header-slot", viewQueries: [{ propertyName: "chatButtonRef", first: true, predicate: ["chatButton"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #chatButton\n (onClick)=\"onToggleClick()\"\n>\n <ax-icon>\n <i class=\"fa-regular fa-robot\"></i>\n </ax-icon>\n</ax-button>\n", styles: ["axm-mini-chat-header-slot{position:relative}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
11801
12351
  }
11802
12352
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatHeaderSlotComponent, decorators: [{
11803
12353
  type: Component,
@@ -11872,7 +12422,7 @@ class AXMMiniChatLauncherComponent {
11872
12422
  <ax-icon [icon]="isOpen() ? 'fa-light fa-xmark' : 'fa-light fa-comments'"></ax-icon>
11873
12423
  </ax-prefix>
11874
12424
  </ax-button>
11875
- `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
12425
+ `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11876
12426
  }
11877
12427
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMMiniChatLauncherComponent, decorators: [{
11878
12428
  type: Component,
@@ -12663,9 +13213,9 @@ class AXMConversationChatInAppNotificationService {
12663
13213
  maybeNotifyForIncomingMessage(message) {
12664
13214
  void this.maybeNotifyForIncomingMessageInternal(message);
12665
13215
  }
12666
- /** Removes a raced inbox row when the user is already viewing the thread. */
12667
- dismissLeftoverForFocusedConversation(conversationId, recipientUserId) {
12668
- void this.inAppSync.dismissConversationInAppNotification(conversationId, recipientUserId, { force: true });
13216
+ /** Marks a raced inbox row read when the user is already viewing the thread. */
13217
+ markLeftoverReadForFocusedConversation(conversationId, recipientUserId) {
13218
+ void this.inAppSync.markConversationInAppNotificationRead(conversationId, recipientUserId, { force: true });
12669
13219
  }
12670
13220
  async maybeNotifyForIncomingMessageInternal(message) {
12671
13221
  if (!this.communicationClient && !this.inboxConnector) {
@@ -12678,6 +13228,9 @@ class AXMConversationChatInAppNotificationService {
12678
13228
  if (!messageId || !conversationId || !currentUserId || !senderId || senderId === currentUserId) {
12679
13229
  return;
12680
13230
  }
13231
+ if (axmIsAssistStreamingMessage(message)) {
13232
+ return;
13233
+ }
12681
13234
  if (this.focus.isFocused(conversationId)) {
12682
13235
  return;
12683
13236
  }
@@ -12829,6 +13382,19 @@ function provideConversationRealtimeHandlers() {
12829
13382
  name: 'conversation-realtime-handlers',
12830
13383
  priority: AXP_APP_STARTUP_PRIORITY.realtimeHandlers,
12831
13384
  run: async () => {
13385
+ const notifyIncomingIfUnfocused = async (message) => {
13386
+ const userId = session.user?.id?.trim();
13387
+ const conversationId = message.conversationId?.trim();
13388
+ if (userId && conversationId && focus.isFocused(conversationId)) {
13389
+ chatInAppNotification.markLeftoverReadForFocusedConversation(conversationId, userId);
13390
+ return;
13391
+ }
13392
+ chatInAppNotification.maybeNotifyForIncomingMessage(message);
13393
+ if (userId && conversationId) {
13394
+ const unreadMessage = message.status === 'read' ? { ...message, status: 'sent' } : message;
13395
+ await store.applyIncomingMessageUnread(unreadMessage, userId);
13396
+ }
13397
+ };
12832
13398
  dispatcher?.register({
12833
13399
  topic: AXP_REALTIME_TOPIC_CONVERSATION_MESSAGE,
12834
13400
  handle: async (envelope) => {
@@ -12857,20 +13423,20 @@ function provideConversationRealtimeHandlers() {
12857
13423
  if (op === 'updated') {
12858
13424
  applyIncomingConversationMessage(store, message, 'updated');
12859
13425
  store.syncConversationPreviewFromMessage(message);
13426
+ const previous = store.getCachedMessage(message.id);
13427
+ store.cacheMessage(message);
13428
+ if (axmIsAssistResponseMessage(message) && !axmIsAssistStreamingMessage(message) && (!previous || axmIsAssistStreamingMessage(previous))) {
13429
+ await notifyIncomingIfUnfocused(message);
13430
+ }
12860
13431
  return;
12861
13432
  }
12862
13433
  if (op === 'created') {
12863
13434
  applyIncomingConversationMessage(store, message, 'created');
12864
- const userId = session.user?.id?.trim();
12865
- const conversationId = message.conversationId?.trim();
12866
- if (userId && conversationId && focus.isFocused(conversationId)) {
12867
- chatInAppNotification.dismissLeftoverForFocusedConversation(conversationId, userId);
13435
+ store.cacheMessage(message);
13436
+ if (axmIsAssistStreamingMessage(message)) {
12868
13437
  return;
12869
13438
  }
12870
- chatInAppNotification.maybeNotifyForIncomingMessage(message);
12871
- if (userId && conversationId) {
12872
- void store.applyIncomingMessageUnread(message, userId);
12873
- }
13439
+ await notifyIncomingIfUnfocused(message);
12874
13440
  }
12875
13441
  },
12876
13442
  });
@@ -12909,31 +13475,52 @@ function provideConversationRealtimeHandlers() {
12909
13475
  }
12910
13476
  const envelopeLastMessage = axmHydrateRealtimeConversationMessage(mutation.lastMessage, String(mutation.lastMessage?.['id'] ?? '').trim(), payload.id);
12911
13477
  if (envelopeLastMessage) {
12912
- applyIncomingConversationMessage(store, envelopeLastMessage, 'updated');
12913
- store.syncConversationPreviewFromMessage(envelopeLastMessage);
13478
+ const existingMessage = store.getCachedMessage(envelopeLastMessage.id);
13479
+ if (!existingMessage) {
13480
+ applyIncomingConversationMessage(store, envelopeLastMessage, 'created');
13481
+ store.cacheMessage(envelopeLastMessage);
13482
+ }
12914
13483
  }
12915
13484
  if (payload.operation === 'updated') {
13485
+ const unreadBefore = store.getCachedConversation(payload.id)?.unreadCount ?? 0;
12916
13486
  const refreshed = await store.refreshConversation(payload.id);
12917
- if (refreshed) {
12918
- store.publishConversationUpdate(refreshed, false);
13487
+ if (!refreshed) {
13488
+ return;
12919
13489
  }
12920
- return;
12921
- }
12922
- const cached = store.getCachedConversation(payload.id);
12923
- if (cached) {
12924
- if (payload.operation === 'created') {
12925
- store.publishConversationCreated(cached, false);
13490
+ if (currentUserId && !axmIsConversationParticipant(refreshed.participants, currentUserId)) {
13491
+ store.publishConversationDeleted(payload.id);
13492
+ return;
12926
13493
  }
12927
- else {
12928
- store.publishConversationUpdate(cached, false);
13494
+ const unread = Math.max(unreadBefore, store.getCachedConversation(payload.id)?.unreadCount ?? 0);
13495
+ const next = { ...refreshed, unreadCount: unread };
13496
+ store.cacheConversation(next);
13497
+ // ACoreX copies `unreadCount` from this snapshot onto the sidebar.
13498
+ // Shared room.unreadCount is the sender's 0. Never emit a room refetch
13499
+ // while this thread is not focused — the message stream already updated preview.
13500
+ if (!focus.isFocused(payload.id)) {
13501
+ return;
12929
13502
  }
13503
+ store.publishConversationUpdate(next, false);
12930
13504
  return;
12931
13505
  }
12932
- const conversation = await store.getConversation(payload.id);
13506
+ const conversation = store.getCachedConversation(payload.id) ?? (await store.getConversation(payload.id));
12933
13507
  if (!conversation) {
12934
13508
  return;
12935
13509
  }
13510
+ if (currentUserId && !axmIsConversationParticipant(conversation.participants, currentUserId)) {
13511
+ return;
13512
+ }
13513
+ if (payload.operation === 'created' && !focus.isFocused(payload.id)) {
13514
+ const inboundLastMessage = envelopeLastMessage ? (envelopeLastMessage.status === 'read' ? { ...envelopeLastMessage, status: 'sent' } : envelopeLastMessage) : null;
13515
+ const inboundUnread = inboundLastMessage && currentUserId && axmMessageCountsTowardUnread(inboundLastMessage, currentUserId) ? 1 : 0;
13516
+ const unread = Math.max(store.getCachedConversation(payload.id)?.unreadCount ?? 0, conversation.unreadCount ?? 0, inboundUnread);
13517
+ const next = { ...conversation, unreadCount: unread };
13518
+ store.cacheConversation(next);
13519
+ store.publishConversationCreated(next, false);
13520
+ return;
13521
+ }
12936
13522
  if (payload.operation === 'created') {
13523
+ store.cacheEmptyMessageList(payload.id);
12937
13524
  store.publishConversationCreated(conversation, false);
12938
13525
  }
12939
13526
  else {
@@ -13025,65 +13612,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13025
13612
  args: [{ providedIn: 'root' }]
13026
13613
  }] });
13027
13614
 
13028
- //#region ----- Imports -----
13029
- //#endregion
13030
- //#region ----- Service -----
13031
- /**
13032
- * Tracks callIds with an open or accepted session so duplicate invite packets
13033
- * do not reopen the incoming-call UI or restart the ringer.
13034
- */
13035
- class AXMChatCallActiveSessionService {
13036
- constructor() {
13037
- this.activeCallIds = new Set();
13038
- this.participantIdsByCall = new Map();
13039
- }
13040
- engage(callId) {
13041
- const id = callId?.trim();
13042
- if (id) {
13043
- this.activeCallIds.add(id);
13044
- }
13045
- }
13046
- release(callId) {
13047
- const id = callId?.trim();
13048
- if (id) {
13049
- this.activeCallIds.delete(id);
13050
- this.participantIdsByCall.delete(id);
13051
- }
13052
- }
13053
- isEngaged(callId) {
13054
- const id = callId?.trim();
13055
- return Boolean(id && this.activeCallIds.has(id));
13056
- }
13057
- addParticipant(callId, userId) {
13058
- const scopedCallId = callId?.trim();
13059
- const scopedUserId = userId?.trim();
13060
- if (!scopedCallId || !scopedUserId) {
13061
- return;
13062
- }
13063
- const members = this.participantIdsByCall.get(scopedCallId) ?? new Set();
13064
- members.add(scopedUserId);
13065
- this.participantIdsByCall.set(scopedCallId, members);
13066
- }
13067
- addParticipants(callId, userIds) {
13068
- for (const userId of userIds) {
13069
- this.addParticipant(callId, userId);
13070
- }
13071
- }
13072
- getParticipantIds(callId) {
13073
- const scopedCallId = callId?.trim();
13074
- if (!scopedCallId) {
13075
- return [];
13076
- }
13077
- return [...(this.participantIdsByCall.get(scopedCallId) ?? [])];
13078
- }
13079
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
13080
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, providedIn: 'root' }); }
13081
- }
13082
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatCallActiveSessionService, decorators: [{
13083
- type: Injectable,
13084
- args: [{ providedIn: 'root' }]
13085
- }] });
13086
-
13087
13615
  //#region ----- Imports -----
13088
13616
  //#endregion
13089
13617
  //#region ----- RTC signaling payloads -----
@@ -13337,6 +13865,7 @@ class AXMChatCallRtcSignalInboxService {
13337
13865
  callId: ring.callId,
13338
13866
  initiatorUserId: ring.fromUserId,
13339
13867
  popupService: this.popupService,
13868
+ activeCallSessions: this.activeSessions,
13340
13869
  });
13341
13870
  }
13342
13871
  finally {
@@ -13511,6 +14040,7 @@ function provideConversationFocusRouteSync() {
13511
14040
  const router = inject(Router);
13512
14041
  const conversationApi = inject(AXMChatConversationApi);
13513
14042
  const miniChatPanel = inject(AXMMiniChatPanelService);
14043
+ const activeCallSessions = inject(AXMChatCallActiveSessionService);
13514
14044
  const destroyRef = inject(DestroyRef);
13515
14045
  return {
13516
14046
  name: 'conversation-focus-route-sync',
@@ -13519,7 +14049,7 @@ function provideConversationFocusRouteSync() {
13519
14049
  router.events
13520
14050
  .pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed(destroyRef))
13521
14051
  .subscribe(() => {
13522
- if (miniChatPanel.panelOpen()) {
14052
+ if (miniChatPanel.panelOpen() || activeCallSessions.engaged()) {
13523
14053
  return;
13524
14054
  }
13525
14055
  if (!axmIsConversationChatUrl(router.url)) {
@@ -13539,7 +14069,7 @@ class AXMCommentsPageComponentProvider {
13539
14069
  return [
13540
14070
  {
13541
14071
  key: COMMENTS_PAGE_COMPONENT_KEY,
13542
- loader: () => import('./acorex-platform-module-conversation-client-comments-page.component-Djn8EikR.mjs').then((m) => m.AXMCommentsPageComponent),
14072
+ loader: () => import('./acorex-platform-module-conversation-client-comments-page.component-Dv_x3ztZ.mjs').then((m) => m.AXMCommentsPageComponent),
13543
14073
  },
13544
14074
  ];
13545
14075
  }
@@ -13831,19 +14361,19 @@ class AXMConversationModule {
13831
14361
  provideCommandSetups([
13832
14362
  {
13833
14363
  key: CONVERSATION_AFTER_MESSAGE_SENT_COMMAND,
13834
- command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-yzW01skh.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
14364
+ command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-BMGagKtP.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
13835
14365
  },
13836
14366
  {
13837
14367
  key: CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND,
13838
- command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-DYIpLKDB.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
14368
+ command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-lcNz4Hpu.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
13839
14369
  },
13840
14370
  {
13841
14371
  key: CONVERSATION_SYNC_READ_STATE_COMMAND,
13842
- command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-D97E8VvL.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
14372
+ command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-DxccFsD9.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
13843
14373
  },
13844
14374
  {
13845
14375
  key: CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND,
13846
- command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-BoTNaBxS.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
14376
+ command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-8NoSuUwe.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
13847
14377
  },
13848
14378
  {
13849
14379
  key: CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND,
@@ -13855,7 +14385,7 @@ class AXMConversationModule {
13855
14385
  },
13856
14386
  {
13857
14387
  key: CONVERSATION_OPEN_CHAT_COMMAND,
13858
- command: () => import('./acorex-platform-module-conversation-client-open-chat.command-VgeGqj-z.mjs').then((m) => m.AXMConversationOpenChatCommand),
14388
+ command: () => import('./acorex-platform-module-conversation-client-open-chat.command-BgJ0Z36e.mjs').then((m) => m.AXMConversationOpenChatCommand),
13859
14389
  },
13860
14390
  {
13861
14391
  key: 'show-comment-popup',
@@ -13950,19 +14480,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13950
14480
  provideCommandSetups([
13951
14481
  {
13952
14482
  key: CONVERSATION_AFTER_MESSAGE_SENT_COMMAND,
13953
- command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-yzW01skh.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
14483
+ command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-BMGagKtP.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
13954
14484
  },
13955
14485
  {
13956
14486
  key: CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND,
13957
- command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-DYIpLKDB.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
14487
+ command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-lcNz4Hpu.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
13958
14488
  },
13959
14489
  {
13960
14490
  key: CONVERSATION_SYNC_READ_STATE_COMMAND,
13961
- command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-D97E8VvL.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
14491
+ command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-DxccFsD9.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
13962
14492
  },
13963
14493
  {
13964
14494
  key: CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND,
13965
- command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-BoTNaBxS.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
14495
+ command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-8NoSuUwe.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
13966
14496
  },
13967
14497
  {
13968
14498
  key: CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND,
@@ -13974,7 +14504,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13974
14504
  },
13975
14505
  {
13976
14506
  key: CONVERSATION_OPEN_CHAT_COMMAND,
13977
- command: () => import('./acorex-platform-module-conversation-client-open-chat.command-VgeGqj-z.mjs').then((m) => m.AXMConversationOpenChatCommand),
14507
+ command: () => import('./acorex-platform-module-conversation-client-open-chat.command-BgJ0Z36e.mjs').then((m) => m.AXMConversationOpenChatCommand),
13978
14508
  },
13979
14509
  {
13980
14510
  key: 'show-comment-popup',
@@ -13999,5 +14529,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13999
14529
  * Generated bundle index. Do not edit.
14000
14530
  */
14001
14531
 
14002
- export { AXMMiniChatHeaderSlotComponent as $, AXMConversationEntityStoreService as A, axmAssistWidgetNodeFromUnknown as B, axmPartitionAssistAnswerText as C, axmSyntheticEmbedMessage as D, AXMNodeMessageRendererComponent as E, AXMAssistBotFileLineComponent as F, AXMAssistSuggestionChipsComponent as G, AXMAddReactionCommand as H, AXMChatComponent as I, AXMChatEntityConversationFocusHandler as J, AXMChatEntityConversationRoomQueryService as K, AXMChatEntityMessageApi as L, AXMChatEntityRealtimeApi as M, AXMChatEntityUserApi as N, AXMChatMessageApi as O, AXMChatRealtimeApi as P, AXMCommentManagementService as Q, AXMCommentPopupComponent as R, AXMCommentRealtimeService as S, AXMCommentRealtimeServiceImpl as T, AXMCommentService as U, AXMCommentServiceImpl as V, AXMCommentWidgetViewComponent as W, AXMConversationAssistBackgroundOperationHandler as X, AXMConversationModule as Y, AXMEntityChatService as Z, AXMMiniChatComponent as _, AXM_CONVERSATION_ASSIST_RESPONSE_PORT as a, axmExtractDirectAgentIdFromMetadata as a$, AXMMiniChatHistoryComponent as a0, AXMMiniChatInboxHistoryComponent as a1, AXMMiniChatInboxPanelHostComponent as a2, AXMMiniChatLauncherComponent as a3, AXMMiniChatPanelComponent as a4, AXMMiniChatPanelService as a5, AXMShowCommentPopupCommand as a6, AXM_AI_MANAGEMENT_AGENT_ENTITY_NAME as a7, AXM_AI_MANAGEMENT_ASSIST_ENTITY_NAME as a8, AXM_AI_MANAGEMENT_MODULE_NAME as a9, axmAssistLastTranscriptLine as aA, axmAssistNormalizeFollowUpItemForConversation as aB, axmAssistNormalizeFollowUpItemsForConversation as aC, axmAssistPersistedMessageLooksComplete as aD, axmAssistResolveFollowUpCommandName as aE, axmAssistStarterPromptChipItems as aF, axmAssistUserFacingPayloadLine as aG, axmAssistUserVisibleItemsForLine as aH, axmAssistWidgetNodeDedupeKey as aI, axmBuildAiChatConversationMetadata as aJ, axmBuildAssistPeerParticipantFromCreateData as aK, axmBuildAssistPeerParticipantFromId as aL, axmBuildAssistTranscriptLinePayload as aM, axmBuildAutoTitleFromUserText as aN, axmBuildEntityChatConversationMetadata as aO, axmChatAiPeerParticipantId as aP, axmChatAiTargetAvatarUrl as aQ, axmChatAiTargetDisplayDescription as aR, axmChatAiTargetDisplayName as aS, axmChatAiTargetShortcutDescriptionKey as aT, axmCoerceDate as aU, axmCoerceTimestampMs as aV, axmComputeConversationUnreadCount as aW, axmConversationIsEntityChat as aX, axmConversationMatchesEntity as aY, axmExtractAssistIdFromMetadata as aZ, axmExtractAssistSnapshotFromMetadata as a_, AXM_ASSIST_DEFAULT_RESOLVER_PORT as aa, AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE as ab, AXM_CHAT_ASSIST_CATALOG_PORT as ac, AXM_CHAT_EMPTY_STATE_COMPONENT as ad, AXM_CHAT_SIDEBAR_ACTION_PROVIDER as ae, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_HANDLERS as af, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_KEY as ag, AXM_CONVERSATION_CHAT_ATTACHMENT_CATEGORY as ah, AXM_CONVERSATION_CHAT_ATTACHMENT_REF_TYPE as ai, AXM_CONVERSATION_TAB_BOT as aj, AXM_MINI_CHAT_INBOX_CONVERSATION_FILTER as ak, AXM_MINI_CHAT_INBOX_SESSION_KEY as al, AXPCommentWidget as am, COMMENTS_PAGE_COMPONENT_KEY as an, CONVERSATION_AFTER_MESSAGE_SENT_COMMAND as ao, CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND as ap, CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND as aq, CONVERSATION_OPEN_CHAT_COMMAND as ar, CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND as as, CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND as at, CONVERSATION_START_ASSIST_CHAT_COMMAND as au, CONVERSATION_START_DIRECT_CHAT_COMMAND as av, CONVERSATION_SYNC_READ_STATE_COMMAND as aw, axmApplyAnswerTextToAssistPayloadLine as ax, axmAssistFollowUpItemsFromUnknown as ay, axmAssistHasFinalizeMetadata as az, AXM_CONVERSATION_REGULAR_AUTO_REPLY_PORT as b, axmExtractEntityRefFromMetadata as b0, axmExtractModelEntityIdFromMetadata as b1, axmExtractTextFromPayload as b2, axmFilterChatAiTargets as b3, axmHydrateRealtimeConversationMessage as b4, axmIsAssistBotConversation as b5, axmIsAssistPeerParticipant as b6, axmIsAssistRetryableStatus as b7, axmIsAssistStreamingMessage as b8, axmIsAssistStreamingStatus as b9, axmIsAssistTerminalStatus as ba, axmIsUnsupportedLegacyAgentAssistConversation as bb, axmLoadChatAiTargets as bc, axmMessageCountsTowardUnread as bd, axmMessageEntityToMessage as be, axmNormalizeAssistTranscriptForChatUi as bf, axmNormalizeAssistTranscriptLineResponses as bg, axmParseAssistTranscriptLinePayload as bh, axmReadAssistResponseError as bi, axmReadAssistResponseStatus as bj, axmReadPlainTextMessagePayload as bk, axmReadReplyToUserMessageId as bl, axmResolveAssistFinalAnswerText as bm, axmResolveChatAiTargetText as bn, axmRoomEntityToConversation as bo, axmRoomWithAssistPeerDisplayName as bp, axmSanitizeAssistUserAnswerText as bq, axmShouldPreferPersistedAssistOverLiveCache as br, axmShowCommentPopupCommandDefinition as bs, axmSortMessagesNewestFirst as bt, axmSyncAssistPeerDisplayName as bu, axmUserRowToParticipant as bv, commentsPlugin as bw, createConversationServiceSessionAdapter as bx, persistChatAttachment as by, axmConversationHasAiChat$1 as c, AXMConversationFocusService as d, AXMConversationInAppNotificationSyncService as e, buildConversationChatInAppCorrelationPrefix as f, AXMCommentComponent as g, axmResolveConversationListAvatar as h, axmEnsureChatCallRtcReady as i, axmOpenChatCallSessionDialog as j, AXMChatUserApi as k, AXMChatEntityConversationApi as l, AXMChatConversationApi as m, AXMChatCallRtcService as n, AXMChatCallRtcSignalInboxService as o, AXMChatCallActiveSessionService as p, AXMChatCallEventsService as q, AXMConversationRealtimeBus as r, axmReadChatCallLog as s, axmBuildChatCallLogMessage as t, axmReadChatCallMediaContextIssue as u, AXM_CHAT_CALL_RTC_PROVIDERS as v, axmReadAssistAiTranscript as w, axmReadAssistAiTranscriptRaw as x, axmAssistSegmentDirection as y, axmParseAssistTranscriptTextEnvelope as z };
14003
- //# sourceMappingURL=acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CDlDFzbl.mjs.map
14532
+ export { AXMCommentWidgetViewComponent as $, AXMConversationEntityStoreService as A, AXM_CHAT_CALL_RTC_PROVIDERS as B, axmReadAssistAiTranscript as C, axmReadAssistAiTranscriptRaw as D, axmAssistSegmentDirection as E, axmParseAssistTranscriptTextEnvelope as F, axmAssistWidgetNodeFromUnknown as G, axmPartitionAssistAnswerText as H, axmSyntheticEmbedMessage as I, AXMNodeMessageRendererComponent as J, AXMAssistBotFileLineComponent as K, AXMAssistSuggestionChipsComponent as L, AXMAddReactionCommand as M, AXMChatComponent as N, AXMChatEntityConversationFocusHandler as O, AXMChatEntityConversationRoomQueryService as P, AXMChatEntityMessageApi as Q, AXMChatEntityRealtimeApi as R, AXMChatEntityUserApi as S, AXMChatMessageApi as T, AXMChatRealtimeApi as U, AXMCommentManagementService as V, AXMCommentPopupComponent as W, AXMCommentRealtimeService as X, AXMCommentRealtimeServiceImpl as Y, AXMCommentService as Z, AXMCommentServiceImpl as _, AXM_CONVERSATION_ASSIST_RESPONSE_PORT as a, axmComputeConversationUnreadCount as a$, AXMConversationAssistBackgroundOperationHandler as a0, AXMConversationModule as a1, AXMEntityChatService as a2, AXMMiniChatComponent as a3, AXMMiniChatHeaderSlotComponent as a4, AXMMiniChatHistoryComponent as a5, AXMMiniChatInboxHistoryComponent as a6, AXMMiniChatInboxPanelHostComponent as a7, AXMMiniChatLauncherComponent as a8, AXMMiniChatPanelComponent as a9, CONVERSATION_START_DIRECT_CHAT_COMMAND as aA, CONVERSATION_SYNC_READ_STATE_COMMAND as aB, axmApplyAnswerTextToAssistPayloadLine as aC, axmAssistFollowUpItemsFromUnknown as aD, axmAssistHasFinalizeMetadata as aE, axmAssistLastTranscriptLine as aF, axmAssistNormalizeFollowUpItemForConversation as aG, axmAssistNormalizeFollowUpItemsForConversation as aH, axmAssistPersistedMessageLooksComplete as aI, axmAssistResolveFollowUpCommandName as aJ, axmAssistStarterPromptChipItems as aK, axmAssistUserFacingPayloadLine as aL, axmAssistUserVisibleItemsForLine as aM, axmAssistWidgetNodeDedupeKey as aN, axmBuildAiChatConversationMetadata as aO, axmBuildAssistPeerParticipantFromCreateData as aP, axmBuildAssistPeerParticipantFromId as aQ, axmBuildAssistTranscriptLinePayload as aR, axmBuildAutoTitleFromUserText as aS, axmBuildEntityChatConversationMetadata as aT, axmChatAiPeerParticipantId as aU, axmChatAiTargetAvatarUrl as aV, axmChatAiTargetDisplayDescription as aW, axmChatAiTargetDisplayName as aX, axmChatAiTargetShortcutDescriptionKey as aY, axmCoerceDate as aZ, axmCoerceTimestampMs as a_, AXMMiniChatPanelService as aa, AXMShowCommentPopupCommand as ab, AXM_AI_MANAGEMENT_AGENT_ENTITY_NAME as ac, AXM_AI_MANAGEMENT_ASSIST_ENTITY_NAME as ad, AXM_AI_MANAGEMENT_MODULE_NAME as ae, AXM_ASSIST_DEFAULT_RESOLVER_PORT as af, AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE as ag, AXM_CHAT_ASSIST_CATALOG_PORT as ah, AXM_CHAT_EMPTY_STATE_COMPONENT as ai, AXM_CHAT_SIDEBAR_ACTION_PROVIDER as aj, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_HANDLERS as ak, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_KEY as al, AXM_CONVERSATION_CHAT_ATTACHMENT_CATEGORY as am, AXM_CONVERSATION_CHAT_ATTACHMENT_REF_TYPE as an, AXM_CONVERSATION_TAB_BOT as ao, AXM_MINI_CHAT_INBOX_CONVERSATION_FILTER as ap, AXM_MINI_CHAT_INBOX_SESSION_KEY as aq, AXPCommentWidget as ar, COMMENTS_PAGE_COMPONENT_KEY as as, CONVERSATION_AFTER_MESSAGE_SENT_COMMAND as at, CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND as au, CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND as av, CONVERSATION_OPEN_CHAT_COMMAND as aw, CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND as ax, CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND as ay, CONVERSATION_START_ASSIST_CHAT_COMMAND as az, AXM_CONVERSATION_REGULAR_AUTO_REPLY_PORT as b, axmConversationIsEntityChat as b0, axmConversationMatchesEntity as b1, axmExtractAssistIdFromMetadata as b2, axmExtractAssistSnapshotFromMetadata as b3, axmExtractDirectAgentIdFromMetadata as b4, axmExtractEntityRefFromMetadata as b5, axmExtractModelEntityIdFromMetadata as b6, axmExtractTextFromPayload as b7, axmFilterChatAiTargets as b8, axmHydrateRealtimeConversationMessage as b9, axmSyncAssistPeerDisplayName as bA, axmUserRowToParticipant as bB, commentsPlugin as bC, createConversationServiceSessionAdapter as bD, persistChatAttachment as bE, axmIsAssistBotConversation as ba, axmIsAssistPeerParticipant as bb, axmIsAssistResponseMessage as bc, axmIsAssistRetryableStatus as bd, axmIsAssistStreamingMessage as be, axmIsAssistStreamingStatus as bf, axmIsAssistTerminalStatus as bg, axmIsUnsupportedLegacyAgentAssistConversation as bh, axmLoadChatAiTargets as bi, axmMessageEntityToMessage as bj, axmNormalizeAssistTranscriptForChatUi as bk, axmNormalizeAssistTranscriptLineResponses as bl, axmParseAssistTranscriptLinePayload as bm, axmPreferLocalUnreadCount as bn, axmReadAssistResponseError as bo, axmReadAssistResponseStatus as bp, axmReadPlainTextMessagePayload as bq, axmReadReplyToUserMessageId as br, axmResolveAssistFinalAnswerText as bs, axmResolveChatAiTargetText as bt, axmRoomEntityToConversation as bu, axmRoomWithAssistPeerDisplayName as bv, axmSanitizeAssistUserAnswerText as bw, axmShouldPreferPersistedAssistOverLiveCache as bx, axmShowCommentPopupCommandDefinition as by, axmSortMessagesNewestFirst as bz, axmConversationHasAiChat$1 as c, AXMConversationFocusService as d, AXMConversationInAppNotificationSyncService as e, axmMessageCountsTowardUnread as f, buildConversationChatInAppCorrelationPrefix as g, AXMCommentComponent as h, AXMChatCallActiveSessionService as i, axmResolveConversationListAvatar as j, axmEnsureChatCallRtcReady as k, axmOpenChatCallSessionDialog as l, AXMChatEmptyStateHostComponent as m, AXMChatUserApi as n, AXMChatEntityConversationApi as o, AXMChatConversationApi as p, AXMChatCallRtcService as q, AXMChatCallRtcSignalInboxService as r, AXMChatCallEventsService as s, AXMConversationRealtimeBus as t, axmReadChatCallLog as u, axmShouldForkPrivateToGroup as v, axmIsConversationParticipant as w, axmBuildChatCallLogMessage as x, axmMatchesForkedGroupForCall as y, axmReadChatCallMediaContextIssue as z };
14533
+ //# sourceMappingURL=acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-XTzQQhii.mjs.map