@acorex/modules 21.0.0-next.45 → 21.0.0-next.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{acorex-modules-ai-management-agent.entity-D6-0_Ms3.mjs → acorex-modules-ai-management-agent.entity-Bnt9zkci.mjs} +15 -1
- package/fesm2022/acorex-modules-ai-management-agent.entity-Bnt9zkci.mjs.map +1 -0
- package/fesm2022/acorex-modules-ai-management.mjs +53 -165
- package/fesm2022/acorex-modules-ai-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-common-search-popup.component-BbRyjGia.mjs → acorex-modules-common-search-popup.component-CVuE0xgM.mjs} +14 -7
- package/fesm2022/acorex-modules-common-search-popup.component-CVuE0xgM.mjs.map +1 -0
- package/fesm2022/acorex-modules-common.mjs +2 -2
- package/fesm2022/{acorex-modules-conversation-acorex-modules-conversation-BJU2_R9O.mjs → acorex-modules-conversation-acorex-modules-conversation-F7nQo1GU.mjs} +749 -335
- package/fesm2022/acorex-modules-conversation-acorex-modules-conversation-F7nQo1GU.mjs.map +1 -0
- package/fesm2022/acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BB5Uyydt.mjs +287 -0
- package/fesm2022/acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BB5Uyydt.mjs.map +1 -0
- package/fesm2022/{acorex-modules-conversation-comments-page.component-Bg6m7UTG.mjs → acorex-modules-conversation-comments-page.component-QnDogSDy.mjs} +2 -2
- package/fesm2022/{acorex-modules-conversation-comments-page.component-Bg6m7UTG.mjs.map → acorex-modules-conversation-comments-page.component-QnDogSDy.mjs.map} +1 -1
- package/fesm2022/acorex-modules-conversation-start-assist-chat.command-DRlWzEDp.mjs +45 -0
- package/fesm2022/acorex-modules-conversation-start-assist-chat.command-DRlWzEDp.mjs.map +1 -0
- package/fesm2022/acorex-modules-conversation.mjs +1 -1
- package/fesm2022/{acorex-modules-dashboard-management-acorex-modules-dashboard-management-D11VudG8.mjs → acorex-modules-dashboard-management-acorex-modules-dashboard-management-kk0CINL1.mjs} +5 -5
- package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-kk0CINL1.mjs.map +1 -0
- package/fesm2022/{acorex-modules-dashboard-management-index-DB3Uh1wL.mjs → acorex-modules-dashboard-management-index-Bhm8mAON.mjs} +2 -2
- package/fesm2022/{acorex-modules-dashboard-management-index-DB3Uh1wL.mjs.map → acorex-modules-dashboard-management-index-Bhm8mAON.mjs.map} +1 -1
- package/fesm2022/acorex-modules-dashboard-management.mjs +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +8 -5
- package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-person-core.mjs +4 -0
- package/fesm2022/acorex-modules-person-core.mjs.map +1 -1
- package/fesm2022/{acorex-modules-platform-dev-tools-menu.provider-BFueKnuF.mjs → acorex-modules-platform-dev-tools-menu.provider-DDjYvQr7.mjs} +6 -2
- package/fesm2022/acorex-modules-platform-dev-tools-menu.provider-DDjYvQr7.mjs.map +1 -0
- package/fesm2022/acorex-modules-platform-dev-tools.mjs +42 -5
- package/fesm2022/acorex-modules-platform-dev-tools.mjs.map +1 -1
- package/fesm2022/acorex-modules-project-management.mjs +33 -3
- package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +12 -8
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-task-management-acorex-modules-task-management-DDUq9FpA.mjs → acorex-modules-task-management-acorex-modules-task-management-BL2IOcx3.mjs} +63 -6
- package/fesm2022/acorex-modules-task-management-acorex-modules-task-management-BL2IOcx3.mjs.map +1 -0
- package/fesm2022/{acorex-modules-task-management-task-board.page-C6j-_aSD.mjs → acorex-modules-task-management-task-board.page-DUIHtqnr.mjs} +138 -68
- package/fesm2022/acorex-modules-task-management-task-board.page-DUIHtqnr.mjs.map +1 -0
- package/fesm2022/acorex-modules-task-management.mjs +1 -1
- package/fesm2022/{acorex-modules-workflow-management-activity-command-configurator-widget-edit.component-Dj6LkQeZ.mjs → acorex-modules-workflow-management-activity-command-configurator-widget-edit.component-CYyr1kQk.mjs} +3 -3
- package/fesm2022/{acorex-modules-workflow-management-activity-command-configurator-widget-edit.component-Dj6LkQeZ.mjs.map → acorex-modules-workflow-management-activity-command-configurator-widget-edit.component-CYyr1kQk.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-workflow-management-index-Eh5DDK-V.mjs → acorex-modules-workflow-management-index-DC_9M9dk.mjs} +3 -3
- package/fesm2022/{acorex-modules-workflow-management-index-Eh5DDK-V.mjs.map → acorex-modules-workflow-management-index-DC_9M9dk.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-workflow-management-index-V4OesZTq.mjs → acorex-modules-workflow-management-index-jin24dmb.mjs} +3 -3
- package/fesm2022/{acorex-modules-workflow-management-index-V4OesZTq.mjs.map → acorex-modules-workflow-management-index-jin24dmb.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-workflow-management-workflow-instance.entity-B_V3uMSI.mjs → acorex-modules-workflow-management-workflow-instance.entity-BnKT3Wgh.mjs} +2 -2
- package/fesm2022/{acorex-modules-workflow-management-workflow-instance.entity-B_V3uMSI.mjs.map → acorex-modules-workflow-management-workflow-instance.entity-BnKT3Wgh.mjs.map} +1 -1
- package/fesm2022/acorex-modules-workflow-management.mjs +11 -20
- package/fesm2022/acorex-modules-workflow-management.mjs.map +1 -1
- package/package.json +2 -2
- package/types/acorex-modules-ai-management.d.ts +19 -22
- package/types/acorex-modules-conversation.d.ts +31 -39
- package/types/acorex-modules-dashboard-management.d.ts +2 -2
- package/types/acorex-modules-platform-dev-tools.d.ts +16 -2
- package/types/acorex-modules-report-management.d.ts +8 -1
- package/types/acorex-modules-task-management.d.ts +26 -1
- package/types/acorex-modules-workflow-management.d.ts +2 -3
- package/fesm2022/acorex-modules-ai-management-agent.entity-D6-0_Ms3.mjs.map +0 -1
- package/fesm2022/acorex-modules-common-search-popup.component-BbRyjGia.mjs.map +0 -1
- package/fesm2022/acorex-modules-conversation-acorex-modules-conversation-BJU2_R9O.mjs.map +0 -1
- package/fesm2022/acorex-modules-conversation-assist-delegated-agent-detail-popup.component-DX2JPckF.mjs +0 -324
- package/fesm2022/acorex-modules-conversation-assist-delegated-agent-detail-popup.component-DX2JPckF.mjs.map +0 -1
- package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-D11VudG8.mjs.map +0 -1
- package/fesm2022/acorex-modules-platform-dev-tools-menu.provider-BFueKnuF.mjs.map +0 -1
- package/fesm2022/acorex-modules-task-management-acorex-modules-task-management-DDUq9FpA.mjs.map +0 -1
- package/fesm2022/acorex-modules-task-management-task-board.page-C6j-_aSD.mjs.map +0 -1
- package/fesm2022/acorex-modules-workflow-management-workflow-task-popover.component-l37iXJIY.mjs +0 -362
- package/fesm2022/acorex-modules-workflow-management-workflow-task-popover.component-l37iXJIY.mjs.map +0 -1
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
import { AXConversationModule } from '@acorex/components/conversation';
|
|
2
2
|
import { AXPSessionService, AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
|
|
3
|
-
import { createAllQueryView, AXPEntityQueryType, AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, AXPFileStorageService, AXP_MENU_PROVIDER } from '@acorex/platform/common';
|
|
4
|
-
import { AXPDataGenerator, AXPPlatformScope, AXPDeviceService, AXP_MODULE_MANIFEST_PROVIDER } from '@acorex/platform/core';
|
|
3
|
+
import { createAllQueryView, AXPEntityQueryType, AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, AXPFileStorageService, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
|
|
4
|
+
import { AXPSystemActionType, AXPDataGenerator, AXPPlatformScope, AXPDeviceService, AXP_MODULE_MANIFEST_PROVIDER } from '@acorex/platform/core';
|
|
5
5
|
import { AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent, AXPUserAvatarComponent, AXPMarkdownViewerComponent, AXPMarkdownTemplateDirective, AXP_PAGE_COMPONENT_PROVIDER, AXP_TASK_BADGE_PROVIDERS } from '@acorex/platform/layout/components';
|
|
6
|
-
import { AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions,
|
|
6
|
+
import { AXPEntityDefinitionRegistryService, AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions, cloneLayoutArrays, ensureLayoutSection, ensureLayoutPropertyView, resolveEntityPluginDetailPageOrder, ensureListActions, actionExists, AXPEntityService, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
7
7
|
import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
8
8
|
import * as i5 from '@angular/common';
|
|
9
9
|
import { CommonModule, AsyncPipe, DecimalPipe, DatePipe } from '@angular/common';
|
|
10
|
+
import { provideCommandSetups } from '@acorex/platform/runtime';
|
|
10
11
|
import * as i0 from '@angular/core';
|
|
11
|
-
import { Injectable, NgModule,
|
|
12
|
+
import { inject, Injectable, NgModule, output, signal, viewChild, computed, effect, untracked, ChangeDetectionStrategy, Component, input, afterNextRender, DestroyRef, ElementRef, ViewEncapsulation, Injector, importProvidersFrom } from '@angular/core';
|
|
12
13
|
import { Router, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
|
|
14
|
+
import { sortBy } from 'lodash-es';
|
|
15
|
+
import { RootConfig as RootConfig$1, axpAiChatMessagesFromProviderAssistant, axpAiParseDelegatedAgentResultSegmentsFromUnknown, axpAiChatTextMessage, AXPAiAssistChatModelCatalogService, axpAiParseSupervisorAgentToolName, axpAiChatMessageGetText, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiDelegatedAgentPromptPreview, axpAiChatToolOrAgentResultBodyJson, axpAiDelegatedAgentOutcomeResponsesPlainText } from '@acorex/modules/ai-management';
|
|
16
|
+
import { AXConversationService, AXNewConversationDialogComponent, AXConversationContainerDirective, AXSidebarComponent, AXInfoBarComponent, AXMessageListComponent, AXComposerComponent, AXUserApi, AXConversationApi, AXMessageApi, AXRealtimeApi, conversationSharedStorage, axConversationIndexedDbStorage, AXImageRendererComponent, AXTextRendererComponent, provideConversation, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_INFO_BAR_INFO_ACTION, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AXComposerService, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_VOICE_RENDERER, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_STICKER_RENDERER } from '@acorex/components/conversation2';
|
|
17
|
+
import { AXToastService } from '@acorex/components/toast';
|
|
18
|
+
import * as i3$1 from '@acorex/core/translation';
|
|
19
|
+
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
13
20
|
import * as i1$3 from '@acorex/platform/layout/widget-core';
|
|
14
21
|
import { AXPWidgetsCatalog, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
15
|
-
import * as i1$
|
|
22
|
+
import * as i1$6 from '@acorex/platform/workflow';
|
|
16
23
|
import { AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
17
24
|
import { AXMNotificationConnectorService, AXP_NOTIFICATION_DEFINITION_PROVIDER } from '@acorex/modules/notification-management';
|
|
18
25
|
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
19
26
|
import { Subject, map, filter, merge, auditTime } from 'rxjs';
|
|
20
27
|
import * as i2 from '@acorex/components/button';
|
|
21
28
|
import { AXButtonModule, AXButtonComponent } from '@acorex/components/button';
|
|
22
|
-
import { AXConversationService, AXNewConversationDialogComponent, AXConversationContainerDirective, AXSidebarComponent, AXInfoBarComponent, AXMessageListComponent, AXComposerComponent, AXUserApi, AXConversationApi, AXMessageApi, AXRealtimeApi, conversationSharedStorage, axConversationIndexedDbStorage, AXImageRendererComponent, AXTextRendererComponent, provideConversation, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_INFO_BAR_INFO_ACTION, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AXComposerService, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_VOICE_RENDERER, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_STICKER_RENDERER } from '@acorex/components/conversation2';
|
|
23
29
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
24
30
|
import * as i1$1 from '@acorex/components/decorators';
|
|
25
31
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
26
|
-
import * as i2$1 from '@acorex/core/translation';
|
|
27
|
-
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
28
32
|
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent } from '@acorex/platform/layout/views';
|
|
29
33
|
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
30
34
|
import * as i3 from '@acorex/components/dropdown';
|
|
31
35
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
32
36
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
33
|
-
import { AXToastService } from '@acorex/components/toast';
|
|
34
|
-
import { RootConfig as RootConfig$1, axpAiParseDelegatedAgentResultSegmentsFromUnknown, axpAiChatTextMessage, AXPAiAssistChatModelCatalogService, axpAiParseSupervisorAgentToolName, axpAiChatMessageGetText, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiDelegatedAgentPromptPreview, axpAiChatToolOrAgentResultBodyJson, axpAiDelegatedAgentOutcomeResponsesPlainText } from '@acorex/modules/ai-management';
|
|
35
37
|
import * as i1 from '@angular/forms';
|
|
36
38
|
import { FormsModule } from '@angular/forms';
|
|
37
39
|
import { AXFabComponent, AXFabItemComponent } from '@acorex/components/fab';
|
|
@@ -52,15 +54,15 @@ import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
|
52
54
|
import { AXFormModule } from '@acorex/components/form';
|
|
53
55
|
import * as i6 from '@acorex/components/loading';
|
|
54
56
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
55
|
-
import * as i2$
|
|
57
|
+
import * as i2$1 from '@acorex/components/skeleton';
|
|
56
58
|
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
57
59
|
import { AXToolBarModule } from '@acorex/components/toolbar';
|
|
58
60
|
import * as i9 from '@acorex/core/format';
|
|
59
61
|
import { AXFormatModule } from '@acorex/core/format';
|
|
60
62
|
import { AXPLayoutBuilderService, AXPLayoutRendererComponent } from '@acorex/platform/layout/builder';
|
|
61
|
-
import * as i1$
|
|
63
|
+
import * as i1$5 from '@acorex/cdk/accordion';
|
|
62
64
|
import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
|
|
63
|
-
import * as
|
|
65
|
+
import * as i1$4 from '@acorex/components/code-editor';
|
|
64
66
|
import { AXCodeEditorModule } from '@acorex/components/code-editor';
|
|
65
67
|
|
|
66
68
|
const config = {
|
|
@@ -98,6 +100,298 @@ const RootConfig = {
|
|
|
98
100
|
},
|
|
99
101
|
};
|
|
100
102
|
|
|
103
|
+
/** Starts a new bot conversation with the given AI assist model. */
|
|
104
|
+
const CONVERSATION_START_ASSIST_CHAT_COMMAND = 'Conversation:StartAssistChat';
|
|
105
|
+
|
|
106
|
+
//#region ---- Imports ----
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region ---- Participant & metadata ----
|
|
109
|
+
/** Synthetic bot participant id for assist or agent-as-assist chats. */
|
|
110
|
+
function axmChatAiPeerParticipantId(catalogId) {
|
|
111
|
+
return `assist-${catalogId.trim()}`;
|
|
112
|
+
}
|
|
113
|
+
/** Conversation metadata for starting an AI chat from a picker row. */
|
|
114
|
+
function axmBuildAiChatConversationMetadata(row) {
|
|
115
|
+
if (row.kind === 'agent') {
|
|
116
|
+
return { directAgentId: row.id };
|
|
117
|
+
}
|
|
118
|
+
return { assistId: row.id };
|
|
119
|
+
}
|
|
120
|
+
/** True when conversation metadata targets an assist row or a direct agent-as-assist chat. */
|
|
121
|
+
function axmConversationHasAiChat(conversation) {
|
|
122
|
+
const meta = conversation?.metadata;
|
|
123
|
+
if (!meta) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const assistId = meta['assistId'];
|
|
127
|
+
if (typeof assistId === 'string' && assistId.trim()) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
const directAgentId = meta['directAgentId'];
|
|
131
|
+
return typeof directAgentId === 'string' && directAgentId.trim().length > 0;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Loads assist rows plus agents flagged with `isAssist` for Conversation AI chat pickers.
|
|
135
|
+
*/
|
|
136
|
+
async function axmLoadChatAiTargets(entityRegistry) {
|
|
137
|
+
const [assists, agents] = await Promise.all([
|
|
138
|
+
axmQueryEntityList(entityRegistry, RootConfig$1.entities.assist.name),
|
|
139
|
+
axmQueryEntityList(entityRegistry, RootConfig$1.entities.agent.name),
|
|
140
|
+
]);
|
|
141
|
+
const assistRows = assists.map((raw) => ({
|
|
142
|
+
id: String(raw['id'] ?? ''),
|
|
143
|
+
name: String(raw['name'] ?? ''),
|
|
144
|
+
title: raw['title'],
|
|
145
|
+
description: raw['description'],
|
|
146
|
+
professionImageUrl: typeof raw['professionImageUrl'] === 'string' ? raw['professionImageUrl'] : undefined,
|
|
147
|
+
kind: 'assist',
|
|
148
|
+
}));
|
|
149
|
+
const agentRows = agents
|
|
150
|
+
.filter((raw) => raw['isAssist'] === true)
|
|
151
|
+
.map((raw) => ({
|
|
152
|
+
id: String(raw['id'] ?? ''),
|
|
153
|
+
name: String(raw['name'] ?? ''),
|
|
154
|
+
title: raw['title'],
|
|
155
|
+
description: raw['description'],
|
|
156
|
+
kind: 'agent',
|
|
157
|
+
}));
|
|
158
|
+
return [...assistRows, ...agentRows]
|
|
159
|
+
.filter((row) => row.id.trim().length > 0)
|
|
160
|
+
.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region ---- Display & filter (dialog + global search) ----
|
|
164
|
+
/** Resolves ML or plain string for search/display. */
|
|
165
|
+
function axmResolveChatAiTargetText(resolveMl, value) {
|
|
166
|
+
if (!value) {
|
|
167
|
+
return '';
|
|
168
|
+
}
|
|
169
|
+
if (typeof value === 'string') {
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
return resolveMl(value) ?? '';
|
|
173
|
+
}
|
|
174
|
+
function axmChatAiTargetDisplayName(resolveMl, row) {
|
|
175
|
+
return axmResolveChatAiTargetText(resolveMl, row.title).trim() || row.name.trim() || row.id;
|
|
176
|
+
}
|
|
177
|
+
function axmChatAiTargetDisplayDescription(resolveMl, row) {
|
|
178
|
+
if (!row.description) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
const text = axmResolveChatAiTargetText(resolveMl, row.description).trim();
|
|
182
|
+
return text || undefined;
|
|
183
|
+
}
|
|
184
|
+
function axmChatAiTargetAvatarUrl(row) {
|
|
185
|
+
const url = row.professionImageUrl?.trim();
|
|
186
|
+
return url ? url : null;
|
|
187
|
+
}
|
|
188
|
+
/** Fallback i18n key for rows with no catalog description. */
|
|
189
|
+
function axmChatAiTargetShortcutDescriptionKey(row) {
|
|
190
|
+
return row.kind === 'agent'
|
|
191
|
+
? '@conversation:search.assist.shortcut-description-agent'
|
|
192
|
+
: '@conversation:search.assist.shortcut-description';
|
|
193
|
+
}
|
|
194
|
+
/** Same filter as {@link AXMChatWithAssistDialogComponent} target list search. */
|
|
195
|
+
function axmFilterChatAiTargets(resolveMl, rows, query) {
|
|
196
|
+
const q = query.trim().toLowerCase();
|
|
197
|
+
if (!q) {
|
|
198
|
+
return rows;
|
|
199
|
+
}
|
|
200
|
+
return rows.filter((r) => {
|
|
201
|
+
const titleText = axmResolveChatAiTargetText(resolveMl, r.title).toLowerCase();
|
|
202
|
+
return (r.name.toLowerCase().includes(q) ||
|
|
203
|
+
titleText.includes(q) ||
|
|
204
|
+
axmResolveChatAiTargetText(resolveMl, r.description).toLowerCase().includes(q));
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region ---- Entity list query ----
|
|
209
|
+
async function axmQueryEntityList(entityRegistry, entityName) {
|
|
210
|
+
const entity = await entityRegistry.resolve(RootConfig$1.module.name, entityName);
|
|
211
|
+
const execute = entity.queries?.list?.execute;
|
|
212
|
+
if (!execute) {
|
|
213
|
+
throw new Error(`${entityName} entity has no list query.`);
|
|
214
|
+
}
|
|
215
|
+
const res = await execute({
|
|
216
|
+
skip: 0,
|
|
217
|
+
take: 500,
|
|
218
|
+
sort: [{ name: 'name', dir: 'asc' }],
|
|
219
|
+
});
|
|
220
|
+
return res.items ?? [];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
//#region ---- Imports ----
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region ---- Service ----
|
|
226
|
+
/**
|
|
227
|
+
* Starts bot conversations from AI target rows (assists + agents with `isAssist`),
|
|
228
|
+
* shared by global search shortcuts and {@link AXMConversationStartAssistChatCommand}.
|
|
229
|
+
*/
|
|
230
|
+
class AXMChatAssistLauncherService {
|
|
231
|
+
constructor() {
|
|
232
|
+
this.conversationService = inject(AXConversationService);
|
|
233
|
+
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
234
|
+
this.translationService = inject(AXTranslationService);
|
|
235
|
+
this.sessionService = inject(AXPSessionService);
|
|
236
|
+
this.router = inject(Router);
|
|
237
|
+
this.toastService = inject(AXToastService);
|
|
238
|
+
this.targetsCache = null;
|
|
239
|
+
this.loadPromise = null;
|
|
240
|
+
}
|
|
241
|
+
async loadTargets(force = false) {
|
|
242
|
+
if (!force && this.targetsCache) {
|
|
243
|
+
return this.targetsCache;
|
|
244
|
+
}
|
|
245
|
+
if (!force && this.loadPromise) {
|
|
246
|
+
return this.loadPromise;
|
|
247
|
+
}
|
|
248
|
+
this.loadPromise = axmLoadChatAiTargets(this.entityRegistry);
|
|
249
|
+
try {
|
|
250
|
+
this.targetsCache = await this.loadPromise;
|
|
251
|
+
return this.targetsCache;
|
|
252
|
+
}
|
|
253
|
+
finally {
|
|
254
|
+
this.loadPromise = null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
displayName(row) {
|
|
258
|
+
return axmChatAiTargetDisplayName(this.#resolveMl.bind(this), row);
|
|
259
|
+
}
|
|
260
|
+
displayDescription(row) {
|
|
261
|
+
return axmChatAiTargetDisplayDescription(this.#resolveMl.bind(this), row);
|
|
262
|
+
}
|
|
263
|
+
targetAvatarUrl(row) {
|
|
264
|
+
return axmChatAiTargetAvatarUrl(row);
|
|
265
|
+
}
|
|
266
|
+
filterTargets(rows, query) {
|
|
267
|
+
return axmFilterChatAiTargets(this.#resolveMl.bind(this), rows, query);
|
|
268
|
+
}
|
|
269
|
+
async startAssistChat(options) {
|
|
270
|
+
const targetId = (options.targetId ?? options.assistId)?.trim();
|
|
271
|
+
if (!targetId) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const rows = await this.loadTargets();
|
|
275
|
+
const row = rows.find((r) => r.id === targetId && (!options.targetKind || r.kind === options.targetKind)) ??
|
|
276
|
+
rows.find((r) => r.id === targetId);
|
|
277
|
+
if (!row) {
|
|
278
|
+
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
279
|
+
this.toastService.danger(message);
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
const conversation = await this.#createTargetConversation(row);
|
|
284
|
+
await this.conversationService.selectConversation(conversation.id);
|
|
285
|
+
if (options.navigate !== false) {
|
|
286
|
+
await this.router.navigate([this.#applicationRouteSegment(), 'chat', conversation.id]);
|
|
287
|
+
}
|
|
288
|
+
return { conversation };
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
console.error('Failed to start AI chat:', error);
|
|
292
|
+
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
293
|
+
this.toastService.danger(message);
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async #createTargetConversation(row) {
|
|
298
|
+
const participantId = axmChatAiPeerParticipantId(row.id);
|
|
299
|
+
const title = this.displayName(row);
|
|
300
|
+
const avatar = this.targetAvatarUrl(row);
|
|
301
|
+
return this.conversationService.createConversation([participantId], 'bot', {
|
|
302
|
+
title,
|
|
303
|
+
...(avatar ? { avatar } : {}),
|
|
304
|
+
icon: 'fa-solid fa-robot',
|
|
305
|
+
metadata: axmBuildAiChatConversationMetadata(row),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
#resolveMl(value) {
|
|
309
|
+
return this.translationService.resolve(value);
|
|
310
|
+
}
|
|
311
|
+
#applicationRouteSegment() {
|
|
312
|
+
return this.sessionService.application?.name ?? 'platform';
|
|
313
|
+
}
|
|
314
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
315
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, providedIn: 'root' }); }
|
|
316
|
+
}
|
|
317
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, decorators: [{
|
|
318
|
+
type: Injectable,
|
|
319
|
+
args: [{ providedIn: 'root' }]
|
|
320
|
+
}] });
|
|
321
|
+
|
|
322
|
+
/** Search group key — AI chat targets (assists + agent-as-assist), not conversation history. */
|
|
323
|
+
const AXM_CONVERSATION_ASSIST_SEARCH_GROUP = 'conversation-assist';
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region ---- Provider ----
|
|
326
|
+
/**
|
|
327
|
+
* Global search entries to start a new AI chat — same catalog as
|
|
328
|
+
* {@link AXMChatWithAssistDialogComponent} / {@link AXMChatSidebarNewActionsComponent}.
|
|
329
|
+
*
|
|
330
|
+
* Note: the shared global search popup only queries when the text length is > 2.
|
|
331
|
+
*/
|
|
332
|
+
class AXMConversationAssistSearchProvider {
|
|
333
|
+
constructor() {
|
|
334
|
+
this.launcher = inject(AXMChatAssistLauncherService);
|
|
335
|
+
}
|
|
336
|
+
async search(text) {
|
|
337
|
+
let rows;
|
|
338
|
+
try {
|
|
339
|
+
rows = await this.launcher.loadTargets();
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
console.error('Failed to load AI chat targets for shortcut search:', error);
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
345
|
+
const filtered = this.launcher.filterTargets(rows, text);
|
|
346
|
+
const sorted = sortBy(filtered, (row) => this.launcher.displayName(row).toLowerCase());
|
|
347
|
+
return sorted.map((row) => ({
|
|
348
|
+
id: row.id,
|
|
349
|
+
group: AXM_CONVERSATION_ASSIST_SEARCH_GROUP,
|
|
350
|
+
title: row.title,
|
|
351
|
+
description: row.description ?? axmChatAiTargetShortcutDescriptionKey(row),
|
|
352
|
+
icon: 'fa-solid fa-robot',
|
|
353
|
+
data: { id: row.id, name: row.name, kind: row.kind },
|
|
354
|
+
command: {
|
|
355
|
+
name: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
356
|
+
options: {
|
|
357
|
+
targetId: row.id,
|
|
358
|
+
targetKind: row.kind,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
}));
|
|
362
|
+
}
|
|
363
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
364
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider }); }
|
|
365
|
+
}
|
|
366
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider, decorators: [{
|
|
367
|
+
type: Injectable
|
|
368
|
+
}] });
|
|
369
|
+
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region ---- Provider ----
|
|
372
|
+
/** Search group for AI assist shortcut picker (not chat/conversation history). */
|
|
373
|
+
class AXMConversationAssistSearchDefinitionProvider {
|
|
374
|
+
async provide(context) {
|
|
375
|
+
context.addDefinition(AXM_CONVERSATION_ASSIST_SEARCH_GROUP, '@conversation:search.assist.group-title', AXM_CONVERSATION_ASSIST_SEARCH_GROUP, 'fa-solid fa-robot', 4, {
|
|
376
|
+
format: {
|
|
377
|
+
id: '{{id}}',
|
|
378
|
+
},
|
|
379
|
+
actions: [
|
|
380
|
+
{
|
|
381
|
+
name: 'start-assist-chat',
|
|
382
|
+
type: AXPSystemActionType.View,
|
|
383
|
+
priority: 'primary',
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
389
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider }); }
|
|
390
|
+
}
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, decorators: [{
|
|
392
|
+
type: Injectable
|
|
393
|
+
}] });
|
|
394
|
+
|
|
101
395
|
class AXMConversationTabService extends AXMEntityCrudServiceImpl {
|
|
102
396
|
}
|
|
103
397
|
class AXMConversationTabServiceImpl extends AXMConversationTabService {
|
|
@@ -922,6 +1216,12 @@ const AXPConversationMenuKeys = {
|
|
|
922
1216
|
Conversations: 'Conversation:Menu:Conversations',
|
|
923
1217
|
};
|
|
924
1218
|
|
|
1219
|
+
const AXMPermissionsKeys = {
|
|
1220
|
+
Conversation: {
|
|
1221
|
+
Management: 'Conversation:Permission:Management',
|
|
1222
|
+
},
|
|
1223
|
+
};
|
|
1224
|
+
|
|
925
1225
|
class AXMMenuProvider {
|
|
926
1226
|
constructor() {
|
|
927
1227
|
this.sessionService = inject(AXPSessionService);
|
|
@@ -937,6 +1237,9 @@ class AXMMenuProvider {
|
|
|
937
1237
|
priority: 30,
|
|
938
1238
|
icon: RootConfig.entities.room.icon,
|
|
939
1239
|
badgeKey: 'badge-chat',
|
|
1240
|
+
policy: {
|
|
1241
|
+
permissions: [AXMPermissionsKeys.Conversation.Management],
|
|
1242
|
+
},
|
|
940
1243
|
},
|
|
941
1244
|
]);
|
|
942
1245
|
}
|
|
@@ -947,9 +1250,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
947
1250
|
type: Injectable
|
|
948
1251
|
}] });
|
|
949
1252
|
|
|
1253
|
+
//#endregion
|
|
1254
|
+
//#region ---- Permission Definition Provider ----
|
|
950
1255
|
class AXMPermissionDefinitionProvider {
|
|
951
1256
|
async define(context) {
|
|
952
|
-
|
|
1257
|
+
const keys = AXMPermissionsKeys.Conversation;
|
|
1258
|
+
const modulePermissions = '@conversation:module.permissions';
|
|
1259
|
+
context
|
|
1260
|
+
.addGroup(RootConfig.module.name, `${modulePermissions}.title`, `${modulePermissions}.description`)
|
|
1261
|
+
.addPermission(keys.Management, `${modulePermissions}.manage.title`, `${modulePermissions}.manage.description`)
|
|
1262
|
+
.endPermission()
|
|
1263
|
+
.endGroup();
|
|
953
1264
|
}
|
|
954
1265
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
955
1266
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider }); }
|
|
@@ -1650,7 +1961,13 @@ class AXMChatEmptyAssistComposerComponent {
|
|
|
1650
1961
|
this.draftInput = viewChild('draftInput', ...(ngDevMode ? [{ debugName: "draftInput" }] : /* istanbul ignore next */ []));
|
|
1651
1962
|
this.selectedAssistLabel = computed(() => {
|
|
1652
1963
|
const selected = this.rows().find((row) => row.id === this.selectedAssistId());
|
|
1653
|
-
|
|
1964
|
+
if (!selected) {
|
|
1965
|
+
return '';
|
|
1966
|
+
}
|
|
1967
|
+
if (typeof selected.title === 'string') {
|
|
1968
|
+
return selected.title;
|
|
1969
|
+
}
|
|
1970
|
+
return this.translationService.resolve(selected.title) ?? selected.name;
|
|
1654
1971
|
}, ...(ngDevMode ? [{ debugName: "selectedAssistLabel" }] : /* istanbul ignore next */ []));
|
|
1655
1972
|
this.assistsLoadPromise = null;
|
|
1656
1973
|
void this.ensureAssistsLoaded();
|
|
@@ -1703,15 +2020,13 @@ class AXMChatEmptyAssistComposerComponent {
|
|
|
1703
2020
|
}
|
|
1704
2021
|
this.sending.set(true);
|
|
1705
2022
|
try {
|
|
1706
|
-
const participantId =
|
|
1707
|
-
const avatar = this.
|
|
2023
|
+
const participantId = axmChatAiPeerParticipantId(row.id);
|
|
2024
|
+
const avatar = this.targetAvatarUrl(row);
|
|
1708
2025
|
const conversation = await this.conversationService.createConversation([participantId], 'bot', {
|
|
1709
|
-
title: this.translationService.resolve(row.title),
|
|
2026
|
+
title: this.translationService.resolve(row.title) ?? row.name,
|
|
1710
2027
|
...(avatar ? { avatar } : {}),
|
|
1711
2028
|
icon: 'fa-solid fa-robot',
|
|
1712
|
-
metadata:
|
|
1713
|
-
assistId: row.id,
|
|
1714
|
-
},
|
|
2029
|
+
metadata: axmBuildAiChatConversationMetadata(row),
|
|
1715
2030
|
});
|
|
1716
2031
|
await this.conversationService.selectConversation(conversation.id);
|
|
1717
2032
|
const payload = { type: 'text', text };
|
|
@@ -1741,20 +2056,10 @@ class AXMChatEmptyAssistComposerComponent {
|
|
|
1741
2056
|
async loadAssistsFromApi() {
|
|
1742
2057
|
this.loading.set(true);
|
|
1743
2058
|
try {
|
|
1744
|
-
|
|
1745
|
-
const execute = entity.queries?.list?.execute;
|
|
1746
|
-
if (!execute) {
|
|
1747
|
-
throw new Error('Assist entity has no list query.');
|
|
1748
|
-
}
|
|
1749
|
-
const res = await execute({
|
|
1750
|
-
skip: 0,
|
|
1751
|
-
take: 500,
|
|
1752
|
-
sort: [{ name: 'name', dir: 'asc' }],
|
|
1753
|
-
});
|
|
1754
|
-
this.rows.set((res.items ?? []).map((raw) => this.normalizeRow(raw)));
|
|
2059
|
+
this.rows.set(await axmLoadChatAiTargets(this.entityRegistry));
|
|
1755
2060
|
}
|
|
1756
2061
|
catch (error) {
|
|
1757
|
-
console.error('Failed to load
|
|
2062
|
+
console.error('Failed to load AI chat targets (empty composer):', error);
|
|
1758
2063
|
const message = await this.translationService.translateAsync('@conversation:chat.empty-assist.errors.load-assists');
|
|
1759
2064
|
this.toastService.danger(message);
|
|
1760
2065
|
this.rows.set([]);
|
|
@@ -1763,15 +2068,7 @@ class AXMChatEmptyAssistComposerComponent {
|
|
|
1763
2068
|
this.loading.set(false);
|
|
1764
2069
|
}
|
|
1765
2070
|
}
|
|
1766
|
-
|
|
1767
|
-
const id = raw['id'];
|
|
1768
|
-
const name = raw['name'];
|
|
1769
|
-
const title = raw['title'];
|
|
1770
|
-
const description = raw['description'];
|
|
1771
|
-
const professionImageUrl = raw['professionImageUrl'];
|
|
1772
|
-
return { id, name, title, description, professionImageUrl };
|
|
1773
|
-
}
|
|
1774
|
-
assistAvatarUrl(row) {
|
|
2071
|
+
targetAvatarUrl(row) {
|
|
1775
2072
|
const avatarUrl = row.professionImageUrl?.trim();
|
|
1776
2073
|
return avatarUrl ? avatarUrl : null;
|
|
1777
2074
|
}
|
|
@@ -1826,7 +2123,7 @@ class AXMChatEmptyAssistComposerComponent {
|
|
|
1826
2123
|
</ax-button>
|
|
1827
2124
|
</div>
|
|
1828
2125
|
</div>
|
|
1829
|
-
`, isInline: true, styles: [".axm-chat-empty-assist-composer{width:min(100%,48rem);margin-inline:auto}.axm-chat-empty-assist-composer__caption{margin-bottom:3rem;text-align:center;font-size:clamp(1.9rem,3.4vw,2.7rem);line-height:1.15;font-weight:700;letter-spacing:-.02em}.axm-chat-empty-assist-composer__composer-row{display:flex;gap:.375rem;align-items:end;padding:.5rem;border-radius:2em;border:1px solid;border-color:rgba(var(--ax-sys-color-border-lighter-surface))}.axm-chat-empty-assist-composer__assist-text{display:inline-block;max-width:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-empty-assist-composer__textarea{resize:none;overflow:hidden;background:transparent;min-height:2.25rem;max-height:14rem;line-height:1.5;padding-block:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: i2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type:
|
|
2126
|
+
`, isInline: true, styles: [".axm-chat-empty-assist-composer{width:min(100%,48rem);margin-inline:auto}.axm-chat-empty-assist-composer__caption{margin-bottom:3rem;text-align:center;font-size:clamp(1.9rem,3.4vw,2.7rem);line-height:1.15;font-weight:700;letter-spacing:-.02em}.axm-chat-empty-assist-composer__composer-row{display:flex;gap:.375rem;align-items:end;padding:.5rem;border-radius:2em;border:1px solid;border-color:rgba(var(--ax-sys-color-border-lighter-surface))}.axm-chat-empty-assist-composer__assist-text{display:inline-block;max-width:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axm-chat-empty-assist-composer__textarea{resize:none;overflow:hidden;background:transparent;min-height:2.25rem;max-height:14rem;line-height:1.5;padding-block:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: i2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1830
2127
|
}
|
|
1831
2128
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatEmptyAssistComposerComponent, decorators: [{
|
|
1832
2129
|
type: Component,
|
|
@@ -1893,7 +2190,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1893
2190
|
|
|
1894
2191
|
class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
1895
2192
|
constructor() {
|
|
1896
|
-
super();
|
|
2193
|
+
super(...arguments);
|
|
1897
2194
|
this.toastService = inject(AXToastService);
|
|
1898
2195
|
this.translationService = inject(AXTranslationService);
|
|
1899
2196
|
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
@@ -1903,15 +2200,14 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
1903
2200
|
this.rows = signal([], ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
1904
2201
|
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1905
2202
|
this.searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
|
|
1906
|
-
|
|
1907
|
-
this.
|
|
1908
|
-
this.assistsLoadPromise = null;
|
|
2203
|
+
this.selectedTargetIds = signal([], ...(ngDevMode ? [{ debugName: "selectedTargetIds" }] : /* istanbul ignore next */ []));
|
|
2204
|
+
this.targetsLoadPromise = null;
|
|
1909
2205
|
this.assistListDataSource = new AXDataSource({
|
|
1910
2206
|
pageSize: 100,
|
|
1911
2207
|
key: 'id',
|
|
1912
2208
|
load: async (e) => {
|
|
1913
|
-
await this.
|
|
1914
|
-
const filtered = this.
|
|
2209
|
+
await this.ensureTargetsLoaded();
|
|
2210
|
+
const filtered = this.filteredTargetRows();
|
|
1915
2211
|
return {
|
|
1916
2212
|
items: filtered.slice(e.skip, e.skip + e.take),
|
|
1917
2213
|
total: filtered.length,
|
|
@@ -1932,7 +2228,7 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
1932
2228
|
}
|
|
1933
2229
|
}, ...(ngDevMode ? [{ debugName: "syncPopupTitle" }] : /* istanbul ignore next */ []));
|
|
1934
2230
|
}
|
|
1935
|
-
|
|
2231
|
+
targetFromItem(item) {
|
|
1936
2232
|
if (!item || typeof item !== 'object') {
|
|
1937
2233
|
return null;
|
|
1938
2234
|
}
|
|
@@ -1945,14 +2241,10 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
1945
2241
|
}
|
|
1946
2242
|
return null;
|
|
1947
2243
|
}
|
|
1948
|
-
|
|
1949
|
-
return this.selectedAssistIds().includes(id);
|
|
1950
|
-
}
|
|
1951
|
-
/** Single assist: keep only the last selected id (list is `multiple` like the user picker). */
|
|
1952
|
-
onSelectedAssistsChange(ids) {
|
|
2244
|
+
onSelectedTargetsChange(ids) {
|
|
1953
2245
|
const deduped = [...new Set(ids)];
|
|
1954
2246
|
const next = deduped.length ? [deduped[deduped.length - 1]] : [];
|
|
1955
|
-
this.
|
|
2247
|
+
this.selectedTargetIds.set(next);
|
|
1956
2248
|
if (deduped.length > 1) {
|
|
1957
2249
|
queueMicrotask(() => this.assistsList()?.refresh(false));
|
|
1958
2250
|
}
|
|
@@ -1961,30 +2253,19 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
1961
2253
|
this.searchQuery.set(value ?? '');
|
|
1962
2254
|
this.assistsList()?.refresh(false);
|
|
1963
2255
|
}
|
|
1964
|
-
async
|
|
1965
|
-
if (!this.
|
|
1966
|
-
this.
|
|
2256
|
+
async ensureTargetsLoaded() {
|
|
2257
|
+
if (!this.targetsLoadPromise) {
|
|
2258
|
+
this.targetsLoadPromise = this.loadTargetsFromApi();
|
|
1967
2259
|
}
|
|
1968
|
-
await this.
|
|
2260
|
+
await this.targetsLoadPromise;
|
|
1969
2261
|
}
|
|
1970
|
-
async
|
|
2262
|
+
async loadTargetsFromApi() {
|
|
1971
2263
|
this.loading.set(true);
|
|
1972
2264
|
try {
|
|
1973
|
-
|
|
1974
|
-
const entity = await this.entityRegistry.resolve(RootConfig$1.module.name, RootConfig$1.entities.assist.name);
|
|
1975
|
-
const execute = entity.queries?.list?.execute;
|
|
1976
|
-
if (!execute) {
|
|
1977
|
-
throw new Error('Assist entity has no list query.');
|
|
1978
|
-
}
|
|
1979
|
-
const res = await execute({
|
|
1980
|
-
skip: 0,
|
|
1981
|
-
take: 500,
|
|
1982
|
-
sort: [{ name: 'name', dir: 'asc' }],
|
|
1983
|
-
});
|
|
1984
|
-
this.rows.set((res.items ?? []));
|
|
2265
|
+
this.rows.set(await axmLoadChatAiTargets(this.entityRegistry));
|
|
1985
2266
|
}
|
|
1986
2267
|
catch (error) {
|
|
1987
|
-
console.error('Failed to load
|
|
2268
|
+
console.error('Failed to load AI chat targets:', error);
|
|
1988
2269
|
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.load-assists');
|
|
1989
2270
|
this.toastService.danger(message);
|
|
1990
2271
|
this.rows.set([]);
|
|
@@ -1993,22 +2274,14 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
1993
2274
|
this.loading.set(false);
|
|
1994
2275
|
}
|
|
1995
2276
|
}
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
const list = this.rows();
|
|
1999
|
-
if (!q) {
|
|
2000
|
-
return list;
|
|
2001
|
-
}
|
|
2002
|
-
return list.filter((r) => r.name.toLowerCase().includes(q) ||
|
|
2003
|
-
r.title.toLowerCase().includes(q) ||
|
|
2004
|
-
(r.description?.toLowerCase().includes(q) ?? false));
|
|
2277
|
+
filteredTargetRows() {
|
|
2278
|
+
return axmFilterChatAiTargets((value) => this.translationService.resolve(value), this.rows(), this.searchQuery());
|
|
2005
2279
|
}
|
|
2006
2280
|
displayName(row) {
|
|
2007
|
-
return this.translationService.resolve(
|
|
2281
|
+
return axmChatAiTargetDisplayName((value) => this.translationService.resolve(value), row);
|
|
2008
2282
|
}
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
return avatarUrl ? avatarUrl : null;
|
|
2283
|
+
targetAvatarUrl(row) {
|
|
2284
|
+
return axmChatAiTargetAvatarUrl(row);
|
|
2012
2285
|
}
|
|
2013
2286
|
onCancel() {
|
|
2014
2287
|
const event = new AXComponentCloseEvent();
|
|
@@ -2017,25 +2290,23 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2017
2290
|
this.onClosed.emit(event);
|
|
2018
2291
|
}
|
|
2019
2292
|
async onStartChat() {
|
|
2020
|
-
const
|
|
2021
|
-
if (!
|
|
2293
|
+
const targetId = this.selectedTargetIds()[0];
|
|
2294
|
+
if (!targetId || !this.conversationService) {
|
|
2022
2295
|
return;
|
|
2023
2296
|
}
|
|
2024
|
-
const row = this.rows().find((r) => r.id ===
|
|
2297
|
+
const row = this.rows().find((r) => r.id === targetId);
|
|
2025
2298
|
if (!row) {
|
|
2026
2299
|
return;
|
|
2027
2300
|
}
|
|
2028
|
-
const participantId =
|
|
2301
|
+
const participantId = axmChatAiPeerParticipantId(row.id);
|
|
2029
2302
|
const title = this.displayName(row);
|
|
2030
|
-
const avatar = this.
|
|
2303
|
+
const avatar = this.targetAvatarUrl(row);
|
|
2031
2304
|
try {
|
|
2032
2305
|
const conversation = await this.conversationService.createConversation([participantId], 'bot', {
|
|
2033
2306
|
title,
|
|
2034
2307
|
...(avatar ? { avatar } : {}),
|
|
2035
2308
|
icon: 'fa-solid fa-robot',
|
|
2036
|
-
metadata:
|
|
2037
|
-
assistId: row.id,
|
|
2038
|
-
},
|
|
2309
|
+
metadata: axmBuildAiChatConversationMetadata(row),
|
|
2039
2310
|
});
|
|
2040
2311
|
const event = new AXComponentCloseEvent();
|
|
2041
2312
|
event.component = this;
|
|
@@ -2052,7 +2323,7 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2052
2323
|
const title = await this.translationService.translateAsync('@conversation:new-conversation.actions.chat-with-ai');
|
|
2053
2324
|
popupRef.setTitle(title);
|
|
2054
2325
|
}
|
|
2055
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatWithAssistDialogComponent, deps:
|
|
2326
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatWithAssistDialogComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2056
2327
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMChatWithAssistDialogComponent, isStandalone: true, selector: "axm-chat-with-assist-dialog", inputs: { __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null }, embeddedInTabs: { classPropertyName: "embeddedInTabs", publicName: "embeddedInTabs", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXClosableComponent, useExisting: AXMChatWithAssistDialogComponent }], viewQueries: [{ propertyName: "assistsListEmptyTpl", first: true, predicate: ["assistsListEmpty"], descendants: true, isSignal: true }, { propertyName: "assistsList", first: true, predicate: ["assistsList"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
2057
2328
|
<div class="new-conversation-panel">
|
|
2058
2329
|
<div class="new-conversation-dialog-content">
|
|
@@ -2067,8 +2338,8 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2067
2338
|
[valueField]="'id'"
|
|
2068
2339
|
[textField]="'name'"
|
|
2069
2340
|
[itemHeight]="'auto'"
|
|
2070
|
-
[ngModel]="
|
|
2071
|
-
(ngModelChange)="
|
|
2341
|
+
[ngModel]="selectedTargetIds()"
|
|
2342
|
+
(ngModelChange)="onSelectedTargetsChange($event ?? [])"
|
|
2072
2343
|
[emptyTemplate]="assistsListEmptyTpl()"
|
|
2073
2344
|
[itemTemplate]="assistItemTpl"
|
|
2074
2345
|
>
|
|
@@ -2096,7 +2367,7 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2096
2367
|
[text]="('@conversation:chat.assist-dialog.actions.start-chat' | translate | async) ?? ''"
|
|
2097
2368
|
[look]="'solid'"
|
|
2098
2369
|
[color]="'primary'"
|
|
2099
|
-
[disabled]="!
|
|
2370
|
+
[disabled]="!selectedTargetIds().length || loading()"
|
|
2100
2371
|
(onClick)="onStartChat()"
|
|
2101
2372
|
></ax-button>
|
|
2102
2373
|
</ax-suffix>
|
|
@@ -2116,12 +2387,11 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2116
2387
|
</ng-template>
|
|
2117
2388
|
|
|
2118
2389
|
<ng-template #assistItemTpl let-item>
|
|
2119
|
-
@if (
|
|
2390
|
+
@if (targetFromItem(item); as row) {
|
|
2120
2391
|
<div class="user-item-content">
|
|
2121
|
-
<!-- <input class="ax-checkbox" type="checkbox" [checked]="isAssistSelected(row.id)" tabindex="0" /> -->
|
|
2122
2392
|
<ax-avatar [size]="54">
|
|
2123
|
-
@if (
|
|
2124
|
-
<ax-image [src]="avatarUrl" [alt]="
|
|
2393
|
+
@if (targetAvatarUrl(row); as avatarUrl) {
|
|
2394
|
+
<ax-image [src]="avatarUrl" [alt]="row.title | translate | async"></ax-image>
|
|
2125
2395
|
} @else {
|
|
2126
2396
|
<ax-icon
|
|
2127
2397
|
><i
|
|
@@ -2138,7 +2408,7 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2138
2408
|
}
|
|
2139
2409
|
</ax-avatar>
|
|
2140
2410
|
<div class="user-item-text">
|
|
2141
|
-
<span class="ax-truncated user-name-text">{{
|
|
2411
|
+
<span class="ax-truncated user-name-text">{{ row.title | translate | async }}</span>
|
|
2142
2412
|
@if (row.description) {
|
|
2143
2413
|
<span class="user-description-text ax-truncated">{{ row.description | translate | async }}</span>
|
|
2144
2414
|
}
|
|
@@ -2146,7 +2416,7 @@ class AXMChatWithAssistDialogComponent extends AXBasePageComponent {
|
|
|
2146
2416
|
</div>
|
|
2147
2417
|
}
|
|
2148
2418
|
</ng-template>
|
|
2149
|
-
`, isInline: true, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.form-field{display:flex;flex-direction:column;gap:.35rem}.users-list-wrap{height:min(50vh,36rem);overflow:hidden}.users-list{display:block;height:100%}.users-list-header{display:block;position:sticky;top:0;z-index:1;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.users-list-header-inner{padding:.5rem .75rem}.user-item-content{display:flex;align-items:center;gap:.5rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.1rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1rem;line-height:1.5rem;font-weight:500}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}.dialog-footer{flex-shrink:0;padding:1rem;border-top:1px solid var(--ax-border-color, #e5e7eb);display:flex;justify-content:flex-end}.dialog-footer>ax-suffix{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.75rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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:
|
|
2419
|
+
`, isInline: true, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.form-field{display:flex;flex-direction:column;gap:.35rem}.users-list-wrap{height:min(50vh,36rem);overflow:hidden}.users-list{display:block;height:100%}.users-list-header{display:block;position:sticky;top:0;z-index:1;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.users-list-header-inner{padding:.5rem .75rem}.user-item-content{display:flex;align-items:center;gap:.5rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.1rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1rem;line-height:1.5rem;font-weight:500}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}.dialog-footer{flex-shrink:0;padding:1rem;border-top:1px solid var(--ax-border-color, #e5e7eb);display:flex;justify-content:flex-end}.dialog-footer>ax-suffix{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.75rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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 }); }
|
|
2150
2420
|
}
|
|
2151
2421
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatWithAssistDialogComponent, decorators: [{
|
|
2152
2422
|
type: Component,
|
|
@@ -2174,8 +2444,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2174
2444
|
[valueField]="'id'"
|
|
2175
2445
|
[textField]="'name'"
|
|
2176
2446
|
[itemHeight]="'auto'"
|
|
2177
|
-
[ngModel]="
|
|
2178
|
-
(ngModelChange)="
|
|
2447
|
+
[ngModel]="selectedTargetIds()"
|
|
2448
|
+
(ngModelChange)="onSelectedTargetsChange($event ?? [])"
|
|
2179
2449
|
[emptyTemplate]="assistsListEmptyTpl()"
|
|
2180
2450
|
[itemTemplate]="assistItemTpl"
|
|
2181
2451
|
>
|
|
@@ -2203,7 +2473,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2203
2473
|
[text]="('@conversation:chat.assist-dialog.actions.start-chat' | translate | async) ?? ''"
|
|
2204
2474
|
[look]="'solid'"
|
|
2205
2475
|
[color]="'primary'"
|
|
2206
|
-
[disabled]="!
|
|
2476
|
+
[disabled]="!selectedTargetIds().length || loading()"
|
|
2207
2477
|
(onClick)="onStartChat()"
|
|
2208
2478
|
></ax-button>
|
|
2209
2479
|
</ax-suffix>
|
|
@@ -2223,12 +2493,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2223
2493
|
</ng-template>
|
|
2224
2494
|
|
|
2225
2495
|
<ng-template #assistItemTpl let-item>
|
|
2226
|
-
@if (
|
|
2496
|
+
@if (targetFromItem(item); as row) {
|
|
2227
2497
|
<div class="user-item-content">
|
|
2228
|
-
<!-- <input class="ax-checkbox" type="checkbox" [checked]="isAssistSelected(row.id)" tabindex="0" /> -->
|
|
2229
2498
|
<ax-avatar [size]="54">
|
|
2230
|
-
@if (
|
|
2231
|
-
<ax-image [src]="avatarUrl" [alt]="
|
|
2499
|
+
@if (targetAvatarUrl(row); as avatarUrl) {
|
|
2500
|
+
<ax-image [src]="avatarUrl" [alt]="row.title | translate | async"></ax-image>
|
|
2232
2501
|
} @else {
|
|
2233
2502
|
<ax-icon
|
|
2234
2503
|
><i
|
|
@@ -2245,7 +2514,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2245
2514
|
}
|
|
2246
2515
|
</ax-avatar>
|
|
2247
2516
|
<div class="user-item-text">
|
|
2248
|
-
<span class="ax-truncated user-name-text">{{
|
|
2517
|
+
<span class="ax-truncated user-name-text">{{ row.title | translate | async }}</span>
|
|
2249
2518
|
@if (row.description) {
|
|
2250
2519
|
<span class="user-description-text ax-truncated">{{ row.description | translate | async }}</span>
|
|
2251
2520
|
}
|
|
@@ -2254,7 +2523,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2254
2523
|
}
|
|
2255
2524
|
</ng-template>
|
|
2256
2525
|
`, styles: [":host{display:block}.new-conversation-panel{display:flex;flex-direction:column;width:100%;overflow:hidden}.new-conversation-dialog-content{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:.75rem}.form-field--grow{flex:1;min-height:0;display:flex;flex-direction:column}.form-field{display:flex;flex-direction:column;gap:.35rem}.users-list-wrap{height:min(50vh,36rem);overflow:hidden}.users-list{display:block;height:100%}.users-list-header{display:block;position:sticky;top:0;z-index:1;border-bottom:1px solid rgb(var(--ax-sys-color-border-light-surface))}.users-list-header-inner{padding:.5rem .75rem}.user-item-content{display:flex;align-items:center;gap:.5rem;height:100%;padding:.5rem .75rem;min-width:0}.user-item-text{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;gap:.1rem}.user-name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1rem;line-height:1.5rem;font-weight:500}.user-description-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;line-height:1.25rem;font-weight:400;opacity:.72;color:rgb(var(--ax-sys-color-on-surface))}.users-list-empty{padding:1rem;text-align:center;font-size:.85rem;opacity:.7}.dialog-footer{flex-shrink:0;padding:1rem;border-top:1px solid var(--ax-border-color, #e5e7eb);display:flex;justify-content:flex-end}.dialog-footer>ax-suffix{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.75rem}\n"] }]
|
|
2257
|
-
}],
|
|
2526
|
+
}], propDecorators: { __popup__: [{ type: i0.Input, args: [{ isSignal: true, alias: "__popup__", required: false }] }], embeddedInTabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "embeddedInTabs", required: false }] }], assistsListEmptyTpl: [{ type: i0.ViewChild, args: ['assistsListEmpty', { isSignal: true }] }], assistsList: [{ type: i0.ViewChild, args: ['assistsList', { isSignal: true }] }] } });
|
|
2258
2527
|
|
|
2259
2528
|
/**
|
|
2260
2529
|
* Replaces the default sidebar "New conversation" control with a split-style dropdown:
|
|
@@ -2322,7 +2591,7 @@ class AXMChatSidebarNewActionsComponent {
|
|
|
2322
2591
|
</ax-fab-item>
|
|
2323
2592
|
</ax-fab>
|
|
2324
2593
|
</div>
|
|
2325
|
-
`, isInline: true, styles: [":host{display:block}.new-conversation-button-container-inner{display:flex;justify-content:end;align-items:center;padding-inline-end:.25rem}.new-conversation-fab{z-index:1}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { 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: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type:
|
|
2594
|
+
`, isInline: true, styles: [":host{display:block}.new-conversation-button-container-inner{display:flex;justify-content:end;align-items:center;padding-inline-end:.25rem}.new-conversation-fab{z-index:1}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { 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: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2326
2595
|
}
|
|
2327
2596
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatSidebarNewActionsComponent, decorators: [{
|
|
2328
2597
|
type: Component,
|
|
@@ -2551,10 +2820,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2551
2820
|
//#endregion
|
|
2552
2821
|
//#region ---- Transcript read ----
|
|
2553
2822
|
/**
|
|
2554
|
-
* Reorders assist transcript
|
|
2555
|
-
* and `tool`-role results in their original order, then all **text** (final answer).
|
|
2556
|
-
* This matches chronological expectation (agent call and its result appear before the
|
|
2557
|
-
* assistant's closing message).
|
|
2823
|
+
* Reorders assist transcript for debug UI: think first, tool/agent + tool results, then text blocks.
|
|
2558
2824
|
*/
|
|
2559
2825
|
function axmNormalizeAssistTranscriptForChatUi(input) {
|
|
2560
2826
|
if (input.length === 0) {
|
|
@@ -2600,17 +2866,14 @@ function axmNormalizeAssistTranscriptForChatUi(input) {
|
|
|
2600
2866
|
}
|
|
2601
2867
|
return out;
|
|
2602
2868
|
}
|
|
2603
|
-
/**
|
|
2604
|
-
* Reads AI transcript lines from assist message metadata (final `aiTranscript` or streaming `aiTranscriptDraft`),
|
|
2605
|
-
* in display order for the assist renderer.
|
|
2606
|
-
*/
|
|
2869
|
+
/** Debug transcript from {@code metadata.transcripts} or streaming {@code metadata.transcriptDraft}. */
|
|
2607
2870
|
function axmReadAssistAiTranscript(metadata) {
|
|
2608
2871
|
if (typeof metadata !== 'object' || metadata == null) {
|
|
2609
2872
|
return null;
|
|
2610
2873
|
}
|
|
2611
2874
|
const m = metadata;
|
|
2612
|
-
const final = m['
|
|
2613
|
-
const draft = m['
|
|
2875
|
+
const final = m['transcripts'];
|
|
2876
|
+
const draft = m['transcriptDraft'];
|
|
2614
2877
|
if (Array.isArray(final) && final.length > 0) {
|
|
2615
2878
|
return axmNormalizeAssistTranscriptForChatUi(final);
|
|
2616
2879
|
}
|
|
@@ -2619,17 +2882,14 @@ function axmReadAssistAiTranscript(metadata) {
|
|
|
2619
2882
|
}
|
|
2620
2883
|
return null;
|
|
2621
2884
|
}
|
|
2622
|
-
/**
|
|
2623
|
-
* Raw {@link AXPAiChatMessage} lines as persisted by the engine/mock (`aiTranscript` / `aiTranscriptDraft`),
|
|
2624
|
-
* without chat UI reordering.
|
|
2625
|
-
*/
|
|
2885
|
+
/** Raw engine transcript (chronological), without debug UI reordering. */
|
|
2626
2886
|
function axmReadAssistAiTranscriptRaw(metadata) {
|
|
2627
2887
|
if (typeof metadata !== 'object' || metadata == null) {
|
|
2628
2888
|
return [];
|
|
2629
2889
|
}
|
|
2630
2890
|
const m = metadata;
|
|
2631
|
-
const final = m['
|
|
2632
|
-
const draft = m['
|
|
2891
|
+
const final = m['transcripts'];
|
|
2892
|
+
const draft = m['transcriptDraft'];
|
|
2633
2893
|
if (Array.isArray(final) && final.length > 0) {
|
|
2634
2894
|
return final;
|
|
2635
2895
|
}
|
|
@@ -2640,10 +2900,6 @@ function axmReadAssistAiTranscriptRaw(metadata) {
|
|
|
2640
2900
|
}
|
|
2641
2901
|
//#endregion
|
|
2642
2902
|
//#region ---- Layout / synthetic helpers ----
|
|
2643
|
-
/**
|
|
2644
|
-
* Transcript response discriminators ({@link AXPAiChatResponse} `type` values).
|
|
2645
|
-
* These must not be treated as {@link AXPWidgetNode} `type` when coercing unknown JSON.
|
|
2646
|
-
*/
|
|
2647
2903
|
const AXM_ASSIST_TRANSCRIPT_NON_WIDGET_TYPES = new Set([
|
|
2648
2904
|
'text',
|
|
2649
2905
|
'think',
|
|
@@ -2656,11 +2912,6 @@ const AXM_ASSIST_TRANSCRIPT_NON_WIDGET_TYPES = new Set([
|
|
|
2656
2912
|
'agent_result',
|
|
2657
2913
|
]);
|
|
2658
2914
|
const AXM_ASSIST_NODE_ENVELOPE_UNWRAP_MAX_DEPTH = 6;
|
|
2659
|
-
/**
|
|
2660
|
-
* Returns `content` as an {@link AXPWidgetNode} when it looks like a widget tree.
|
|
2661
|
-
* Rejects assistant transcript segment shapes (e.g. `{ type: 'text', content: '...' }`) and unwraps
|
|
2662
|
-
* a single `{ type: 'node', content: <widget> }` envelope if present.
|
|
2663
|
-
*/
|
|
2664
2915
|
function axmAssistWidgetNodeFromUnknown(content, depth = 0) {
|
|
2665
2916
|
if (depth > AXM_ASSIST_NODE_ENVELOPE_UNWRAP_MAX_DEPTH) {
|
|
2666
2917
|
return null;
|
|
@@ -2681,35 +2932,76 @@ function axmAssistWidgetNodeFromUnknown(content, depth = 0) {
|
|
|
2681
2932
|
}
|
|
2682
2933
|
return content;
|
|
2683
2934
|
}
|
|
2684
|
-
/**
|
|
2685
|
-
* Returns the first `node` segment's content as an {@link AXPWidgetNode} when it looks like a widget tree.
|
|
2686
|
-
*/
|
|
2687
|
-
function axmAssistNodeAsLayoutNode(message) {
|
|
2688
|
-
if (message.role !== 'assistant') {
|
|
2689
|
-
return null;
|
|
2690
|
-
}
|
|
2691
|
-
const n = message.responses.find((r) => r.type === 'node');
|
|
2692
|
-
return n?.type === 'node' ? axmAssistWidgetNodeFromUnknown(n.content) : null;
|
|
2693
|
-
}
|
|
2694
|
-
/**
|
|
2695
|
-
* Builds a synthetic {@link AXMessage} for embedding default conversation renderers (text, image, etc.).
|
|
2696
|
-
*/
|
|
2697
2935
|
function axmSyntheticEmbedMessage(parent, suffix, partial) {
|
|
2698
2936
|
return {
|
|
2699
2937
|
...parent,
|
|
2700
2938
|
id: `${parent.id}::${suffix}`,
|
|
2701
2939
|
type: partial.type,
|
|
2702
2940
|
payload: partial.payload,
|
|
2703
|
-
metadata: {
|
|
2941
|
+
metadata: {
|
|
2942
|
+
...(typeof parent.metadata === 'object' && parent.metadata != null ? parent.metadata : {}),
|
|
2943
|
+
assistEmbed: true,
|
|
2944
|
+
},
|
|
2704
2945
|
replyTo: undefined,
|
|
2705
2946
|
};
|
|
2706
2947
|
}
|
|
2707
2948
|
//#endregion
|
|
2708
|
-
//#region ----
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2949
|
+
//#region ---- Payload (last transcript line) ----
|
|
2950
|
+
const AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE = 'assist-transcript-line';
|
|
2951
|
+
function axmNormalizeAssistTranscriptLineResponses(line) {
|
|
2952
|
+
if (line.role !== 'assistant') {
|
|
2953
|
+
return line;
|
|
2954
|
+
}
|
|
2955
|
+
const expanded = [];
|
|
2956
|
+
for (const seg of line.responses) {
|
|
2957
|
+
if (seg.type === 'text') {
|
|
2958
|
+
const parsed = axpAiChatMessagesFromProviderAssistant(seg.content, undefined)[0];
|
|
2959
|
+
if (parsed?.role === 'assistant' && parsed.responses.length > 0) {
|
|
2960
|
+
expanded.push(...parsed.responses);
|
|
2961
|
+
}
|
|
2962
|
+
else {
|
|
2963
|
+
expanded.push(seg);
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
else {
|
|
2967
|
+
expanded.push(seg);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
return { ...line, responses: expanded };
|
|
2971
|
+
}
|
|
2972
|
+
/** Last {@link AXPAiChatMessage} in the engine turn (index {@code length - 1}). */
|
|
2973
|
+
function axmAssistLastTranscriptLine(transcript) {
|
|
2974
|
+
if (transcript.length === 0) {
|
|
2975
|
+
return null;
|
|
2976
|
+
}
|
|
2977
|
+
return axmNormalizeAssistTranscriptLineResponses(transcript[transcript.length - 1]);
|
|
2978
|
+
}
|
|
2979
|
+
function axmBuildAssistTranscriptLinePayload(line) {
|
|
2980
|
+
return {
|
|
2981
|
+
type: AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE,
|
|
2982
|
+
line: axmNormalizeAssistTranscriptLineResponses(line),
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
function axmParseAssistTranscriptLinePayload(payload) {
|
|
2986
|
+
if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
2987
|
+
return null;
|
|
2988
|
+
}
|
|
2989
|
+
const rec = payload;
|
|
2990
|
+
if (rec['type'] !== AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE) {
|
|
2991
|
+
return null;
|
|
2992
|
+
}
|
|
2993
|
+
const line = rec['line'];
|
|
2994
|
+
if (line == null || typeof line !== 'object' || Array.isArray(line)) {
|
|
2995
|
+
return null;
|
|
2996
|
+
}
|
|
2997
|
+
const lm = line;
|
|
2998
|
+
if (!Array.isArray(lm.responses)) {
|
|
2999
|
+
return null;
|
|
3000
|
+
}
|
|
3001
|
+
return axmNormalizeAssistTranscriptLineResponses(lm);
|
|
3002
|
+
}
|
|
3003
|
+
//#endregion
|
|
3004
|
+
//#region ---- Text envelope ----
|
|
2713
3005
|
function axmParseAssistTranscriptTextEnvelope(raw) {
|
|
2714
3006
|
if (!raw) {
|
|
2715
3007
|
return { thinking: null, body: '' };
|
|
@@ -2727,76 +3019,99 @@ function axmParseAssistTranscriptTextEnvelope(raw) {
|
|
|
2727
3019
|
.trim();
|
|
2728
3020
|
return { thinking: parts.length ? parts.join('\n\n') : null, body };
|
|
2729
3021
|
}
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
3022
|
+
//#endregion
|
|
3023
|
+
//#region ---- User-mode visible segments (non-debug bubble) ----
|
|
3024
|
+
function axmUserVisibleDelegatedSegment(seg) {
|
|
3025
|
+
if (seg.type === 'think') {
|
|
3026
|
+
return false;
|
|
3027
|
+
}
|
|
3028
|
+
if (seg.type === 'node') {
|
|
3029
|
+
return axmAssistWidgetNodeFromUnknown(seg.content) != null;
|
|
3030
|
+
}
|
|
3031
|
+
if (seg.type === 'file') {
|
|
3032
|
+
return true;
|
|
3033
|
+
}
|
|
3034
|
+
if (seg.type === 'text') {
|
|
3035
|
+
const body = axmParseAssistTranscriptTextEnvelope(seg.content).body.trim();
|
|
3036
|
+
return body.length > 0 && body !== '```' && body !== '```json';
|
|
3037
|
+
}
|
|
3038
|
+
return false;
|
|
3039
|
+
}
|
|
3040
|
+
function axmUserVisibleChatResponse(line, seg) {
|
|
3041
|
+
if (line.role === 'assistant') {
|
|
3042
|
+
if (seg.type === 'think') {
|
|
3043
|
+
return false;
|
|
2735
3044
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
if (c.success !== true || c.data == null || typeof c.data !== 'object' || Array.isArray(c.data)) {
|
|
2742
|
-
continue;
|
|
2743
|
-
}
|
|
2744
|
-
const responses = c.data['responses'];
|
|
2745
|
-
const parsed = axpAiParseDelegatedAgentResultSegmentsFromUnknown(responses);
|
|
2746
|
-
if (parsed.length > 0) {
|
|
2747
|
-
return parsed;
|
|
2748
|
-
}
|
|
3045
|
+
if (seg.type === 'node') {
|
|
3046
|
+
return axmAssistWidgetNodeFromUnknown(seg.content) != null;
|
|
3047
|
+
}
|
|
3048
|
+
if (seg.type === 'file') {
|
|
3049
|
+
return true;
|
|
2749
3050
|
}
|
|
3051
|
+
if (seg.type === 'text') {
|
|
3052
|
+
const body = axmParseAssistTranscriptTextEnvelope(seg.content).body.trim();
|
|
3053
|
+
return body.length > 0 && body !== '```' && body !== '```json';
|
|
3054
|
+
}
|
|
3055
|
+
return false;
|
|
2750
3056
|
}
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
* When the transcript has no such segment, {@code fallbackText} is used as plain text.
|
|
2756
|
-
*/
|
|
2757
|
-
function axmExtractAssistFinalDeliverableFromTranscript(transcript, fallbackText) {
|
|
2758
|
-
let last = null;
|
|
2759
|
-
for (const line of transcript) {
|
|
2760
|
-
if (line.role !== 'assistant') {
|
|
2761
|
-
continue;
|
|
3057
|
+
if (line.role === 'tool' && seg.type === 'agent_result') {
|
|
3058
|
+
const c = seg.content;
|
|
3059
|
+
if (c.success !== true || c.data == null || typeof c.data !== 'object' || Array.isArray(c.data)) {
|
|
3060
|
+
return false;
|
|
2762
3061
|
}
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
3062
|
+
const responses = c.data['responses'];
|
|
3063
|
+
return axpAiParseDelegatedAgentResultSegmentsFromUnknown(responses).some(axmUserVisibleDelegatedSegment);
|
|
3064
|
+
}
|
|
3065
|
+
return false;
|
|
3066
|
+
}
|
|
3067
|
+
function axmAssistUserVisibleItemsForLine(line) {
|
|
3068
|
+
const out = [];
|
|
3069
|
+
for (const seg of line.responses) {
|
|
3070
|
+
if (line.role === 'assistant') {
|
|
3071
|
+
if (seg.type === 'text' && axmUserVisibleChatResponse(line, seg)) {
|
|
3072
|
+
out.push({ kind: 'text', content: seg.content });
|
|
2766
3073
|
}
|
|
2767
|
-
else if (seg.type === '
|
|
2768
|
-
|
|
2769
|
-
if (body) {
|
|
2770
|
-
last = { kind: 'text', text: seg.content };
|
|
2771
|
-
}
|
|
3074
|
+
else if (seg.type === 'node' && axmUserVisibleChatResponse(line, seg)) {
|
|
3075
|
+
out.push({ kind: 'node', content: seg.content });
|
|
2772
3076
|
}
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
last = { kind: 'node', content: seg.content };
|
|
2781
|
-
break;
|
|
3077
|
+
else if (seg.type === 'file') {
|
|
3078
|
+
out.push({
|
|
3079
|
+
kind: 'file',
|
|
3080
|
+
fileId: seg.content.fileId,
|
|
3081
|
+
mimeType: seg.content.mimeType,
|
|
3082
|
+
name: seg.content.name,
|
|
3083
|
+
});
|
|
2782
3084
|
}
|
|
3085
|
+
continue;
|
|
2783
3086
|
}
|
|
2784
|
-
if (
|
|
2785
|
-
const
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
3087
|
+
if (line.role === 'tool' && seg.type === 'agent_result') {
|
|
3088
|
+
const c = seg.content;
|
|
3089
|
+
if (c.success !== true || c.data == null || typeof c.data !== 'object' || Array.isArray(c.data)) {
|
|
3090
|
+
continue;
|
|
3091
|
+
}
|
|
3092
|
+
const responses = c.data['responses'];
|
|
3093
|
+
for (const ds of axpAiParseDelegatedAgentResultSegmentsFromUnknown(responses)) {
|
|
3094
|
+
if (!axmUserVisibleDelegatedSegment(ds)) {
|
|
3095
|
+
continue;
|
|
3096
|
+
}
|
|
3097
|
+
if (ds.type === 'text') {
|
|
3098
|
+
out.push({ kind: 'text', content: ds.content });
|
|
3099
|
+
}
|
|
3100
|
+
else if (ds.type === 'node') {
|
|
3101
|
+
out.push({ kind: 'node', content: ds.content });
|
|
3102
|
+
}
|
|
3103
|
+
else if (ds.type === 'file') {
|
|
3104
|
+
out.push({
|
|
3105
|
+
kind: 'file',
|
|
3106
|
+
fileId: ds.content.fileId,
|
|
3107
|
+
mimeType: ds.content.mimeType,
|
|
3108
|
+
name: ds.content.name,
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
2793
3111
|
}
|
|
2794
3112
|
}
|
|
2795
3113
|
}
|
|
2796
|
-
|
|
2797
|
-
return last;
|
|
2798
|
-
}
|
|
2799
|
-
return { kind: 'text', text: fallbackText.trim() };
|
|
3114
|
+
return out;
|
|
2800
3115
|
}
|
|
2801
3116
|
//#endregion
|
|
2802
3117
|
|
|
@@ -2812,11 +3127,15 @@ function axmIsAssistPeerParticipant(participant) {
|
|
|
2812
3127
|
if (!meta) {
|
|
2813
3128
|
return false;
|
|
2814
3129
|
}
|
|
2815
|
-
if (meta['kind'] === 'assist') {
|
|
3130
|
+
if (meta['kind'] === 'assist' || meta['kind'] === 'agent-assist') {
|
|
2816
3131
|
return true;
|
|
2817
3132
|
}
|
|
2818
3133
|
const assistId = meta['assistId'];
|
|
2819
|
-
|
|
3134
|
+
if (typeof assistId === 'string' && assistId.trim().length > 0) {
|
|
3135
|
+
return true;
|
|
3136
|
+
}
|
|
3137
|
+
const directAgentId = meta['directAgentId'];
|
|
3138
|
+
return typeof directAgentId === 'string' && directAgentId.trim().length > 0;
|
|
2820
3139
|
}
|
|
2821
3140
|
|
|
2822
3141
|
class AXMCommentRealtimeService {
|
|
@@ -3639,7 +3958,7 @@ class AXMCommentComponent {
|
|
|
3639
3958
|
this.showToast(content, color);
|
|
3640
3959
|
}
|
|
3641
3960
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3642
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\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)=\"onRepliesExpandedChange(comment.id!, $event)\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"40\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.edit.title' | translate | async) ?? ''\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item\n [text]=\"('@conversation:comments.actions.delete.title' | translate | async) ?? ''\"\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 [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [like]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"40\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.edit.title' | translate | async) ?? ''\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.delete.title' | translate | async) ?? ''\"\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 [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [like]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n {{ '@conversation:comments.components.comment.empty-states.no-comments.title' | translate | async }}\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <div class=\"ax-flex ax-flex-col\">\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-surface ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-light ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\">\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n @if (isReplyingMode()) {\n {{ '@conversation:comments.actions.reply-to' | translate | async }}\n <span class=\"ax-font-bold\">{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{ '@conversation:comments.actions.edit-message' | translate | async }}\n }\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-light ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></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 [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"'@conversation:comments.actions.send.title' | translate | async\"\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", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-comment-item.highlighted{animation:comment-highlight-pulse 2.5s cubic-bezier(.4,0,.2,1) forwards}@keyframes comment-highlight-pulse{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}}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$2.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$2.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$2.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$2.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$2.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$2.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$2.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$2.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount", "repliesExpanded"], outputs: ["repliesExpandedChange"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: i2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i2.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: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.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"] }, { kind: "pipe", type: i9.AXFormatPipe, name: "format" }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
3961
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\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)=\"onRepliesExpandedChange(comment.id!, $event)\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"40\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.edit.title' | translate | async) ?? ''\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item\n [text]=\"('@conversation:comments.actions.delete.title' | translate | async) ?? ''\"\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 [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [like]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"40\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.edit.title' | translate | async) ?? ''\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"('@conversation:comments.actions.delete.title' | translate | async) ?? ''\"\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 [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [like]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n {{ '@conversation:comments.components.comment.empty-states.no-comments.title' | translate | async }}\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <div class=\"ax-flex ax-flex-col\">\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-surface ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-light ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\">\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n @if (isReplyingMode()) {\n {{ '@conversation:comments.actions.reply-to' | translate | async }}\n <span class=\"ax-font-bold\">{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{ '@conversation:comments.actions.edit-message' | translate | async }}\n }\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-light ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></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 [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"'@conversation:comments.actions.send.title' | translate | async\"\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", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-comment-item.highlighted{animation:comment-highlight-pulse 2.5s cubic-bezier(.4,0,.2,1) forwards}@keyframes comment-highlight-pulse{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}}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$2.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$2.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$2.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$2.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$2.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$2.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$2.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$2.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount", "repliesExpanded"], outputs: ["repliesExpandedChange"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: i2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i2.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: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.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"] }, { kind: "pipe", type: i9.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
3643
3962
|
trigger('fadeIn', [
|
|
3644
3963
|
transition(':enter', [
|
|
3645
3964
|
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
@@ -3806,7 +4125,7 @@ class AXMCommentPopupComponent extends AXBasePageComponent {
|
|
|
3806
4125
|
// ACoreX
|
|
3807
4126
|
AXDecoratorModule }, { kind: "component", type: i1$1.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: i2.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:
|
|
3808
4127
|
// Comment
|
|
3809
|
-
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type:
|
|
4128
|
+
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
3810
4129
|
}
|
|
3811
4130
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMCommentPopupComponent, decorators: [{
|
|
3812
4131
|
type: Component,
|
|
@@ -4082,8 +4401,7 @@ const DOWNLOAD_DEBUG_LABEL = '@conversation:chat.actions.download-debug-informat
|
|
|
4082
4401
|
//#endregion
|
|
4083
4402
|
//#region ---- Helpers ----
|
|
4084
4403
|
function isAssistConversation(conversation) {
|
|
4085
|
-
|
|
4086
|
-
return typeof assistId === 'string' && assistId.trim().length > 0;
|
|
4404
|
+
return axmConversationHasAiChat(conversation ?? undefined);
|
|
4087
4405
|
}
|
|
4088
4406
|
function isDebugExportVisible() {
|
|
4089
4407
|
return axmAssistChatDebugModeState.resolved && axmAssistChatDebugModeState.enabled;
|
|
@@ -4167,6 +4485,10 @@ function axmIsAssistBotConversation(conversation) {
|
|
|
4167
4485
|
if (typeof fromMeta === 'string' && fromMeta.trim().length > 0) {
|
|
4168
4486
|
return true;
|
|
4169
4487
|
}
|
|
4488
|
+
const fromDirectAgent = conversation.metadata?.['directAgentId'];
|
|
4489
|
+
if (typeof fromDirectAgent === 'string' && fromDirectAgent.trim().length > 0) {
|
|
4490
|
+
return true;
|
|
4491
|
+
}
|
|
4170
4492
|
for (const participant of conversation.participants ?? []) {
|
|
4171
4493
|
if (typeof participant.id === 'string' && participant.id.startsWith('assist-')) {
|
|
4172
4494
|
return true;
|
|
@@ -4175,6 +4497,10 @@ function axmIsAssistBotConversation(conversation) {
|
|
|
4175
4497
|
if (typeof fromParticipant === 'string' && fromParticipant.trim().length > 0) {
|
|
4176
4498
|
return true;
|
|
4177
4499
|
}
|
|
4500
|
+
const fromParticipantAgent = participant.metadata?.['directAgentId'];
|
|
4501
|
+
if (typeof fromParticipantAgent === 'string' && fromParticipantAgent.trim().length > 0) {
|
|
4502
|
+
return true;
|
|
4503
|
+
}
|
|
4178
4504
|
}
|
|
4179
4505
|
return false;
|
|
4180
4506
|
}
|
|
@@ -4283,6 +4609,9 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4283
4609
|
this.assistData = this.entityService
|
|
4284
4610
|
.withEntity(RootConfig$1.module.name, RootConfig$1.entities.assist.name)
|
|
4285
4611
|
.data();
|
|
4612
|
+
this.agentData = this.entityService
|
|
4613
|
+
.withEntity(RootConfig$1.module.name, RootConfig$1.entities.agent.name)
|
|
4614
|
+
.data();
|
|
4286
4615
|
//#endregion
|
|
4287
4616
|
//#region ---- State ----
|
|
4288
4617
|
this.error = signal(false, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
@@ -4316,8 +4645,13 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4316
4645
|
this.reset();
|
|
4317
4646
|
return;
|
|
4318
4647
|
}
|
|
4648
|
+
if (!axmConversationHasAiChat(conversation)) {
|
|
4649
|
+
this.reset();
|
|
4650
|
+
return;
|
|
4651
|
+
}
|
|
4652
|
+
const directAgentId = this.getDirectAgentId(conversation);
|
|
4319
4653
|
const assistId = this.getAssistId(conversation);
|
|
4320
|
-
if (!assistId) {
|
|
4654
|
+
if (!directAgentId && !assistId) {
|
|
4321
4655
|
this.reset();
|
|
4322
4656
|
return;
|
|
4323
4657
|
}
|
|
@@ -4328,15 +4662,22 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4328
4662
|
this.isAssistConversation.set(true);
|
|
4329
4663
|
this.error.set(false);
|
|
4330
4664
|
try {
|
|
4331
|
-
|
|
4332
|
-
|
|
4665
|
+
let modelEntityId;
|
|
4666
|
+
if (directAgentId) {
|
|
4667
|
+
const agent = await this.agentData.byKey(directAgentId);
|
|
4668
|
+
modelEntityId = agent?.modelEntityId?.trim();
|
|
4669
|
+
}
|
|
4670
|
+
else if (assistId) {
|
|
4671
|
+
const assist = await this.assistData.byKey(assistId);
|
|
4672
|
+
modelEntityId = assist?.modelId?.trim();
|
|
4673
|
+
}
|
|
4333
4674
|
if (!modelEntityId) {
|
|
4334
4675
|
this.error.set(true);
|
|
4335
4676
|
this.resolvedModelTitle.set(undefined);
|
|
4336
4677
|
return;
|
|
4337
4678
|
}
|
|
4338
4679
|
this.persistModelToMetadata(conversation.id, modelEntityId);
|
|
4339
|
-
const rows = await this.modelCatalog.listModels({});
|
|
4680
|
+
const rows = await this.modelCatalog.listModels(directAgentId ? { directAgentId } : { assistId: assistId });
|
|
4340
4681
|
const title = rows.find((r) => r.id === modelEntityId)?.title?.trim();
|
|
4341
4682
|
this.resolvedModelTitle.set(title ?? modelEntityId);
|
|
4342
4683
|
}
|
|
@@ -4366,12 +4707,6 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4366
4707
|
return raw.trim();
|
|
4367
4708
|
}
|
|
4368
4709
|
for (const participant of conversation.participants ?? []) {
|
|
4369
|
-
if (typeof participant.id !== 'string') {
|
|
4370
|
-
continue;
|
|
4371
|
-
}
|
|
4372
|
-
if (participant.id.startsWith('assist-')) {
|
|
4373
|
-
return participant.id.slice('assist-'.length) || null;
|
|
4374
|
-
}
|
|
4375
4710
|
const participantAssistId = participant.metadata?.['assistId'];
|
|
4376
4711
|
if (typeof participantAssistId === 'string' && participantAssistId.trim()) {
|
|
4377
4712
|
return participantAssistId.trim();
|
|
@@ -4379,6 +4714,25 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4379
4714
|
}
|
|
4380
4715
|
return null;
|
|
4381
4716
|
}
|
|
4717
|
+
getDirectAgentId(conversation) {
|
|
4718
|
+
const raw = conversation.metadata?.['directAgentId'];
|
|
4719
|
+
if (typeof raw === 'string' && raw.trim()) {
|
|
4720
|
+
return raw.trim();
|
|
4721
|
+
}
|
|
4722
|
+
for (const participant of conversation.participants ?? []) {
|
|
4723
|
+
const participantAgentId = participant.metadata?.['directAgentId'];
|
|
4724
|
+
if (typeof participantAgentId === 'string' && participantAgentId.trim()) {
|
|
4725
|
+
return participantAgentId.trim();
|
|
4726
|
+
}
|
|
4727
|
+
if (typeof participant.id === 'string' && participant.id.startsWith('assist-')) {
|
|
4728
|
+
const peerId = participant.id.slice('assist-'.length);
|
|
4729
|
+
if (peerId && !this.getAssistId(conversation)) {
|
|
4730
|
+
return peerId;
|
|
4731
|
+
}
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
return null;
|
|
4735
|
+
}
|
|
4382
4736
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatInfoBarAssistModelActionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4383
4737
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMChatInfoBarAssistModelActionComponent, isStandalone: true, selector: "axm-chat-info-bar-assist-model-action", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null }, service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
4384
4738
|
@if (isAssistConversation() && debugModeEnabled()) {
|
|
@@ -4395,7 +4749,7 @@ class AXMChatInfoBarAssistModelActionComponent {
|
|
|
4395
4749
|
}
|
|
4396
4750
|
</div>
|
|
4397
4751
|
}
|
|
4398
|
-
`, isInline: true, styles: [":host{display:block;width:100%}.axm-chat-assist-model-action{width:min(100%,24rem)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type:
|
|
4752
|
+
`, isInline: true, styles: [":host{display:block;width:100%}.axm-chat-assist-model-action{width:min(100%,24rem)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4399
4753
|
}
|
|
4400
4754
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatInfoBarAssistModelActionComponent, decorators: [{
|
|
4401
4755
|
type: Component,
|
|
@@ -4417,20 +4771,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4417
4771
|
`, styles: [":host{display:block;width:100%}.axm-chat-assist-model-action{width:min(100%,24rem)}\n"] }]
|
|
4418
4772
|
}], propDecorators: { conversation: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversation", required: true }] }], service: [{ type: i0.Input, args: [{ isSignal: true, alias: "service", required: false }] }] } });
|
|
4419
4773
|
|
|
4420
|
-
/** True when the conversation is an assist
|
|
4774
|
+
/** True when the conversation is an assist or agent-as-assist chat. */
|
|
4421
4775
|
function conversationHasAssistContext(conversation) {
|
|
4422
|
-
|
|
4423
|
-
if (typeof fromMeta === 'string' && fromMeta.trim().length > 0) {
|
|
4776
|
+
if (axmConversationHasAiChat(conversation)) {
|
|
4424
4777
|
return true;
|
|
4425
4778
|
}
|
|
4426
4779
|
for (const participant of conversation.participants ?? []) {
|
|
4427
4780
|
if (typeof participant.id === 'string' && participant.id.startsWith('assist-')) {
|
|
4428
4781
|
return true;
|
|
4429
4782
|
}
|
|
4430
|
-
const fromParticipant = participant.metadata?.['assistId'];
|
|
4431
|
-
if (typeof fromParticipant === 'string' && fromParticipant.trim().length > 0) {
|
|
4432
|
-
return true;
|
|
4433
|
-
}
|
|
4434
4783
|
}
|
|
4435
4784
|
return false;
|
|
4436
4785
|
}
|
|
@@ -4446,45 +4795,6 @@ const AXM_CHAT_INFO_BAR_ASSIST_MODEL_ACTION = {
|
|
|
4446
4795
|
visible: (context) => conversationHasAssistContext(context.conversation),
|
|
4447
4796
|
};
|
|
4448
4797
|
|
|
4449
|
-
//#region ---- Imports ----
|
|
4450
|
-
//#endregion
|
|
4451
|
-
//#region ---- Dialog ----
|
|
4452
|
-
/**
|
|
4453
|
-
* Opens a read-only specialist sub-run transcript for one delegated {@code agent:*} tool call.
|
|
4454
|
-
* Renders {@link AXPAiChatMessage} lines (role + responses[]) in conversation-owned UI.
|
|
4455
|
-
*/
|
|
4456
|
-
async function axmOpenAssistDelegatedAgentDetailDialog(options) {
|
|
4457
|
-
const callId = options.callId?.trim() ?? '';
|
|
4458
|
-
if (!callId) {
|
|
4459
|
-
return;
|
|
4460
|
-
}
|
|
4461
|
-
const entry = options.delegatedTranscriptsByCallId[callId];
|
|
4462
|
-
const catalogId = axpAiParseSupervisorAgentToolName(options.toolName);
|
|
4463
|
-
const catalogTitle = catalogId != null ? options.resolveCatalogTitle?.(catalogId)?.trim() : undefined;
|
|
4464
|
-
const titleBase = options.resolvedAgentLabel?.trim() ||
|
|
4465
|
-
entry?.agentName?.trim() ||
|
|
4466
|
-
catalogTitle ||
|
|
4467
|
-
options.toolName.trim() ||
|
|
4468
|
-
callId;
|
|
4469
|
-
const [titleSuffix, missingHint] = await Promise.all([
|
|
4470
|
-
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.dialog-title-suffix'),
|
|
4471
|
-
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.transcript-missing'),
|
|
4472
|
-
]);
|
|
4473
|
-
const comp = (await import('./acorex-modules-conversation-assist-delegated-agent-detail-popup.component-DX2JPckF.mjs'))
|
|
4474
|
-
.AXMAssistDelegatedAgentDetailPopupComponent;
|
|
4475
|
-
const data = {
|
|
4476
|
-
messages: entry?.messages ?? [],
|
|
4477
|
-
emptyHint: entry?.messages?.length ? undefined : missingHint,
|
|
4478
|
-
agentTitleById: options.agentTitleById ?? (catalogId && catalogTitle ? { [catalogId]: catalogTitle } : {}),
|
|
4479
|
-
};
|
|
4480
|
-
await options.popupService.open(comp, {
|
|
4481
|
-
title: `${titleBase} — ${titleSuffix ?? 'Full Specialist Run'}`,
|
|
4482
|
-
size: 'lg',
|
|
4483
|
-
data,
|
|
4484
|
-
});
|
|
4485
|
-
}
|
|
4486
|
-
//#endregion
|
|
4487
|
-
|
|
4488
4798
|
/**
|
|
4489
4799
|
* Detects strong RTL scripts (Arabic / Persian / Hebrew and related blocks) in a string
|
|
4490
4800
|
* so each assist transcript segment can set `dir` independently of the app locale.
|
|
@@ -4601,7 +4911,7 @@ class AXMAssistBotImageLineComponent {
|
|
|
4601
4911
|
} @else if (errorText()) {
|
|
4602
4912
|
<p class="axm-assist-bot-image-line__err">{{ ((errorText() ?? '') | translate | async) ?? '' }}</p>
|
|
4603
4913
|
}
|
|
4604
|
-
`, isInline: true, styles: [":host{display:block;max-inline-size:min(100%,40rem)}.axm-assist-bot-image-line__err{margin:0;font-size:.8125rem;color:rgb(var(--ax-sys-color-danger-600, 220 38 38))}\n"], dependencies: [{ kind: "component", type: AXImageRendererComponent, selector: "ax-conversation-image-renderer", inputs: ["message"], outputs: ["imageClick"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type:
|
|
4914
|
+
`, isInline: true, styles: [":host{display:block;max-inline-size:min(100%,40rem)}.axm-assist-bot-image-line__err{margin:0;font-size:.8125rem;color:rgb(var(--ax-sys-color-danger-600, 220 38 38))}\n"], dependencies: [{ kind: "component", type: AXImageRendererComponent, selector: "ax-conversation-image-renderer", inputs: ["message"], outputs: ["imageClick"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4605
4915
|
}
|
|
4606
4916
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMAssistBotImageLineComponent, decorators: [{
|
|
4607
4917
|
type: Component,
|
|
@@ -4774,7 +5084,7 @@ class AXMNodeMessageRendererComponent {
|
|
|
4774
5084
|
</div>
|
|
4775
5085
|
}
|
|
4776
5086
|
</div>
|
|
4777
|
-
`, 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}\n"], dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$3.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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:
|
|
5087
|
+
`, 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}\n"], dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$3.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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 }); }
|
|
4778
5088
|
}
|
|
4779
5089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMNodeMessageRendererComponent, decorators: [{
|
|
4780
5090
|
type: Component,
|
|
@@ -4814,6 +5124,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4814
5124
|
`, styles: [":host{display:block;inline-size:min(100%,28rem)}:host:has(.axm-user-form-renderer--assist-embed){inline-size:100%;max-inline-size:none}\n"] }]
|
|
4815
5125
|
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: false }] }], formSubmitted: [{ type: i0.Output, args: ["formSubmitted"] }] } });
|
|
4816
5126
|
|
|
5127
|
+
//#region ---- Imports ----
|
|
5128
|
+
//#endregion
|
|
5129
|
+
//#region ---- Component ----
|
|
5130
|
+
/**
|
|
5131
|
+
* Renders the user-facing assist answer: ordered segments from the payload line
|
|
5132
|
+
* ({@link axmAssistUserVisibleItemsForLine}).
|
|
5133
|
+
*/
|
|
5134
|
+
class AXMAssistTranscriptUserLineComponent {
|
|
5135
|
+
constructor() {
|
|
5136
|
+
this.line = input.required(...(ngDevMode ? [{ debugName: "line" }] : /* istanbul ignore next */ []));
|
|
5137
|
+
this.parentMessage = input.required(...(ngDevMode ? [{ debugName: "parentMessage" }] : /* istanbul ignore next */ []));
|
|
5138
|
+
this.segmentDir = axmAssistSegmentDirection;
|
|
5139
|
+
this.parseAssistLineText = axmParseAssistTranscriptTextEnvelope;
|
|
5140
|
+
this.axmAssistWidgetNodeFromUnknown = axmAssistWidgetNodeFromUnknown;
|
|
5141
|
+
this.items = computed(() => axmAssistUserVisibleItemsForLine(this.line()), ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
5142
|
+
}
|
|
5143
|
+
syntheticNodeMessage(segIndex, content) {
|
|
5144
|
+
return axmSyntheticEmbedMessage(this.parentMessage(), `user-node-${segIndex}`, {
|
|
5145
|
+
type: 'node',
|
|
5146
|
+
payload: { type: 'node', content },
|
|
5147
|
+
});
|
|
5148
|
+
}
|
|
5149
|
+
markdownCodeLanguage(segment) {
|
|
5150
|
+
if (this.isMarkdownCodeSegment(segment) && segment.language.trim()) {
|
|
5151
|
+
return segment.language;
|
|
5152
|
+
}
|
|
5153
|
+
return 'javascript';
|
|
5154
|
+
}
|
|
5155
|
+
markdownCodeValue(segment) {
|
|
5156
|
+
return this.isMarkdownCodeSegment(segment) ? segment.code : '';
|
|
5157
|
+
}
|
|
5158
|
+
isMarkdownCodeSegment(segment) {
|
|
5159
|
+
if (!segment || typeof segment !== 'object') {
|
|
5160
|
+
return false;
|
|
5161
|
+
}
|
|
5162
|
+
const c = segment;
|
|
5163
|
+
return c.type === 'code' && typeof c.language === 'string' && typeof c.code === 'string';
|
|
5164
|
+
}
|
|
5165
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMAssistTranscriptUserLineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5166
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMAssistTranscriptUserLineComponent, isStandalone: true, selector: "axm-assist-transcript-user-line", inputs: { line: { classPropertyName: "line", publicName: "line", isSignal: true, isRequired: true, transformFunction: null }, parentMessage: { classPropertyName: "parentMessage", publicName: "parentMessage", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"axm-assist-bot axm-assist-bot__final-line\">\n @for (item of items(); track $index; let itemIndex = $index) {\n @switch (item.kind) {\n @case ('text') {\n @let parsed = parseAssistLineText(item.content);\n @if (parsed.body.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsed.body)\">\n <axp-markdown-viewer [markdown]=\"parsed.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n @case ('node') {\n @if (axmAssistWidgetNodeFromUnknown(item.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeMessage(itemIndex, item.content)\" />\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"parentMessage()\"\n [fileId]=\"item.fileId\"\n [mimeType]=\"item.mimeType\"\n [name]=\"item.name\"\n />\n }\n }\n }\n</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot,.axm-assist-bot__final-line{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__delegated-agent-detail-link{padding:.25rem;text-decoration:underline;padding-top:0}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"], dependencies: [{ kind: "component", type: AXMNodeMessageRendererComponent, selector: "axm-chat-user-form-renderer", inputs: ["message", "node"], outputs: ["formSubmitted"] }, { kind: "component", type: AXMAssistBotImageLineComponent, selector: "axm-assist-bot-image-line", inputs: ["parentMessage", "fileId", "mimeType", "name"] }, { kind: "ngmodule", type: AXCodeEditorModule }, { kind: "component", type: i1$4.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
5167
|
+
}
|
|
5168
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMAssistTranscriptUserLineComponent, decorators: [{
|
|
5169
|
+
type: Component,
|
|
5170
|
+
args: [{ selector: 'axm-assist-transcript-user-line', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
5171
|
+
AXMNodeMessageRendererComponent,
|
|
5172
|
+
AXMAssistBotImageLineComponent,
|
|
5173
|
+
AXCodeEditorModule,
|
|
5174
|
+
AXPMarkdownViewerComponent,
|
|
5175
|
+
AXPMarkdownTemplateDirective,
|
|
5176
|
+
FormsModule,
|
|
5177
|
+
], template: "<div class=\"axm-assist-bot axm-assist-bot__final-line\">\n @for (item of items(); track $index; let itemIndex = $index) {\n @switch (item.kind) {\n @case ('text') {\n @let parsed = parseAssistLineText(item.content);\n @if (parsed.body.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(parsed.body)\">\n <axp-markdown-viewer [markdown]=\"parsed.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n @case ('node') {\n @if (axmAssistWidgetNodeFromUnknown(item.content)) {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticNodeMessage(itemIndex, item.content)\" />\n </div>\n }\n }\n @case ('file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"parentMessage()\"\n [fileId]=\"item.fileId\"\n [mimeType]=\"item.mimeType\"\n [name]=\"item.name\"\n />\n }\n }\n }\n</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot,.axm-assist-bot__final-line{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__delegated-agent-detail-link{padding:.25rem;text-decoration:underline;padding-top:0}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"] }]
|
|
5178
|
+
}], propDecorators: { line: [{ type: i0.Input, args: [{ isSignal: true, alias: "line", required: true }] }], parentMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentMessage", required: true }] }] } });
|
|
5179
|
+
|
|
5180
|
+
//#region ---- Imports ----
|
|
5181
|
+
//#endregion
|
|
5182
|
+
//#region ---- Dialog ----
|
|
5183
|
+
/**
|
|
5184
|
+
* Opens a read-only specialist sub-run transcript for one delegated {@code agent:*} tool call.
|
|
5185
|
+
* Renders {@link AXPAiChatMessage} lines (role + responses[]) in conversation-owned UI.
|
|
5186
|
+
*/
|
|
5187
|
+
async function axmOpenAssistDelegatedAgentDetailDialog(options) {
|
|
5188
|
+
const callId = options.callId?.trim() ?? '';
|
|
5189
|
+
if (!callId) {
|
|
5190
|
+
return;
|
|
5191
|
+
}
|
|
5192
|
+
const entry = options.delegatedTranscriptsByCallId[callId];
|
|
5193
|
+
const catalogId = axpAiParseSupervisorAgentToolName(options.toolName);
|
|
5194
|
+
const catalogTitle = catalogId != null ? options.resolveCatalogTitle?.(catalogId)?.trim() : undefined;
|
|
5195
|
+
const titleBase = options.resolvedAgentLabel?.trim() ||
|
|
5196
|
+
entry?.agentName?.trim() ||
|
|
5197
|
+
catalogTitle ||
|
|
5198
|
+
options.toolName.trim() ||
|
|
5199
|
+
callId;
|
|
5200
|
+
const [titleSuffix, missingHint] = await Promise.all([
|
|
5201
|
+
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.dialog-title-suffix'),
|
|
5202
|
+
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.transcript-missing'),
|
|
5203
|
+
]);
|
|
5204
|
+
const comp = (await import('./acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BB5Uyydt.mjs'))
|
|
5205
|
+
.AXMAssistDelegatedAgentDetailPopupComponent;
|
|
5206
|
+
const data = {
|
|
5207
|
+
messages: entry?.messages ?? [],
|
|
5208
|
+
emptyHint: entry?.messages?.length ? undefined : missingHint,
|
|
5209
|
+
agentTitleById: options.agentTitleById ?? (catalogId && catalogTitle ? { [catalogId]: catalogTitle } : {}),
|
|
5210
|
+
};
|
|
5211
|
+
await options.popupService.open(comp, {
|
|
5212
|
+
title: `${titleBase} — ${titleSuffix ?? 'Full Specialist Run'}`,
|
|
5213
|
+
size: 'lg',
|
|
5214
|
+
data,
|
|
5215
|
+
});
|
|
5216
|
+
}
|
|
5217
|
+
//#endregion
|
|
5218
|
+
|
|
4817
5219
|
//#region ---- Imports ----
|
|
4818
5220
|
//#endregion
|
|
4819
5221
|
//#region ---- Component ----
|
|
@@ -4902,23 +5304,18 @@ class AXMAssistMessageRendererComponent {
|
|
|
4902
5304
|
return map;
|
|
4903
5305
|
}, ...(ngDevMode ? [{ debugName: "toolResultByCallId" }] : /* istanbul ignore next */ []));
|
|
4904
5306
|
this.useTranscriptUi = computed(() => this.transcriptLines().length > 0, ...(ngDevMode ? [{ debugName: "useTranscriptUi" }] : /* istanbul ignore next */ []));
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
const disc = payload['type'];
|
|
4911
|
-
if (disc === 'node' && 'content' in payload && axmAssistWidgetNodeFromUnknown(payload['content']) != null) {
|
|
4912
|
-
return { kind: 'node', content: payload['content'] };
|
|
5307
|
+
/** Last transcript line for the non-debug bubble ({@link axmParseAssistTranscriptLinePayload} or engine transcript). */
|
|
5308
|
+
this.assistPayloadLine = computed(() => {
|
|
5309
|
+
const fromPayload = axmParseAssistTranscriptLinePayload(this.message().payload);
|
|
5310
|
+
if (fromPayload) {
|
|
5311
|
+
return fromPayload;
|
|
4913
5312
|
}
|
|
4914
|
-
|
|
4915
|
-
|
|
5313
|
+
const raw = axmReadAssistAiTranscriptRaw(this.message().metadata);
|
|
5314
|
+
if (raw.length > 0) {
|
|
5315
|
+
return axmAssistLastTranscriptLine(raw);
|
|
4916
5316
|
}
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
}
|
|
4920
|
-
return { kind: 'none' };
|
|
4921
|
-
}, ...(ngDevMode ? [{ debugName: "assistPayloadView" }] : /* istanbul ignore next */ []));
|
|
5317
|
+
return null;
|
|
5318
|
+
}, ...(ngDevMode ? [{ debugName: "assistPayloadLine" }] : /* istanbul ignore next */ []));
|
|
4922
5319
|
/**
|
|
4923
5320
|
* Transcript lines that render at least one visible segment. Skips e.g. {@code tool} role lines
|
|
4924
5321
|
* whose results are merged into assistant tool UI (would otherwise produce empty {@code axm-assist-bot__line}).
|
|
@@ -4995,11 +5392,7 @@ class AXMAssistMessageRendererComponent {
|
|
|
4995
5392
|
}, ...(ngDevMode ? [{ debugName: "streamThink" }] : /* istanbul ignore next */ []));
|
|
4996
5393
|
this.streamText = computed(() => {
|
|
4997
5394
|
const d = this.readMeta('streamDraftText');
|
|
4998
|
-
|
|
4999
|
-
return d;
|
|
5000
|
-
}
|
|
5001
|
-
const text = this.message().payload?.['text'];
|
|
5002
|
-
return typeof text === 'string' ? text : '';
|
|
5395
|
+
return typeof d === 'string' ? d : '';
|
|
5003
5396
|
}, ...(ngDevMode ? [{ debugName: "streamText" }] : /* istanbul ignore next */ []));
|
|
5004
5397
|
this.toolCalls = computed(() => {
|
|
5005
5398
|
const raw = this.readMeta('toolCalls');
|
|
@@ -5009,28 +5402,23 @@ class AXMAssistMessageRendererComponent {
|
|
|
5009
5402
|
if (this.isStreaming()) {
|
|
5010
5403
|
return { thinking: null, body: '' };
|
|
5011
5404
|
}
|
|
5012
|
-
const
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5405
|
+
const line = this.assistPayloadLine();
|
|
5406
|
+
if (line) {
|
|
5407
|
+
const textParts = axmAssistUserVisibleItemsForLine(line)
|
|
5408
|
+
.filter((i) => i.kind === 'text')
|
|
5409
|
+
.map((i) => axmParseAssistTranscriptTextEnvelope(i.content).body.trim())
|
|
5410
|
+
.filter((t) => t.length > 0);
|
|
5411
|
+
return { thinking: null, body: textParts.join('\n\n') };
|
|
5412
|
+
}
|
|
5413
|
+
return { thinking: null, body: '' };
|
|
5017
5414
|
}, ...(ngDevMode ? [{ debugName: "parsed" }] : /* istanbul ignore next */ []));
|
|
5018
|
-
/**
|
|
5019
|
-
* Non-debug finalized UI already shows {@link assistPayloadView} (widget or markdown body);
|
|
5020
|
-
* legacy blocks must not duplicate the same answer.
|
|
5021
|
-
*/
|
|
5415
|
+
/** Non-debug finalized UI already shows {@link assistPayloadLine}; debug fallback must not duplicate it. */
|
|
5022
5416
|
this.assistNonDebugPayloadFinalShown = computed(() => {
|
|
5023
5417
|
if (this.showDebugUi() || this.isStreaming()) {
|
|
5024
5418
|
return false;
|
|
5025
5419
|
}
|
|
5026
|
-
const
|
|
5027
|
-
|
|
5028
|
-
return true;
|
|
5029
|
-
}
|
|
5030
|
-
if (v.kind === 'text' && axmParseAssistTranscriptTextEnvelope(v.text).body.trim()) {
|
|
5031
|
-
return true;
|
|
5032
|
-
}
|
|
5033
|
-
return false;
|
|
5420
|
+
const line = this.assistPayloadLine();
|
|
5421
|
+
return line != null && axmAssistUserVisibleItemsForLine(line).length > 0;
|
|
5034
5422
|
}, ...(ngDevMode ? [{ debugName: "assistNonDebugPayloadFinalShown" }] : /* istanbul ignore next */ []));
|
|
5035
5423
|
}
|
|
5036
5424
|
/**
|
|
@@ -5120,13 +5508,6 @@ class AXMAssistMessageRendererComponent {
|
|
|
5120
5508
|
payload: { type: 'node', content },
|
|
5121
5509
|
});
|
|
5122
5510
|
}
|
|
5123
|
-
/** Embeds the finalized assist {@code node} payload for the chat layout renderer (non-debug path). */
|
|
5124
|
-
syntheticFinalPayloadNodeMessage(content) {
|
|
5125
|
-
return axmSyntheticEmbedMessage(this.message(), 'payload-node', {
|
|
5126
|
-
type: 'node',
|
|
5127
|
-
payload: { type: 'node', content },
|
|
5128
|
-
});
|
|
5129
|
-
}
|
|
5130
5511
|
markdownCodeLanguage(segment) {
|
|
5131
5512
|
if (this.isMarkdownCodeSegment(segment) && segment.language.trim()) {
|
|
5132
5513
|
return segment.language;
|
|
@@ -5448,13 +5829,14 @@ class AXMAssistMessageRendererComponent {
|
|
|
5448
5829
|
}
|
|
5449
5830
|
}
|
|
5450
5831
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMAssistMessageRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5451
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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()) {\n <div\n class=\"axm-assist-bot\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div\n class=\"axm-assist-bot__line\"\n [class.axm-assist-bot__line--user]=\"line.role === 'user'\"\n [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\"\n >\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(seg.content)\"\n >\n {{ seg.content }}\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 @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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsedLine.thinking)\"\n >\n {{ parsedLine.thinking }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (displayBody.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(displayBody)\">\n <axp-markdown-viewer [markdown]=\"displayBody\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (\n line.role === 'assistant' &&\n (seg.type === 'agent' || seg.type === 'tool') &&\n isDelegatedAgentCommand(seg.content.command)\n ) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #agentDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!agentDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span\n class=\"axm-assist-renderer__header-actions\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ax-button\n look=\"outline\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </span>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.agent')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @if (parsedOut.body.trim()) {\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsedOut.body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsedOut.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\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-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"outSeg.content.fileId\"\n [mimeType]=\"outSeg.content.mimeType\"\n [name]=\"outSeg.content.name\"\n />\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + $index, outSeg.content)\"\n />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(agentFallbackText)\"\n >\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\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #toolDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistToolKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistToolKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!toolDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.tool')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\"\n />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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\n class=\"axm-assist-bot__fallback axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\"\n >\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\n }\n <!-- @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\" aria-hidden=\"true\"></span>\n } -->\n </div>\n } @else if (!showDebugUi() && !isStreaming()) {\n @let pv = assistPayloadView();\n @if (pv.kind === 'node') {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticFinalPayloadNodeMessage(pv.content)\" />\n </div>\n } @else if (pv.kind === 'text' && parsed().body) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (!showDebugUi() && isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\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\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(streamThink())\"\n >\n {{ streamThink() }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (streamText()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment\" [attr.dir]=\"segmentDir(streamText())\">\n {{ streamText() }}\n </div>\n }\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 @let legacyAgentAns = delegatedAnswerFromToolOutputString(tc.output);\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__agent-accordion axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyAgentAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(tc.id))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(tc.id))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!legacyAgentAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span\n class=\"axm-assist-renderer__accordion-header-title ax-inline-flex ax-items-center ax-gap-2 ax-flex-wrap\"\n >\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyAgentAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n @if (tc.state === 'running') {\n <span\n class=\"axm-assist-renderer__agent-live-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <i class=\"fa-light fa-people-group ax-text-primary-500\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__agent-live-title\">{{\n resolveToolDisplayTitle(tc.name)\n }}</span>\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n @if (tc.state !== 'running') {\n <span\n class=\"axm-assist-renderer__header-actions\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ax-button\n look=\"outline\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(tc.id, tc.name, delegatedAgentLabelForCall(tc.id))\n \"\n ></ax-button>\n </span>\n }\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state !== 'running'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.agent'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div\n class=\"axm-assist-renderer__agent-live-block axm-assist-renderer__agent-live-block--in-accordion\"\n role=\"region\"\n >\n <div\n class=\"axm-assist-renderer__agent-live-prompt\"\n [attr.dir]=\"segmentDir(delegatedPromptPreview(tc.arguments))\"\n >\n {{ delegatedPromptPreview(tc.arguments) }}\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.nestedTools?.length) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n @for (nt of tc.nestedTools; track nt.id) {\n <div class=\"axm-assist-renderer__agent-live-nested-row\">\n @if (nt.state === 'running') {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <code class=\"axm-assist-renderer__agent-live-nested-name\">{{ nt.name }}</code>\n <span class=\"axm-assist-renderer__agent-live-nested-status\">{{\n nt.state === 'running' ? '\u2026' : '\u2713'\n }}</span>\n </div>\n }\n </div>\n }\n @if (legacyAgentAns) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.agent-answer' | translate | async }}\n </div>\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(legacyAgentAns)\"\n >\n {{ legacyAgentAns }}\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyStreamDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyStreamDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state === 'done'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.done'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } @else if (isStreaming() && !streamText().trim() && !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 {\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsed().thinking)\"\n >\n {{ parsed().thinking }}\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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyDoneDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyDoneDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--success\">{{\n (resolveToolBadge(tc.name, '@conversation:chat.assist-renderer.badges.done') | translate | async) ??\n ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment ax-pt-1\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (parsed().body && !assistNonDebugPayloadFinalShown()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer\n class=\"axm-assist-renderer__run-meta-wrap\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\"\n >\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 !ax-mb-0\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\">\n (+{{ totals.cachedPromptTokens | number }}\n {{ '@ai-management:chat.usage-cached' | translate | async }})\n </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</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__header-actions{display:inline-flex;align-items:center}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{color:rgb(var(--ax-sys-color-on-warning-light-surface));background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{color:rgb(var(--ax-sys-color-on-primary-lightest-surface));background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{color:rgb(var(--ax-sys-color-on-success-darker-surface));background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"], dependencies: [{ kind: "component", type: AXTextRendererComponent, 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: AXMAssistBotImageLineComponent, selector: "axm-assist-bot-image-line", inputs: ["parentMessage", "fileId", "mimeType", "name"] }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i1$4.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i1$4.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i1$4.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i1$4.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: AXCodeEditorModule }, { kind: "component", type: i3$1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
5832
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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()) {\n <div\n class=\"axm-assist-bot\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div\n class=\"axm-assist-bot__line\"\n [class.axm-assist-bot__line--user]=\"line.role === 'user'\"\n [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\"\n >\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(seg.content)\"\n >\n {{ seg.content }}\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 @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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsedLine.thinking)\"\n >\n {{ parsedLine.thinking }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (displayBody.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(displayBody)\">\n <axp-markdown-viewer [markdown]=\"displayBody\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (\n line.role === 'assistant' &&\n (seg.type === 'agent' || seg.type === 'tool') &&\n isDelegatedAgentCommand(seg.content.command)\n ) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #agentDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!agentDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.agent')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @if (parsedOut.body.trim()) {\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsedOut.body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsedOut.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\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-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"outSeg.content.fileId\"\n [mimeType]=\"outSeg.content.mimeType\"\n [name]=\"outSeg.content.name\"\n />\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + $index, outSeg.content)\"\n />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(agentFallbackText)\"\n >\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\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'tool' && showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #toolDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistToolKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistToolKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!toolDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.tool')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\"\n />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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\n class=\"axm-assist-bot__fallback axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\"\n >\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\n }\n <!-- @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\" aria-hidden=\"true\"></span>\n } -->\n </div>\n } @else if (!showDebugUi() && !isStreaming()) {\n @if (assistPayloadLine(); as line) {\n <div\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n <axm-assist-transcript-user-line [line]=\"line\" [parentMessage]=\"message()\" />\n </div>\n }\n } @else if (!showDebugUi() && isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\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\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(streamThink())\"\n >\n {{ streamThink() }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (streamText()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment\" [attr.dir]=\"segmentDir(streamText())\">\n {{ streamText() }}\n </div>\n }\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 @let legacyAgentAns = delegatedAnswerFromToolOutputString(tc.output);\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__agent-accordion axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyAgentAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(tc.id))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(tc.id))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!legacyAgentAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span\n class=\"axm-assist-renderer__accordion-header-title ax-inline-flex ax-items-center ax-gap-2 ax-flex-wrap\"\n >\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyAgentAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n @if (tc.state === 'running') {\n <span\n class=\"axm-assist-renderer__agent-live-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <i class=\"fa-light fa-people-group ax-text-primary-500\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__agent-live-title\">{{\n resolveToolDisplayTitle(tc.name)\n }}</span>\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state !== 'running'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.agent'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div\n class=\"axm-assist-renderer__agent-live-block axm-assist-renderer__agent-live-block--in-accordion\"\n role=\"region\"\n >\n <div\n class=\"axm-assist-renderer__agent-live-prompt\"\n [attr.dir]=\"segmentDir(delegatedPromptPreview(tc.arguments))\"\n >\n {{ delegatedPromptPreview(tc.arguments) }}\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.nestedTools?.length) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n @for (nt of tc.nestedTools; track nt.id) {\n <div class=\"axm-assist-renderer__agent-live-nested-row\">\n @if (nt.state === 'running') {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <code class=\"axm-assist-renderer__agent-live-nested-name\">{{ nt.name }}</code>\n <span class=\"axm-assist-renderer__agent-live-nested-status\">{{\n nt.state === 'running' ? '\u2026' : '\u2713'\n }}</span>\n </div>\n }\n </div>\n }\n @if (legacyAgentAns) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.agent-answer' | translate | async }}\n </div>\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(legacyAgentAns)\"\n >\n {{ legacyAgentAns }}\n </div>\n </div>\n }\n </div>\n @if (tc.state !== 'running') {\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(tc.id, tc.name, delegatedAgentLabelForCall(tc.id))\n \"\n ></ax-button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyStreamDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyStreamDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state === 'done'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.done'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } @else if (isStreaming() && !streamText().trim() && !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 {\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsed().thinking)\"\n >\n {{ parsed().thinking }}\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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyDoneDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyDoneDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--success\">{{\n (resolveToolBadge(tc.name, '@conversation:chat.assist-renderer.badges.done') | translate | async) ??\n ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment ax-pt-1\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (parsed().body && !assistNonDebugPayloadFinalShown()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer\n class=\"axm-assist-renderer__run-meta-wrap\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\"\n >\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 !ax-mb-0\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\">\n (+{{ totals.cachedPromptTokens | number }}\n {{ '@ai-management:chat.usage-cached' | translate | async }})\n </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</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot,.axm-assist-bot__final-line{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__delegated-agent-detail-link{padding:.25rem;text-decoration:underline;padding-top:0}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"], dependencies: [{ kind: "component", type: AXTextRendererComponent, 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: AXMAssistTranscriptUserLineComponent, selector: "axm-assist-transcript-user-line", inputs: ["line", "parentMessage"] }, { kind: "component", type: AXMAssistBotImageLineComponent, selector: "axm-assist-bot-image-line", inputs: ["parentMessage", "fileId", "mimeType", "name"] }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i1$5.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i1$5.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i1$5.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i1$5.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.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: AXCodeEditorModule }, { kind: "component", type: i1$4.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXTranslationModule }, { 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 }); }
|
|
5452
5833
|
}
|
|
5453
5834
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMAssistMessageRendererComponent, decorators: [{
|
|
5454
5835
|
type: Component,
|
|
5455
5836
|
args: [{ selector: 'axm-assist-message-renderer', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
5456
5837
|
AXTextRendererComponent,
|
|
5457
5838
|
AXMNodeMessageRendererComponent,
|
|
5839
|
+
AXMAssistTranscriptUserLineComponent,
|
|
5458
5840
|
AXMAssistBotImageLineComponent,
|
|
5459
5841
|
AXAccordionCdkModule,
|
|
5460
5842
|
AXButtonModule,
|
|
@@ -5465,13 +5847,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5465
5847
|
AXTranslationModule,
|
|
5466
5848
|
AsyncPipe,
|
|
5467
5849
|
DecimalPipe,
|
|
5468
|
-
], template: "<div class=\"axm-assist-renderer\">\n @if (showDebugUi() && useTranscriptUi()) {\n <div\n class=\"axm-assist-bot\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div\n class=\"axm-assist-bot__line\"\n [class.axm-assist-bot__line--user]=\"line.role === 'user'\"\n [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\"\n >\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(seg.content)\"\n >\n {{ seg.content }}\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 @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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsedLine.thinking)\"\n >\n {{ parsedLine.thinking }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (displayBody.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(displayBody)\">\n <axp-markdown-viewer [markdown]=\"displayBody\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (\n line.role === 'assistant' &&\n (seg.type === 'agent' || seg.type === 'tool') &&\n isDelegatedAgentCommand(seg.content.command)\n ) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #agentDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!agentDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span\n class=\"axm-assist-renderer__header-actions\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ax-button\n look=\"outline\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </span>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.agent')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @if (parsedOut.body.trim()) {\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsedOut.body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsedOut.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\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-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"outSeg.content.fileId\"\n [mimeType]=\"outSeg.content.mimeType\"\n [name]=\"outSeg.content.name\"\n />\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + $index, outSeg.content)\"\n />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(agentFallbackText)\"\n >\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\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #toolDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistToolKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistToolKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!toolDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.tool')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\"\n />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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\n class=\"axm-assist-bot__fallback axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\"\n >\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\n }\n <!-- @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\" aria-hidden=\"true\"></span>\n } -->\n </div>\n } @else if (!showDebugUi() && !isStreaming()) {\n @let pv = assistPayloadView();\n @if (pv.kind === 'node') {\n <div class=\"axm-assist-bot__segment\" dir=\"auto\">\n <axm-chat-user-form-renderer [message]=\"syntheticFinalPayloadNodeMessage(pv.content)\" />\n </div>\n } @else if (pv.kind === 'text' && parsed().body) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (!showDebugUi() && isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\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\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(streamThink())\"\n >\n {{ streamThink() }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (streamText()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment\" [attr.dir]=\"segmentDir(streamText())\">\n {{ streamText() }}\n </div>\n }\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 @let legacyAgentAns = delegatedAnswerFromToolOutputString(tc.output);\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__agent-accordion axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyAgentAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(tc.id))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(tc.id))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!legacyAgentAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span\n class=\"axm-assist-renderer__accordion-header-title ax-inline-flex ax-items-center ax-gap-2 ax-flex-wrap\"\n >\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyAgentAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n @if (tc.state === 'running') {\n <span\n class=\"axm-assist-renderer__agent-live-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <i class=\"fa-light fa-people-group ax-text-primary-500\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__agent-live-title\">{{\n resolveToolDisplayTitle(tc.name)\n }}</span>\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n @if (tc.state !== 'running') {\n <span\n class=\"axm-assist-renderer__header-actions\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ax-button\n look=\"outline\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(tc.id, tc.name, delegatedAgentLabelForCall(tc.id))\n \"\n ></ax-button>\n </span>\n }\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state !== 'running'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.agent'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div\n class=\"axm-assist-renderer__agent-live-block axm-assist-renderer__agent-live-block--in-accordion\"\n role=\"region\"\n >\n <div\n class=\"axm-assist-renderer__agent-live-prompt\"\n [attr.dir]=\"segmentDir(delegatedPromptPreview(tc.arguments))\"\n >\n {{ delegatedPromptPreview(tc.arguments) }}\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.nestedTools?.length) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n @for (nt of tc.nestedTools; track nt.id) {\n <div class=\"axm-assist-renderer__agent-live-nested-row\">\n @if (nt.state === 'running') {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <code class=\"axm-assist-renderer__agent-live-nested-name\">{{ nt.name }}</code>\n <span class=\"axm-assist-renderer__agent-live-nested-status\">{{\n nt.state === 'running' ? '\u2026' : '\u2713'\n }}</span>\n </div>\n }\n </div>\n }\n @if (legacyAgentAns) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.agent-answer' | translate | async }}\n </div>\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(legacyAgentAns)\"\n >\n {{ legacyAgentAns }}\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyStreamDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyStreamDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state === 'done'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.done'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } @else if (isStreaming() && !streamText().trim() && !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 {\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsed().thinking)\"\n >\n {{ parsed().thinking }}\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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyDoneDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyDoneDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--success\">{{\n (resolveToolBadge(tc.name, '@conversation:chat.assist-renderer.badges.done') | translate | async) ??\n ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment ax-pt-1\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (parsed().body && !assistNonDebugPayloadFinalShown()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer\n class=\"axm-assist-renderer__run-meta-wrap\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\"\n >\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 !ax-mb-0\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\">\n (+{{ totals.cachedPromptTokens | number }}\n {{ '@ai-management:chat.usage-cached' | translate | async }})\n </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</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__header-actions{display:inline-flex;align-items:center}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{color:rgb(var(--ax-sys-color-on-warning-light-surface));background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{color:rgb(var(--ax-sys-color-on-primary-lightest-surface));background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{color:rgb(var(--ax-sys-color-on-success-darker-surface));background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"] }]
|
|
5850
|
+
], template: "<div class=\"axm-assist-renderer\">\n @if (showDebugUi() && useTranscriptUi()) {\n <div\n class=\"axm-assist-bot\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n @for (item of visibleTranscriptLines(); track item.lineIndex) {\n @let line = item.line;\n @let lineIndex = item.lineIndex;\n <div\n class=\"axm-assist-bot__line\"\n [class.axm-assist-bot__line--user]=\"line.role === 'user'\"\n [class.axm-assist-bot__line--tool-role]=\"line.role === 'tool'\"\n >\n @for (seg of line.responses; track segIndex; let segIndex = $index) {\n @if (line.role === 'user' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(seg.content)\"\n >\n {{ seg.content }}\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 @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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkKey(lineIndex, segIndex))\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkKey(lineIndex, segIndex))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsedLine.thinking)\"\n >\n {{ parsedLine.thinking }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (displayBody.trim()) {\n <div class=\"axm-assist-bot__segment axm-assist-renderer__markdown\" [attr.dir]=\"segmentDir(displayBody)\">\n <axp-markdown-viewer [markdown]=\"displayBody\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n } @else if (\n line.role === 'assistant' &&\n (seg.type === 'agent' || seg.type === 'tool') &&\n isDelegatedAgentCommand(seg.content.command)\n ) {\n @if (showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #agentDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!agentDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.agent')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n } @else {\n @let res = toolResultForCallId(seg.callId);\n @let outcomeSegs = delegatedAgentOutcomeSegmentsForCall(res);\n @if (outcomeSegs.length > 0) {\n @for (outSeg of outcomeSegs; track $index) {\n @switch (outSeg.type) {\n @case ('text') {\n @let parsedOut = parseAssistLineText(outSeg.content);\n @if (parsedOut.body.trim()) {\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsedOut.body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsedOut.body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\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-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"outSeg.content.fileId\"\n [mimeType]=\"outSeg.content.mimeType\"\n [name]=\"outSeg.content.name\"\n />\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex * 1000 + $index, outSeg.content)\"\n />\n </div>\n }\n }\n }\n }\n } @else if (delegatedAgentAnswerForCall(res).trim()) {\n @let agentFallbackText = delegatedAgentAnswerForCall(res);\n <div\n class=\"axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(agentFallbackText)\"\n >\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\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ?? ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(\n seg.callId,\n seg.content.command,\n delegatedAgentLabelForCall(seg.callId)\n )\n \"\n ></ax-button>\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'tool' && showDebugUi()) {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell !ax-mb-0\"\n axAccordionItem\n #toolDebugAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistToolKey(seg.callId))\"\n (onClick)=\"onAssistAccordionClick($event, assistToolKey(seg.callId))\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!toolDebugAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(seg.content.command) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--primary\">{{\n (resolveToolBadge(seg.content.command, '@conversation:chat.assist-renderer.badges.tool')\n | translate\n | async) ?? ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(seg.content.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (toolResultForCallId(seg.callId); as resultLine) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatToolResultBody(resultLine)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\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\n [message]=\"syntheticNodeEmbedMessage(lineIndex, segIndex, seg.content)\"\n />\n </div>\n }\n } @else if (line.role === 'assistant' && seg.type === 'file') {\n <axm-assist-bot-image-line\n [parentMessage]=\"message()\"\n [fileId]=\"seg.content.fileId\"\n [mimeType]=\"seg.content.mimeType\"\n [name]=\"seg.content.name\"\n />\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\n class=\"axm-assist-bot__fallback axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(formatFallbackSegment(seg))\"\n >\n {{ formatFallbackSegment(seg) }}\n </div>\n }\n }\n }\n </div>\n }\n @if (isStreaming()) {\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\n }\n <!-- @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\" aria-hidden=\"true\"></span>\n } -->\n </div>\n } @else if (!showDebugUi() && !isStreaming()) {\n @if (assistPayloadLine(); as line) {\n <div\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.assistant-response' | translate | async) ?? ''\"\n >\n <axm-assist-transcript-user-line [line]=\"line\" [parentMessage]=\"message()\" />\n </div>\n }\n } @else if (!showDebugUi() && isStreaming()) {\n <div class=\"axm-assist-renderer__stream-content axm-assist-renderer__stream-content--non-debug\">\n <div class=\"axm-assist-renderer__streaming-activity\" role=\"status\" aria-live=\"polite\">\n <span\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</span>\n </div>\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\n class=\"axm-assist-renderer__activity-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"axm-assist-renderer__activity-label ax-text-xs ax-text-muted ax-italic\">{{\n assistActivityMessageKey() | translate | async\n }}</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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkStreamKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkStreamKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(streamThink())\"\n >\n {{ streamThink() }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (streamText()) {\n <div class=\"axm-assist-renderer__text axm-assist-bot__segment\" [attr.dir]=\"segmentDir(streamText())\">\n {{ streamText() }}\n </div>\n }\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 @let legacyAgentAns = delegatedAnswerFromToolOutputString(tc.output);\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__agent-accordion axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyAgentAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistAgentKey(tc.id))\"\n (onClick)=\"onAssistAccordionClick($event, assistAgentKey(tc.id))\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!legacyAgentAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span\n class=\"axm-assist-renderer__accordion-header-title ax-inline-flex ax-items-center ax-gap-2 ax-flex-wrap\"\n >\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyAgentAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n @if (tc.state === 'running') {\n <span\n class=\"axm-assist-renderer__agent-live-spin ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-3 ax-h-3 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <i class=\"fa-light fa-people-group ax-text-primary-500\" aria-hidden=\"true\"></i>\n <span class=\"axm-assist-renderer__agent-live-title\">{{\n resolveToolDisplayTitle(tc.name)\n }}</span>\n </span>\n </div>\n <div class=\"axm-assist-renderer__header-trailing\">\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state !== 'running'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.agent'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div\n class=\"axm-assist-renderer__agent-live-block axm-assist-renderer__agent-live-block--in-accordion\"\n role=\"region\"\n >\n <div\n class=\"axm-assist-renderer__agent-live-prompt\"\n [attr.dir]=\"segmentDir(delegatedPromptPreview(tc.arguments))\"\n >\n {{ delegatedPromptPreview(tc.arguments) }}\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.nestedTools?.length) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n @for (nt of tc.nestedTools; track nt.id) {\n <div class=\"axm-assist-renderer__agent-live-nested-row\">\n @if (nt.state === 'running') {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-border-2 ax-border-primary-500 ax-border-t-transparent fa-spin ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span\n class=\"ax-inline-block ax-w-2.5 ax-h-2.5 ax-rounded-full ax-bg-success-500 ax-shrink-0\"\n aria-hidden=\"true\"\n ></span>\n }\n <code class=\"axm-assist-renderer__agent-live-nested-name\">{{ nt.name }}</code>\n <span class=\"axm-assist-renderer__agent-live-nested-status\">{{\n nt.state === 'running' ? '\u2026' : '\u2713'\n }}</span>\n </div>\n }\n </div>\n }\n @if (legacyAgentAns) {\n <div class=\"axm-assist-renderer__agent-live-nested-tools\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.agent-answer' | translate | async }}\n </div>\n <div\n class=\"axm-assist-renderer__agent-live-stream\"\n [attr.dir]=\"segmentDir(legacyAgentAns)\"\n >\n {{ legacyAgentAns }}\n </div>\n </div>\n }\n </div>\n @if (tc.state !== 'running') {\n <div class=\"axm-assist-renderer__delegated-agent-detail-link\">\n <ax-button\n look=\"link\"\n color=\"primary\"\n class=\"ax-sm\"\n [text]=\"('@conversation:chat.assist-renderer.delegated-agent.detail' | translate | async) ?? ''\"\n [attr.aria-label]=\"\n ('@conversation:chat.assist-renderer.delegated-agent.detail-aria' | translate | async) ??\n ''\n \"\n (onClick)=\"\n openDelegatedAgentTranscriptDialog(tc.id, tc.name, delegatedAgentLabelForCall(tc.id))\n \"\n ></ax-button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"axm-assist-renderer__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyStreamDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyStreamDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span\n class=\"axm-assist-renderer__badge\"\n [class.axm-assist-renderer__badge--primary]=\"tc.state === 'running'\"\n [class.axm-assist-renderer__badge--success]=\"tc.state === 'done'\"\n >\n {{\n (resolveToolBadge(\n tc.name,\n tc.state === 'running'\n ? '@conversation:chat.assist-renderer.badges.running'\n : '@conversation:chat.assist-renderer.badges.done'\n )\n | translate\n | async) ?? ''\n }}\n </span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n @if (isStreaming() && streamText().trim()) {\n <span class=\"axm-assist-renderer__cursor\"></span>\n } @else if (isStreaming() && !streamText().trim() && !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 {\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 !ax-mb-0\"\n axAccordionItem\n #thinkAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistThinkFinalKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistThinkFinalKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!thinkAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!thinkAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\n class=\"axm-assist-renderer__thinking-body axm-assist-bot__segment\"\n [attr.dir]=\"segmentDir(parsed().thinking)\"\n >\n {{ parsed().thinking }}\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__accordion-group\" axAccordionGroup [accordion]=\"false\">\n <div\n class=\"axm-assist-renderer__tool-card axm-assist-renderer__collapse-shell\"\n axAccordionItem\n #legacyDoneDbgAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistLegacyToolAccordionKey(tc))\"\n (onClick)=\"onAssistLegacyAccordionClick($event, tc)\"\n >\n <div class=\"axm-assist-renderer__accordion-header\" axAccordionItemHeader>\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!legacyDoneDbgAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></i>\n <i class=\"fa-light fa-screwdriver-wrench axm-assist-renderer__tool-title-icon\"></i>\n {{ resolveToolDisplayTitle(tc.name) }}\n </span>\n </div>\n <span class=\"axm-assist-renderer__badge axm-assist-renderer__badge--success\">{{\n (resolveToolBadge(tc.name, '@conversation:chat.assist-renderer.badges.done') | translate | async) ??\n ''\n }}</span>\n </div>\n <div axAccordionItemContent>\n <div class=\"axm-assist-renderer__collapse-body\">\n <div class=\"axm-assist-renderer__tool-body\">\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.input' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatArgs(tc.arguments)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n @if (tc.nestedStreamText?.trim()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment ax-pt-1\"\n [attr.dir]=\"segmentDir(tc.nestedStreamText ?? '')\"\n >\n {{ tc.nestedStreamText }}\n </div>\n }\n @if (tc.output) {\n <div class=\"axm-assist-renderer__tool-section-label\">\n {{ '@conversation:chat.assist-renderer.sections.output' | translate | async }}\n </div>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"formatJson(tc.output)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (parsed().body && !assistNonDebugPayloadFinalShown()) {\n <div\n class=\"axm-assist-renderer__text axm-assist-bot__segment axm-assist-renderer__markdown\"\n [attr.dir]=\"segmentDir(parsed().body)\"\n >\n <axp-markdown-viewer [markdown]=\"parsed().body\">\n <ng-template axpMarkdownTemplate=\"code\" let-segment>\n <div class=\"axm-assist-renderer__tool-editor-wrap\" style=\"direction: ltr\">\n <ax-code-editor\n [ngModel]=\"markdownCodeValue(segment)\"\n [readonly]=\"true\"\n [language]=\"markdownCodeLanguage(segment)\"\n [lineNumbers]=\"true\"\n class=\"axm-assist-renderer__tool-editor\"\n ></ax-code-editor>\n </div>\n </ng-template>\n </axp-markdown-viewer>\n </div>\n }\n }\n }\n @if (showDebugUi() && assistRunDebug(); as dbg) {\n <footer\n class=\"axm-assist-renderer__run-meta-wrap\"\n role=\"region\"\n [attr.aria-label]=\"('@conversation:chat.assist-renderer.aria.run-usage' | translate | async) ?? ''\"\n >\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 !ax-mb-0\"\n axAccordionItem\n #runMetaAcc=\"axAccordionItem\"\n [isCollapsed]=\"assistSectionIsCollapsed(assistRunMetaKey())\"\n (onClick)=\"onAssistAccordionClick($event, assistRunMetaKey())\"\n >\n <div\n class=\"axm-assist-renderer__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n [attr.aria-expanded]=\"!runMetaAcc.isCollapsed()\"\n >\n <div class=\"axm-assist-renderer__accordion-header-main\">\n <span class=\"axm-assist-renderer__accordion-header-title\">\n <i\n class=\"fa-light fa-chevron-down axm-assist-renderer__thinking-chevron\"\n [class.axm-assist-renderer__thinking-chevron--expanded]=\"!runMetaAcc.isCollapsed()\"\n aria-hidden=\"true\"\n ></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\">\n (+{{ totals.cachedPromptTokens | number }}\n {{ '@ai-management:chat.usage-cached' | translate | async }})\n </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</div>\n", styles: [".axm-assist-renderer{display:flex;flex-direction:column;gap:.5rem}.axm-assist-bot,.axm-assist-bot__final-line{display:flex;flex-direction:column;gap:.75rem}.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__line--user{align-self:flex-end}.axm-assist-bot__line--tool-role{align-self:stretch}.axm-assist-bot__tool-result{border-radius:.5rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.5rem .75rem}.axm-assist-bot__fallback{font-size:.88rem;line-height:1.75;word-break:break-word;opacity:.9}.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}@keyframes axm-blink{0%{opacity:1}50%{opacity:0}}.axm-assist-renderer__stream-content{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__streaming-activity{display:flex;align-items:center;gap:.5rem;padding-block:.15rem}.axm-assist-renderer__activity-label{line-height:1.45}.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-bot__segment ax-conversation-text-renderer{display:block}.axm-assist-bot__segment ax-conversation-text-renderer :is(p,ul,ol){margin-block:.45rem}.axm-assist-bot__segment ax-conversation-text-renderer li{line-height:1.8}.axm-assist-renderer__accordion-group{width:100%}.axm-assist-renderer__collapse-shell{border-radius:.625rem;overflow:hidden;background:rgb(var(--ax-sys-color-lighter-surface))}.axm-assist-renderer__collapse-body{margin:0;padding:0;border-radius:0 0 .5rem .5rem;background:transparent}.axm-assist-renderer__collapse-body>.axm-assist-renderer__agent-live-block--in-accordion{padding-inline:.5rem;padding-block-end:.35rem}.axm-assist-renderer__accordion-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;cursor:pointer;background:transparent;border:none;border-radius:.625rem .625rem 0 0;transition:background-color .15s ease}.axm-assist-renderer__collapse-shell>.axm-assist-renderer__accordion-header:hover{background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__accordion-header-main{min-inline-size:0;display:flex;flex-direction:column;gap:.1rem}.axm-assist-renderer__accordion-header-title{font-size:.8125rem;line-height:1.25;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));display:inline-flex;align-items:center;gap:.4rem}.axm-assist-renderer__header-trailing{flex-shrink:0;display:inline-flex;align-items:center;gap:.35rem}.axm-assist-renderer__delegated-agent-detail-link{padding:.25rem;text-decoration:underline;padding-top:0}.axm-assist-renderer__badge{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;max-width:min(100%,14rem);padding:.1875rem .65rem;border-radius:9999px;font-size:.6875rem;font-weight:600;line-height:1.3;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__badge--warning{background:rgb(var(--ax-sys-color-warning-100))}.axm-assist-renderer__badge--primary{background:rgb(var(--ax-sys-color-primary-100))}.axm-assist-renderer__badge--success{background:rgb(var(--ax-sys-color-success-100))}.axm-assist-renderer__thinking-chevron{display:inline-block;font-size:.65rem;opacity:.65;transition:transform .2s ease;line-height:1;flex-shrink:0}.axm-assist-renderer__thinking-chevron--expanded{transform:rotate(180deg)}.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__tools{display:flex;flex-direction:column;gap:.5rem}.axm-assist-renderer__tool-card{border-radius:.625rem;overflow:hidden}.axm-assist-renderer__tool-body{padding:.625rem .75rem .75rem;display:flex;flex-direction:column;gap:.35rem}.axm-assist-renderer__tool-section-label{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700))}.axm-assist-renderer__tool-pre{margin:0;max-block-size:10rem;overflow:auto;border-radius:.375rem;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__run-meta-wrap{margin-block-start:.45rem}.axm-assist-renderer__run-meta-header-sub{font-size:.7rem;line-height:1.35;color:rgb(var(--ax-sys-color-neutral-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.axm-assist-renderer__run-meta{margin-block-start:.45rem;padding:.55rem .65rem .6rem;border-radius:.625rem;background:rgb(var(--ax-sys-color-lighter-surface));display:flex;flex-direction:column;gap:.45rem}.axm-assist-renderer__run-meta--panel{margin-block-start:0;padding:.45rem .5rem .55rem;background:transparent;border-radius:0}.axm-assist-renderer__run-meta-grid{display:flex;gap:.4rem}.axm-assist-renderer__meta-tile{min-width:0;padding:.4rem .5rem .45rem;border-radius:.45rem;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__meta-tile--wide{grid-column:1/-1}.axm-assist-renderer__meta-tile--accent{background:rgb(var(--ax-sys-color-primary-50))}.axm-assist-renderer__meta-tile-label{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgb(var(--ax-sys-color-neutral-700));margin-block-end:.2rem}.axm-assist-renderer__meta-tile-value{font-size:.78rem;font-weight:600;line-height:1.35;color:rgb(var(--ax-sys-color-on-surface));word-break:break-word}.axm-assist-renderer__meta-tile-value--mono{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.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__meta-tile-note{display:inline;margin-inline-start:.2rem;font-size:.65rem;font-weight:500;color:rgb(var(--ax-sys-color-success-700))}.axm-assist-renderer__tool-editor-wrap{border-radius:.375rem;overflow:hidden;background:rgb(var(--ax-sys-color-light-surface))}.axm-assist-renderer__waiting{display:flex;gap:.25rem;padding:.25rem 0}.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__dot:nth-child(2){animation-delay:.2s}.axm-assist-renderer__dot:nth-child(3){animation-delay:.4s}.axm-assist-renderer__agent-live-block{border-radius:.75rem;background:rgb(var(--ax-sys-color-lighter-surface));padding:.75rem .875rem;display:flex;flex-direction:column;gap:.65rem;max-inline-size:min(42rem,100%)}.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__agent-live-header{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}.axm-assist-renderer__agent-live-title{font-size:.8125rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface));flex:1;min-inline-size:0}.axm-assist-renderer__agent-live-prompt{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));align-self:flex-end;max-inline-size:min(92%,36rem)}.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__agent-live-nested-tools{display:flex;flex-direction:column;gap:.35rem;padding-block-start:.35rem}.axm-assist-renderer__agent-live-nested-row{display:flex;align-items:center;gap:.45rem;font-size:.72rem}.axm-assist-renderer__agent-live-nested-name{font-family:var(--ax-font-mono, monospace);font-size:.7rem;flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis}.axm-assist-renderer__agent-live-nested-status{color:rgb(var(--ax-sys-color-neutral-600));flex-shrink:0}\n"] }]
|
|
5469
5851
|
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }] } });
|
|
5470
5852
|
|
|
5471
5853
|
/**
|
|
5472
5854
|
* Renderer for AI assist (bot) responses.
|
|
5473
5855
|
*
|
|
5474
|
-
* When `metadata.
|
|
5856
|
+
* When `metadata.transcripts` / `metadata.transcriptDraft` contains
|
|
5475
5857
|
* `AXPAiChatMessage` lines, the UI maps each line by `role` and
|
|
5476
5858
|
* segment `type` inside `responses` to the same building blocks as the AI chat page (text,
|
|
5477
5859
|
* image, tool cards, tool results, layout nodes). Otherwise it falls back
|
|
@@ -5732,7 +6114,7 @@ class AXMChatNotificationContentComponent {
|
|
|
5732
6114
|
<ax-button (onClick)="goToChat($event)" [text]="'Go to Chat'"></ax-button> -->
|
|
5733
6115
|
</div>
|
|
5734
6116
|
</div>
|
|
5735
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type:
|
|
6117
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5736
6118
|
}
|
|
5737
6119
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatNotificationContentComponent, decorators: [{
|
|
5738
6120
|
type: Component,
|
|
@@ -5866,7 +6248,7 @@ class AXMCommentsPageComponentProvider {
|
|
|
5866
6248
|
return [
|
|
5867
6249
|
{
|
|
5868
6250
|
key: COMMENTS_PAGE_COMPONENT_KEY,
|
|
5869
|
-
loader: () => import('./acorex-modules-conversation-comments-page.component-
|
|
6251
|
+
loader: () => import('./acorex-modules-conversation-comments-page.component-QnDogSDy.mjs').then((m) => m.AXMCommentsPageComponent),
|
|
5870
6252
|
},
|
|
5871
6253
|
];
|
|
5872
6254
|
}
|
|
@@ -5953,7 +6335,7 @@ function routesFactory() {
|
|
|
5953
6335
|
}
|
|
5954
6336
|
class AXMConversationModule {
|
|
5955
6337
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
5956
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationModule, imports: [AXPWidgetCoreModule, i1$
|
|
6338
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationModule, imports: [AXPWidgetCoreModule, i1$6.AXPWorkflowModule,
|
|
5957
6339
|
// Entity Modules
|
|
5958
6340
|
AXMConversationTabEntityModule,
|
|
5959
6341
|
AXMRoomEntityModule,
|
|
@@ -6032,6 +6414,22 @@ class AXMConversationModule {
|
|
|
6032
6414
|
useClass: AXMConversationWidgetsProvider,
|
|
6033
6415
|
multi: true,
|
|
6034
6416
|
},
|
|
6417
|
+
{
|
|
6418
|
+
provide: AXP_SEARCH_PROVIDER,
|
|
6419
|
+
useClass: AXMConversationAssistSearchProvider,
|
|
6420
|
+
multi: true,
|
|
6421
|
+
},
|
|
6422
|
+
{
|
|
6423
|
+
provide: AXP_SEARCH_DEFINITION_PROVIDER,
|
|
6424
|
+
useClass: AXMConversationAssistSearchDefinitionProvider,
|
|
6425
|
+
multi: true,
|
|
6426
|
+
},
|
|
6427
|
+
provideCommandSetups([
|
|
6428
|
+
{
|
|
6429
|
+
key: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
6430
|
+
command: () => import('./acorex-modules-conversation-start-assist-chat.command-DRlWzEDp.mjs').then((m) => m.AXMConversationStartAssistChatCommand),
|
|
6431
|
+
},
|
|
6432
|
+
]),
|
|
6035
6433
|
], imports: [AXPWidgetCoreModule,
|
|
6036
6434
|
AXPWorkflowModule.forChild({
|
|
6037
6435
|
actions: {
|
|
@@ -6143,6 +6541,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
6143
6541
|
useClass: AXMConversationWidgetsProvider,
|
|
6144
6542
|
multi: true,
|
|
6145
6543
|
},
|
|
6544
|
+
{
|
|
6545
|
+
provide: AXP_SEARCH_PROVIDER,
|
|
6546
|
+
useClass: AXMConversationAssistSearchProvider,
|
|
6547
|
+
multi: true,
|
|
6548
|
+
},
|
|
6549
|
+
{
|
|
6550
|
+
provide: AXP_SEARCH_DEFINITION_PROVIDER,
|
|
6551
|
+
useClass: AXMConversationAssistSearchDefinitionProvider,
|
|
6552
|
+
multi: true,
|
|
6553
|
+
},
|
|
6554
|
+
provideCommandSetups([
|
|
6555
|
+
{
|
|
6556
|
+
key: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
6557
|
+
command: () => import('./acorex-modules-conversation-start-assist-chat.command-DRlWzEDp.mjs').then((m) => m.AXMConversationStartAssistChatCommand),
|
|
6558
|
+
},
|
|
6559
|
+
]),
|
|
6146
6560
|
],
|
|
6147
6561
|
}]
|
|
6148
6562
|
}] });
|
|
@@ -6151,5 +6565,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
6151
6565
|
* Generated bundle index. Do not edit.
|
|
6152
6566
|
*/
|
|
6153
6567
|
|
|
6154
|
-
export {
|
|
6155
|
-
//# sourceMappingURL=acorex-modules-conversation-acorex-modules-conversation-
|
|
6568
|
+
export { roomFactory as $, AXMChatAssistLauncherService as A, AXMConversationModule as B, AXMConversationTabEntityModule as C, AXMConversationTabService as D, AXMConversationTabServiceImpl as E, AXMMessageEntityModule as F, AXMMessageService as G, AXMMessageServiceImpl as H, AXMPermissionsKeys as I, AXMRoomEntityModule as J, AXMRoomService as K, AXMRoomServiceImpl as L, AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE as M, AXPCommentWidget as N, COMMENTS_PAGE_COMPONENT_KEY as O, axmAssistLastTranscriptLine as P, axmAssistUserVisibleItemsForLine as Q, RootConfig as R, axmBuildAssistTranscriptLinePayload as S, axmIsAssistPeerParticipant as T, axmNormalizeAssistTranscriptForChatUi as U, axmNormalizeAssistTranscriptLineResponses as V, axmParseAssistTranscriptLinePayload as W, axmReadAssistAiTranscript as X, axmReadAssistAiTranscriptRaw as Y, commentsPlugin as Z, messageFactory as _, AXMCommentComponent as a, tabFactory as a0, axmAssistSegmentDirection as b, axmParseAssistTranscriptTextEnvelope as c, axmAssistWidgetNodeFromUnknown as d, axmSyntheticEmbedMessage as e, AXMNodeMessageRendererComponent as f, AXMAssistBotImageLineComponent as g, AXMChatComponent as h, AXMChatConversationApi as i, AXMChatManagementService as j, AXMChatMessageApi as k, AXMChatRealtimeApi as l, AXMChatRealtimeService as m, AXMChatRealtimeServiceImpl as n, AXMChatService as o, AXMChatServiceImpl as p, AXMChatUserApi as q, AXMCommentManagementService as r, AXMCommentPopupComponent as s, AXMCommentPopupStartAction as t, AXMCommentPopupWorkflow as u, AXMCommentRealtimeService as v, AXMCommentRealtimeServiceImpl as w, AXMCommentService as x, AXMCommentServiceImpl as y, AXMCommentWidgetViewComponent as z };
|
|
6569
|
+
//# sourceMappingURL=acorex-modules-conversation-acorex-modules-conversation-F7nQo1GU.mjs.map
|