@c8y/ngx-components 1024.15.16 → 1024.16.5
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/c8y-ngx-components-ai-agent-chat.mjs +303 -63
- package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-agents-html.mjs +9 -0
- package/fesm2022/c8y-ngx-components-ai-agents-html.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-agents-scada.mjs +4 -0
- package/fesm2022/c8y-ngx-components-ai-agents-scada.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +394 -52
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai.mjs +329 -19
- package/fesm2022/c8y-ngx-components-ai.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +4 -0
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +95 -76
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +92 -47
- package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +25 -4
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-time-context.mjs +13 -9
- package/fesm2022/c8y-ngx-components-time-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +3 -2
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +4 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs +3 -2
- package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +65 -14
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/locales/de.po +147 -16
- package/locales/es.po +143 -11
- package/locales/fr.po +459 -324
- package/locales/ja_JP.po +143 -11
- package/locales/ko.po +143 -11
- package/locales/locales.pot +136 -10
- package/locales/nl.po +143 -11
- package/locales/pl.po +143 -11
- package/locales/pt_BR.po +143 -11
- package/locales/zh_CN.po +143 -11
- package/locales/zh_TW.po +143 -11
- package/package.json +1 -1
- package/types/c8y-ngx-components-ai-agent-chat.d.ts +111 -4
- package/types/c8y-ngx-components-ai-agent-chat.d.ts.map +1 -1
- package/types/c8y-ngx-components-ai-agents-html.d.ts.map +1 -1
- package/types/c8y-ngx-components-ai-agents-scada.d.ts.map +1 -1
- package/types/c8y-ngx-components-ai-ai-chat.d.ts +224 -10
- package/types/c8y-ngx-components-ai-ai-chat.d.ts.map +1 -1
- package/types/c8y-ngx-components-ai.d.ts +176 -6
- package/types/c8y-ngx-components-ai.d.ts.map +1 -1
- package/types/c8y-ngx-components-context-dashboard.d.ts.map +1 -1
- package/types/c8y-ngx-components-datapoint-explorer-view.d.ts +7 -2
- package/types/c8y-ngx-components-datapoint-explorer-view.d.ts.map +1 -1
- package/types/c8y-ngx-components-datapoint-selector.d.ts +63 -50
- package/types/c8y-ngx-components-datapoint-selector.d.ts.map +1 -1
- package/types/c8y-ngx-components-echart.d.ts +12 -0
- package/types/c8y-ngx-components-echart.d.ts.map +1 -1
- package/types/c8y-ngx-components-time-context.d.ts +2 -0
- package/types/c8y-ngx-components-time-context.d.ts.map +1 -1
- package/types/c8y-ngx-components-widgets-implementations-scada.d.ts.map +1 -1
- package/types/c8y-ngx-components.d.ts +10 -1
- package/types/c8y-ngx-components.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"c8y-ngx-components-ai-ai-chat.mjs","sources":["../../ai/ai-chat/ai-chat-tool-call.component.ts","../../ai/ai-chat/ai-chat-tool-call.component.html","../../ai/ai-chat/json-to-markdown.pipe.ts","../../ai/ai-chat/ai-chat-assistant-part.component.ts","../../ai/ai-chat/ai-chat-assistant-part.component.html","../../ai/ai-chat/ai-chat-assistant-message.component.ts","../../ai/ai-chat/ai-chat-assistant-message.component.html","../../ai/ai-chat/ai-chat-message-action.component.ts","../../ai/ai-chat/ai-chat-message-action.component.html","../../ai/ai-chat/ai-chat-message.component.ts","../../ai/ai-chat/ai-chat-message.component.html","../../ai/ai-chat/ai-chat-suggestion.component.ts","../../ai/ai-chat/ai-chat-suggestion.component.html","../../ai/ai-chat/ai-chat.component.ts","../../ai/ai-chat/ai-chat.component.html","../../ai/ai-chat/c8y-ngx-components-ai-ai-chat.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, input, signal, Type } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { ToolCallConfig, ToolCallPart } from '@c8y/ngx-components/ai';\nimport { C8yTranslateModule, C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { JsonPipe, NgComponentOutlet } from '@angular/common';\nimport { TranslateService } from '@ngx-translate/core';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\n\n@Component({\n selector: 'c8y-ai-chat-tool-call',\n templateUrl: './ai-chat-tool-call.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgComponentOutlet,\n JsonPipe,\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n C8yTranslateModule\n ]\n})\nexport class AiChatToolCallComponent {\n /**\n * The tool call part to render. This includes all information about the tool call, including the name of the tool,\n * the input provided and (once available) the output from the tool.\n */\n readonly tool = input.required<ToolCallPart>();\n\n /**\n * Whether the tool call is still in progress.\n */\n readonly isExecuting = input.required<boolean>();\n\n /**\n * A custom component to render the details of the tool call. If not provided, the default details section will be shown.\n */\n readonly toolDetailsComponent = input<Type<unknown> | undefined>(undefined);\n\n /**\n * Shows the default details section for a tool call.\n */\n readonly showDefaultToolDetails = input<boolean>(false);\n\n /**\n * The label to show while the tool is executing. If not provided, a default label will be generated based on the tool name.\n */\n readonly executingLabel = input<string | undefined>(undefined);\n /**\n * The label to show once the tool has completed. If not provided, a default label will be generated based on the tool name and whether the tool call was successful or resulted in an error.\n */\n readonly completedLabel = input<string | undefined>(undefined);\n\n /**\n * A function that can generate a label for this tool call based on the tool call data.\n */\n readonly labelProvider = input<ToolCallConfig['labelProvider']>();\n\n protected readonly expanded = signal(false);\n protected readonly everExpanded = signal(false);\n\n private readonly translateService = inject(TranslateService);\n\n getToolLabel(tool: ToolCallPart): string {\n const isExecuting = tool.type !== 'tool-result';\n if (this.labelProvider()) {\n try {\n const dynamicLabel = this.labelProvider()(tool, this.translateService);\n if (dynamicLabel) return dynamicLabel;\n } catch (err) {\n // Should never happen, report it then fall back to default logic\n console.error(`Error in labelProvider for tool ${tool.toolName}:`, err);\n }\n }\n\n if (isExecuting && this.executingLabel()) {\n return this.executingLabel();\n }\n if (!isExecuting && this.completedLabel()) {\n return this.completedLabel();\n }\n\n return this.translateService.instant(\n isExecuting ? gettext('Calling tool {{toolName}}') : gettext('Used tool {{toolName}}'),\n { toolName: tool.toolName }\n );\n }\n\n protected toggleExpanded(): void {\n const willExpand = !this.expanded();\n this.expanded.set(willExpand);\n if (willExpand) {\n this.everExpanded.set(true);\n }\n }\n}\n","@let _tool = tool();\n@let showDetails = showDefaultToolDetails() || toolDetailsComponent() || _tool.error;\n@let isToolExpanded = expanded();\n\n<fieldset\n class=\"c8y-fieldset p-b-4 ai-tool-call__fieldset\"\n [attr.aria-label]=\"'Tool call: ' + _tool.toolName\"\n>\n <button\n class=\"btn-clean ai-tool-call__btn\"\n [attr.aria-expanded]=\"showDetails ? isToolExpanded : null\"\n [attr.aria-controls]=\"showDetails ? 'tool-call-' + _tool.toolCallId : null\"\n type=\"button\"\n [attr.data-cy]=\"'tool-call-' + _tool.toolName\"\n [disabled]=\"!showDetails || null\"\n (click)=\"toggleExpanded()\"\n >\n @if (isExecuting()) {\n <i\n class=\"icon-spin icon-14 text-primary m-r-4\"\n c8yIcon=\"spinner\"\n aria-hidden=\"true\"\n ></i>\n } @else {\n <!-- Treat it as an error if a tool still thinks its executing when the message containing it is not -->\n @if (_tool.error || isExecuting()) {\n <i\n class=\"icon-14 text-danger m-r-4\"\n [c8yIcon]=\"'exclamation-circle'\"\n aria-hidden=\"true\"\n ></i>\n } @else {\n <i\n class=\"icon-14 text-success m-r-4\"\n [c8yIcon]=\"'check'\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n <span class=\"small\">{{ getToolLabel(_tool) | translate }}</span>\n\n @if (showDetails) {\n <i\n class=\"m-l-4 icon-12\"\n [c8yIcon]=\"isToolExpanded ? 'collapse-arrow' : 'expand-arrow'\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n <!-- If this is an artifact tool, render it - but do so lazily only on first open,\n since these components could be heavyweight (e.g. Monaco)\n -->\n @if (showDetails && (isToolExpanded || everExpanded())) {\n <div\n class=\"collapse tool-details m-t-8 p-8\"\n [attr.aria-label]=\"'Tool details for message latest tool: ' + _tool.toolName\"\n role=\"region\"\n [collapse]=\"!isToolExpanded\"\n [id]=\"'tool-call-' + _tool.toolCallId\"\n [isAnimated]=\"true\"\n data-cy=\"ai-tool-component\"\n >\n @if (toolDetailsComponent()) {\n <ng-container\n [ngComponentOutlet]=\"toolDetailsComponent()\"\n [ngComponentOutletInputs]=\"{ tool: _tool }\"\n ></ng-container>\n } @else {\n @let noneLabel = '(no data)' | translate;\n\n <p class=\"text-label-small\">{{ 'Tool input' | translate }}</p>\n <pre class=\"fit-w small\">{{ _tool.input || noneLabel | json }}</pre>\n\n @if (_tool.type === 'tool-result') {\n <p class=\"text-label-small\">{{ 'Tool output' | translate }}</p>\n @if (\n typeof _tool.output === 'string' || _tool.output === undefined || _tool.output === null\n ) {\n <pre class=\"fit-w small\">{{ _tool.output || noneLabel }}</pre>\n } @else {\n <pre class=\"fit-w small\">{{ _tool.output | json }}</pre>\n }\n }\n }\n </div>\n }\n</fieldset>\n","import { Pipe, PipeTransform } from '@angular/core';\n\n/**\n * Converts a JSON string to a markdown code block.\n */\n@Pipe({\n name: 'jsonToMarkdown',\n standalone: true\n})\nexport class JsonToMarkdownPipe implements PipeTransform {\n transform(value: string | null | undefined): string {\n if (!value) {\n return '```json\\nnull\\n```';\n }\n\n const escapedValue = value.replace(/\\\\/g, '\\\\\\\\').replace(/`/g, '\\\\`');\n return `\\`\\`\\`json\\n${escapedValue}\\n\\`\\`\\``;\n }\n}\n","import { ChangeDetectionStrategy, Component, input, signal } from '@angular/core';\nimport { AIMessagePart } from '@c8y/ngx-components/ai';\nimport {\n C8yTranslateDirective,\n C8yTranslatePipe,\n IconDirective,\n MarkdownToHtmlPipe\n} from '@c8y/ngx-components';\nimport { AsyncPipe, NgComponentOutlet } from '@angular/common';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\nimport { AssistantMessageContext } from './ai-chat-assistant-message.component';\nimport { AiChatToolCallComponent } from './ai-chat-tool-call.component';\nimport { JsonToMarkdownPipe } from './json-to-markdown.pipe';\n\n/** This renders a part of an assistant message. Currently only ToolCallPart is supported, but later we can expand this to deal with all part types. */\n@Component({\n selector: 'c8y-ai-chat-assistant-part',\n templateUrl: './ai-chat-assistant-part.component.html',\n standalone: true,\n imports: [\n NgComponentOutlet,\n C8yTranslateDirective,\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n MarkdownToHtmlPipe,\n AsyncPipe,\n AiChatToolCallComponent,\n JsonToMarkdownPipe\n ],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AiChatAssistantPartComponent {\n readonly part = input.required<AIMessagePart>();\n\n /** Whether this part is rendered as part of the main answer, or is an intermediate step with more muted rendering. */\n readonly displayAsPartOfMainAnswer = input(true);\n\n /**\n * The context needed to render a message.\n * This is a single input so we can extend in future without breaking people who have a custom rendering implementation.\n */\n readonly assistantMessageContext = input.required<AssistantMessageContext>();\n\n /** Tracks whether this is currently expanded (used for reasoning section). */\n protected readonly expanded = signal(false);\n\n protected toggleExpanded(): void {\n this.expanded.update(v => !v);\n }\n}\n","@let ctx = assistantMessageContext();\n@let _config = ctx.config;\n@let toolCallConfig = _config.toolCallConfig || {};\n@let _part = part();\n\n@if (_part.type === 'text') {\n <p\n [class.text-muted]=\"!displayAsPartOfMainAnswer()\"\n [innerHTML]=\"_part.text | markdownToHtml | async\"\n ></p>\n} @else if (_part.type === 'reasoning') {\n @let reasoningExpanded = expanded();\n\n <fieldset\n class=\"c8y-fieldset p-b-4 ai-tool-call__fieldset\"\n data-cy=\"ai-reasoning\"\n >\n <button\n class=\"btn-clean ai-tool-call__btn\"\n aria-label=\"{{ 'Toggle display of the reasoning section' | translate }}\"\n [attr.aria-expanded]=\"reasoningExpanded\"\n [attr.aria-controls]=\"'reasoning-content-message' + ctx.messageDisplayIndex\"\n type=\"button\"\n (click)=\"toggleExpanded()\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"'ai-sparkles'\"\n ></i>\n @let hideReasoning = 'Hide reasoning' | translate;\n @let showReasoning = 'Show reasoning' | translate;\n <span class=\"small\">{{ reasoningExpanded ? hideReasoning : showReasoning }}</span>\n <i\n class=\"m-l-4 icon-12 text-muted\"\n [c8yIcon]=\"reasoningExpanded ? 'collapse-arrow' : 'expand-arrow'\"\n ></i>\n </button>\n\n @let ariaLabel =\n 'Reasoning for message number {{ number }}' | translate: { number: ctx.messageDisplayIndex };\n <div\n class=\"collapse reasoning-content\"\n [attr.aria-label]=\"ariaLabel\"\n role=\"region\"\n [collapse]=\"!reasoningExpanded\"\n [id]=\"'reasoning-content-message' + ctx.messageDisplayIndex\"\n [isAnimated]=\"true\"\n data-cy=\"ai-reasoning-content\"\n >\n <div\n class=\"m-t-8 p-b-4 text-muted\"\n [innerHTML]=\"_part.text | markdownToHtml | async\"\n ></div>\n </div>\n </fieldset>\n} @else if (_part.type === 'object') {\n <p\n [class.text-muted]=\"!displayAsPartOfMainAnswer()\"\n [innerHTML]=\"_part.jsonContent | jsonToMarkdown | markdownToHtml | async\"\n data-cy=\"ai-object-content\"\n ></p>\n} @else if (_part.type === 'step-start') {\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"ai-step-start hidden-copy-label\"\n aria-hidden=\"true\"\n data-cy=\"ai-step-start-separator\"\n translate\n >--- (step separator) ---</span\n >\n} @else if (_part.type.startsWith('tool')) {\n @let tool = $any(_part);\n @let toolDisplay = toolCallConfig[tool.toolName];\n\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"hidden-copy-label\"\n aria-hidden=\"true\"\n translate\n [translateParams]=\"{ toolName: tool.toolName }\"\n ngNonBindable\n >--- Tool call: {{ toolName }} ---</span\n >\n\n @if (toolDisplay?.component) {\n <div data-cy=\"ai-tool-with-custom-component\">\n <ng-container\n [ngComponentOutlet]=\"toolDisplay.component\"\n [ngComponentOutletInputs]=\"{\n tool: tool,\n ctx: ctx\n }\"\n ></ng-container>\n </div>\n } @else if (!toolDisplay?.isHidden) {\n <!-- Don't allow expanding while tool call is in progress - it's unlikely to have anything worth rendering,\n and complicates implementation for the client to have to check for the isExecuting case.\n -->\n <c8y-ai-chat-tool-call\n [tool]=\"tool\"\n [isExecuting]=\"tool.type !== 'tool-result' && ctx.isMessageLoading\"\n [toolDetailsComponent]=\"_config.toolDetailsComponent?.(tool)\"\n [showDefaultToolDetails]=\"_config.showDefaultToolDetails === 'all'\"\n [executingLabel]=\"toolDisplay?.executingLabel\"\n [completedLabel]=\"toolDisplay?.completedLabel\"\n [labelProvider]=\"toolDisplay?.labelProvider\"\n ></c8y-ai-chat-tool-call>\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n signal\n} from '@angular/core';\nimport { C8yTranslateModule, C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport {\n AIAssistantMessage,\n AIMessagePart,\n AssistantMessageDisplayConfig,\n ToolCallPart\n} from '@c8y/ngx-components/ai';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { TranslateService } from '@ngx-translate/core';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\nimport { AiChatAssistantPartComponent } from './ai-chat-assistant-part.component';\n\n/**\n * Context object which includes the inputs needed for assistant message rendering.\n * If creating a custom component for assistant message rendering, you will receive this as an input.\n */\nexport interface AssistantMessageContext {\n message: AIAssistantMessage;\n config: AssistantMessageDisplayConfig;\n\n /** The message response is currently streaming in (not yet complete). */\n isMessageLoading: boolean;\n\n /** A number identifying this message in the chat history numbered from the latest - 0 is the latest, -1 is the previous, etc. */\n messageDisplayIndex: number;\n}\n\n/**\n * This is the default component used to render the contents of a message from the AI assistant, including\n * the main answer text, text from earlier steps, reasoning text and tool calls.\n */\n@Component({\n selector: 'c8y-ai-chat-assistant-message',\n templateUrl: './ai-chat-assistant-message.component.html',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n C8yTranslateModule,\n AiChatAssistantPartComponent\n ]\n})\nexport class AiChatAssistantMessageComponent {\n /**\n * The context needed to render a message.\n * This is a single input so we can extend in future without breaking people who have a custom rendering implementation.\n */\n readonly assistantMessageContext = input.required<AssistantMessageContext>();\n\n /**\n * By default this component will render a \"Working...\" indicator while streaming results. This input can turn that off if required.\n */\n readonly showWorkingIndicator = input(true);\n\n /**\n * Whether the thinking section is expanded. Initialized to false unless the message is still loading.\n * Call setThinkingExpanded() via viewChild to control this programmatically. Does nothing if appearance does not distinguish thinking steps.\n */\n protected readonly thinkingExpanded = signal(false);\n\n /**\n * Tracks which reasoning sections are expanded, keyed by step index.\n */\n protected readonly expandedReasoningStepIndices = signal(new Set<number>());\n\n private readonly translateService = inject(TranslateService);\n\n protected readonly thinkingAndMainAnswerParts = computed(() =>\n this.splitContentIntoThinkingAndMainAnswer(this.assistantMessageContext())\n );\n\n constructor() {\n // Expand when we initially set the message loading flag, without overwriting the value\n // any other time\n effect(() => {\n if (this.assistantMessageContext().isMessageLoading) {\n this.thinkingExpanded.set(true);\n }\n });\n }\n\n /**\n * This is public and exists for agent-chat to collapse older messages.\n * @param expanded Whether the thinking section should be expanded or not.\n */\n setThinkingExpanded(expanded: boolean): void {\n this.thinkingExpanded.set(expanded);\n }\n\n /**\n * Get a translated/translateable label for the specified tool.\n * @param tool The tool call part to get the label for.\n * @return The label to show for this tool call.\n */\n getToolLabel(tool: ToolCallPart): string {\n const isExecuting = tool.type !== 'tool-result';\n const config = this.assistantMessageContext().config;\n const toolCallConfig = config?.toolCallConfig?.[tool.toolName];\n if (toolCallConfig?.labelProvider) {\n try {\n const dynamicLabel = toolCallConfig.labelProvider(tool, this.translateService);\n // Run it through translate in case it contains gettext values\n if (dynamicLabel) return dynamicLabel;\n } catch (err) {\n // Should never happen, so report this - then fallback to default logic\n console.warn(`Error in labelProvider for tool ${tool.toolName}:`, err);\n }\n }\n\n if (isExecuting && toolCallConfig?.executingLabel) {\n return toolCallConfig.executingLabel;\n }\n if (!isExecuting && toolCallConfig?.completedLabel) {\n return toolCallConfig.completedLabel;\n }\n\n // If we have no specific label configured, use the default\n return this.translateService.instant(\n isExecuting ? gettext('Calling tool {{toolName}}') : gettext('Used tool {{toolName}}'),\n // Have to use the tool id since that's all we have\n { toolName: tool.toolName }\n );\n }\n\n protected toggleReasoningExpanded(stepIndex: number): void {\n this.expandedReasoningStepIndices.update(s => {\n const next = new Set(s);\n s.has(stepIndex) ? next.delete(stepIndex) : next.add(stepIndex);\n return next;\n });\n }\n\n /**\n * Note: ctx is passed as a parameter rather than reading the signal in the template to ensure\n * it's totally aligned with what the template is rendering.\n * @param ctx The context for the assistant message.\n * @return The label to display for the reasoning section.\n */\n protected getThinkingLabel(ctx: AssistantMessageContext): string {\n return ctx.isMessageLoading\n ? gettext('Reasoning')\n : this.thinkingExpanded()\n ? gettext('Hide reasoning')\n : gettext('Show reasoning');\n }\n\n protected getToolName(part: AIMessagePart): string | undefined {\n return part.type === 'tool-input-streaming' ||\n part.type === 'tool-executing' ||\n part.type === 'tool-result'\n ? part.toolName\n : undefined;\n }\n\n protected experimental_nonFinalStepTextDisplay(\n ctx: AssistantMessageContext\n ): AssistantMessageDisplayConfig['experimental_nonFinalStepTextDisplay'] {\n // For now be conservative with the old behaviour, but hope to change this once we've got working really smoothly.\n return ctx.config?.experimental_nonFinalStepTextDisplay || 'main-answer';\n }\n\n /**\n * Splits the assistant message content into two arrays: thinking content and main answer content.\n * This also removes hidden tools.\n *\n * If using the experimental rendering modes, main answer content is text in the final step (if conditions are met) plus any tool calls configured to be shown with the main answer.\n * Thinking content is everything else (reasoning, earlier text, tool calls not shown with main answer).\n *\n * @param ctx The context for the assistant message.\n * @return An object with thinkingParts and mainAnswerParts arrays.\n */\n protected splitContentIntoThinkingAndMainAnswer(ctx: AssistantMessageContext): {\n thinkingParts: AIMessagePart[];\n mainAnswerParts: AIMessagePart[];\n } {\n // Remove hidden tools\n let content = ctx.message?.content || [];\n if (Object.values(ctx.config?.toolCallConfig || {}).some(c => c?.isHidden)) {\n content = (ctx.message?.content || []).filter(\n part => !ctx.config?.toolCallConfig?.[this.getToolName(part) || '']?.isHidden\n );\n }\n\n // Putting this check here keeps things safe by ensuring there is no chance of any rendering differences\n // during streaming unless in one of the experimental modes. This means the rest of this method only applies\n // to the experimental rendering.\n if (this.experimental_nonFinalStepTextDisplay(ctx) === 'main-answer') {\n return { thinkingParts: [], mainAnswerParts: content };\n }\n\n const { finalStepStart, finalStepHasText } = this.findFinalStepWithText(content);\n\n const hasToolCalls = content.some(\n part =>\n part.type === 'tool-input-streaming' ||\n part.type === 'tool-executing' ||\n part.type === 'tool-result'\n );\n // Since we don't bother with a step-start at index 0 for the first step, add one\n const stepCount =\n content.filter((part, index) => index > 0 && part.type === 'step-start').length + 1;\n\n // The final step text goes in the main answer area if there are no pending tool calls\n // (since otherwise the tools would show below it), and\n // message has finished loading, or we're expecting more steps than this.\n // Note that we check all steps for toolCalls not just the current one, for the sake of \"fake\" tool calls created by preprocessAgentMessage\n // where additional step boundaries may be added to simplify parsing.\n const shouldShowLastTextAsMainAnswer =\n finalStepHasText &&\n finalStepStart !== -1 &&\n !hasToolCalls &&\n (!ctx.isMessageLoading || stepCount >= (ctx.config?.experimental_expectedStepCount || 2));\n\n if (!shouldShowLastTextAsMainAnswer) {\n return { thinkingParts: content, mainAnswerParts: [] };\n }\n\n const thinkingParts: AIMessagePart[] = [];\n const mainAnswerParts: AIMessagePart[] = [];\n\n // Split the content: final step and promoted tool calls go to main answer, everything else to thinking\n content.forEach((part, index) => {\n const isPromotedToolCall =\n ctx.config?.toolCallConfig?.[this.getToolName(part) || '']?.isShownWithMainAnswer;\n\n // This ensures promoted tool calls never go to the collapseable thinking area\n if (index >= finalStepStart || isPromotedToolCall) {\n mainAnswerParts.push(part);\n } else {\n thinkingParts.push(part);\n }\n });\n\n return { thinkingParts, mainAnswerParts };\n }\n\n /**\n * Scans backwards through the content parts to find the step-start index for the last step\n * that contains at least one text part. Skips trailing empty steps (step-start with no text after).\n *\n * @returns `finalStepStart` — index of the step-start part, or 0 if content belongs to the implicit first step.\n * `finalStepHasText` — whether a step with text was found at all.\n */\n private findFinalStepWithText(content: AIMessagePart[]): {\n finalStepStart: number;\n finalStepHasText: boolean;\n } {\n let finalStepStart = 0;\n let finalStepHasText = false;\n for (let i = content.length - 1; i >= 0; i--) {\n if (content[i].type === 'text') {\n finalStepHasText = true;\n }\n if (content[i].type === 'step-start') {\n if (finalStepHasText) {\n finalStepStart = i;\n break;\n } else if (i === content.length - 1) {\n // Trailing empty step-start — keep looking\n continue;\n } else {\n // step-start found but no text in that step\n finalStepStart = -1;\n break;\n }\n }\n }\n return { finalStepStart, finalStepHasText };\n }\n}\n","@let ctx = assistantMessageContext();\n@let parts = ctx.message.content;\n@let _config = ctx.config;\n\n<!-- \nWe show the assistant message in (up to) 3 slots:\n- collapsible thinking block (for intermediate step text, standard tool calls, etc)\n- special \"artifact\" tools that update user artifacts and need prominent display (e.g. for code edits made by the AI)\n- the main answer (typically from the final step)\n\nThis is a standard approach for AI chats - step text and tools from an LLM are treated as a work log, i.e. useful to \ndisplay progress while streaming the response, but only the text from the last step after all tool calls gives the main answer of the AI to the user. \n\nDepending on configuration, we have an experimental option (if we need it) to style the thinking block the same as the main answer. \n\nOnce the message finishes loading we know the final step IS the main content, but if it's still steaming \nwe don't know for sure which step has the final/main answer until the LLM has actually finished so have to take a heuistic guess \n(and minimize jumping in the UI). \n\nFor applications where we expect tool calls in most responses, assume the 2nd step is probably the final text; \nfor applications where tool calls are less ubiquitous, assume the first step is main answer until proved otherwise. \nThis minimizes jumping (except when there are >2 steps, which is rare).\n\n-->\n\n@let contentSplit = thinkingAndMainAnswerParts();\n@let nonFinalStepTextDisplay = experimental_nonFinalStepTextDisplay(ctx);\n\n<!-- Thinking steps section - holds reasoning, text from non-final steps, and standard/non-artifact tool calls -->\n\n@if (contentSplit.thinkingParts.length > 0) {\n <div\n class=\"m-b-8 text-muted\"\n [class.thinking-block]=\"nonFinalStepTextDisplay === 'collapsible-thinking-block'\"\n [class.small]=\"nonFinalStepTextDisplay === 'muted-main-answer'\"\n [class.thinking-steps-appearance]=\"nonFinalStepTextDisplay\"\n data-cy=\"thinking-steps\"\n >\n @if (nonFinalStepTextDisplay === 'collapsible-thinking-block') {\n <button\n class=\"btn btn-clean btn-xs text-muted p-l-0\"\n aria-label=\"{{ 'Toggle collapse of the reasoning section' | translate }}\"\n [attr.aria-expanded]=\"thinkingExpanded()\"\n [attr.aria-controls]=\"'thinking-content-' + ctx.messageDisplayIndex\"\n type=\"button\"\n (click)=\"thinkingExpanded.set(!thinkingExpanded())\"\n >\n <span class=\"small\">{{ getThinkingLabel(ctx) }}</span>\n <i\n class=\"m-l-4 icon-12\"\n [c8yIcon]=\"thinkingExpanded() ? 'collapse-arrow' : 'expand-arrow'\"\n ></i>\n </button>\n }\n\n @let ariaLabel =\n 'Reasoning for message number {{ number }}' | translate: { number: ctx.messageDisplayIndex };\n <div\n class=\"collapse\"\n [attr.aria-label]=\"ariaLabel\"\n role=\"region\"\n [collapse]=\"nonFinalStepTextDisplay === 'collapsible-thinking-block' && !thinkingExpanded()\"\n [id]=\"'thinking-content-' + ctx.messageDisplayIndex\"\n [isAnimated]=\"true\"\n >\n <div\n [class]=\"\n nonFinalStepTextDisplay === 'collapsible-thinking-block'\n ? 'thinking-content bg-level-1 m-t-8 p-8 border-left-accent small m-b-0 text-muted'\n : ''\n \"\n >\n @for (part of contentSplit.thinkingParts; track $index) {\n @if (part.type !== 'step-start' || $index > 0) {\n <c8y-ai-chat-assistant-part\n [part]=\"part\"\n [assistantMessageContext]=\"ctx\"\n [displayAsPartOfMainAnswer]=\"nonFinalStepTextDisplay !== 'muted-main-answer'\"\n ></c8y-ai-chat-assistant-part>\n }\n }\n </div>\n </div>\n </div>\n}\n\n<!-- Main answer area contains the text from the final step, and \n any promoted tool calls which are too important to be hidden in the collapeable thinking area -->\n<div\n class=\"message-content\"\n data-cy=\"ai-main-answer-content\"\n>\n @for (part of contentSplit.mainAnswerParts; track $index) {\n <c8y-ai-chat-assistant-part\n [part]=\"part\"\n [assistantMessageContext]=\"ctx\"\n [displayAsPartOfMainAnswer]=\"true\"\n ></c8y-ai-chat-assistant-part>\n }\n</div>\n\n@if (ctx.isMessageLoading && showWorkingIndicator()) {\n <!-- Once the message starts to stream, show a small/low-key thinking indicator -->\n <div\n class=\"text-muted text-12 fade-in-out d-flex j-c-end\"\n aria-live=\"polite\"\n role=\"status\"\n data-cy=\"working-indicator\"\n >\n {{ 'Working…' | translate }}\n </div>\n}\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An action button that can be added to chat messages.\n * Typically used for actions like copying, regenerating, or providing feedback on messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message-action',\n templateUrl: './ai-chat-message-action.component.html',\n standalone: true,\n imports: [TooltipModule, C8yTranslatePipe, IconDirective]\n})\nexport class AiChatMessageActionComponent {\n /**\n * Set to true to use content projection for custom action button content.\n */\n @Input()\n custom = false;\n\n /**\n * Disables the action button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Tooltip text displayed when hovering over the action button.\n */\n @Input()\n tooltip = '';\n\n /**\n * Icon to display in the action button.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'cog';\n\n /**\n * Emitted when the action button is clicked.\n */\n @Output()\n actionClicked = new EventEmitter<void>();\n}\n","@if (!custom) {\n <button\n class=\"btn btn-dot text-muted\"\n [attr.aria-label]=\"tooltip | translate\"\n [tooltip]=\"tooltip | translate\"\n [adaptivePosition]=\"true\"\n [delay]=\"500\"\n (click)=\"actionClicked.emit()\"\n [disabled]=\"disabled\"\n >\n <i\n class=\"text-12\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n} @else {\n <ng-content></ng-content>\n}\n","import { Component, computed, input, inject, ChangeDetectionStrategy } from '@angular/core';\n\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { C8yTranslatePipe, DatePipe } from '@c8y/ngx-components';\nimport { NgClass } from '@angular/common';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { TranslateService } from '@ngx-translate/core';\n\n/**\n * A container for content and actions that should be rendered for each chat message.\n *\n * Project content into this component to display the message, for example add an `<ai-chat-assistant-message>`\n * for assistant messages, and a simple `markdownToHtml | async` rendering of the content for user messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message',\n templateUrl: './ai-chat-message.component.html',\n styleUrl: './ai-chat-message.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgClass, TooltipModule, C8yTranslatePipe, DatePipe]\n})\nexport class AiChatMessageComponent {\n readonly role = input<AIMessage['role']>();\n readonly message = input<AIMessage>();\n\n private readonly translateService = inject(TranslateService);\n\n private readonly roleResolved = computed(() => {\n return this.message()?.role || this.role();\n });\n\n /**\n * Generates an accessible label for the message container.\n * Includes the role (user or assistant) and timestamp if available.\n * @returns The aria-label string for screen readers\n */\n readonly ariaLabel = computed(() => {\n const tpl =\n this.roleResolved() === 'user'\n ? gettext('You said: \"{{ message }}\"')\n : gettext('Assistant said: \"{{ message }}\"');\n const msg = this.message();\n return this.translateService.instant(tpl, { message: msg?.content || gettext('No response.') });\n });\n\n /**\n * Generates an accessible label for the message content.\n * Prefixes the content with contextual information about who sent it.\n * @returns The aria-label string with prefixed role information\n */\n readonly messageContentAriaLabel = computed(() => {\n const msg = this.message();\n const time =\n msg.role != 'system' && msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : '';\n let tpl: string;\n if (time) {\n tpl =\n this.roleResolved() === 'user'\n ? gettext('User message at {{ time }}')\n : gettext('Assistant message at {{ time }}');\n } else {\n tpl = this.roleResolved() === 'user' ? gettext('User message') : gettext('Assistant message');\n }\n return this.translateService.instant(tpl, { time });\n });\n}\n","<div\n class=\"d-col p-t-16\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"article\"\n>\n <div\n class=\"chat-message text-break-word\"\n [ngClass]=\"{\n 'user-message': message()?.role === 'user' || role() === 'user',\n 'agent-message': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"hidden-copy-label\"\n aria-hidden=\"true\"\n >\n {{ `====== ${messageContentAriaLabel()} ======` }}</span\n >\n\n <!-- Apply the class and aria-label to both the main content and whatever is projected, so we get the same styling by default -->\n <div\n class=\"message-content\"\n [attr.aria-label]=\"messageContentAriaLabel()\"\n >\n <div style=\"display: contents\">\n <ng-content select=\":not(c8y-ai-chat-message-action)\"></ng-content>\n </div>\n </div>\n @if (message()?.timestamp) {\n <div class=\"message-timestamp\">\n <span [tooltip]=\"message()?.timestamp | c8yDate\">\n {{ message()?.timestamp | c8yDate: 'adaptiveDate' }}\n </span>\n </div>\n }\n </div>\n <div\n class=\"message-action\"\n [attr.aria-label]=\"'Message actions' | translate\"\n role=\"toolbar\"\n [ngClass]=\"{\n 'user-action showOnHover': message()?.role === 'user' || role() === 'user',\n 'agent-action p-l-16': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <ng-content select=\"c8y-ai-chat-message-action\"></ng-content>\n </div>\n</div>\n","import { Component, input, output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\n\n/**\n * A suggestion chip that can be displayed in the chat interface.\n * When clicked, it automatically populates and sends a predefined prompt.\n */\n@Component({\n selector: 'c8y-ai-chat-suggestion',\n templateUrl: './ai-chat-suggestion.component.html',\n host: { class: 'd-contents' },\n standalone: true,\n imports: [IconDirective, C8yTranslatePipe]\n})\nexport class AiChatSuggestionComponent {\n /**\n * The visible label text displayed on the suggestion chip.\n */\n readonly label = input.required<string>();\n\n /**\n * The prompt text that will be sent when the suggestion is clicked.\n */\n readonly prompt = input.required<string>();\n\n /**\n * Icon to display alongside the suggestion label.\n */\n readonly icon = input<SupportedIconsSuggestions>('c8y-bulb');\n\n /**\n * When true, uses AI-styled buttons instead of default styling.\n */\n readonly useAiButtons = input(false);\n\n /**\n * Disables the suggestion chip when true.\n */\n readonly disabled = input(false);\n\n /**\n * Emitted when the suggestion is clicked, providing the prompt as an AIMessage.\n */\n readonly suggestionClicked = output<AIMessage>();\n\n /**\n * Handles suggestion click and emits the prompt as a user message.\n */\n suggest() {\n this.suggestionClicked.emit({\n content: this.prompt(),\n role: 'user',\n timestamp: new Date().toISOString()\n });\n }\n}\n","@if (!useAiButtons()) {\n <button\n class=\"btn btn-default btn-sm\"\n [title]=\"prompt() | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled()\"\n >\n <i [c8yIcon]=\"icon()\"></i>\n {{ label() | translate }}\n </button>\n} @else {\n <button\n class=\"btn btn-sm btn-ai\"\n [title]=\"prompt() | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled()\"\n >\n <span>{{ label() | translate }}</span>\n </button>\n}\n","import { AsyncPipe, NgClass, NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n contentChildren,\n effect,\n ElementRef,\n EventEmitter,\n Input,\n Output,\n TemplateRef,\n viewChild\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n C8yTranslatePipe,\n IconDirective,\n MarkdownToHtmlPipe,\n NumberPipe,\n TextareaAutoresizeDirective\n} from '@c8y/ngx-components';\nimport { AIMessage, ChatConfig } from '@c8y/ngx-components/ai';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AiChatMessageComponent } from './ai-chat-message.component';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An interactive chat interface component for AI-powered conversations.\n * Displays messages in a conversation format with support for loading states,\n * custom configuration, and markdown formatting.\n */\n@Component({\n selector: 'c8y-ai-chat',\n templateUrl: './ai-chat.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n C8yTranslatePipe,\n FormsModule,\n TextareaAutoresizeDirective,\n IconDirective,\n NgClass,\n NgTemplateOutlet,\n MarkdownToHtmlPipe,\n AsyncPipe,\n TooltipModule,\n NumberPipe\n ],\n standalone: true,\n host: { class: 'd-contents' }\n})\nexport class AiChatComponent {\n /**\n * Indicates whether the chat is currently processing a request.\n * When true, displays a cancel button instead of send button and disables the input.\n */\n @Input()\n isLoading = false;\n\n /**\n * Disables the chat input and send button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * The current text in the chat input field. Supports two-way binding.\n */\n @Input()\n prompt = '';\n\n /**\n * Template for rendering custom suggestions below the input field. Can be used to provide predefined prompts or actions\n * from a dynamic source such as the AI. To use this, wrap your suggestion components in an `<ng-template #suggestionsRef>`\n * (where `suggestionsRef` matches the suggestionsTemplate reference);\n */\n @Input()\n suggestionsTemplate?: TemplateRef<any>;\n\n /** Template for customizing the welcome view using `<ng-template>`. */\n @Input() welcomeTemplate?: TemplateRef<any>;\n\n @Input() cumulativeUsage?: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n } | null = null;\n\n /**\n * Emitted when the user sends a message.\n * Provides an AIMessage object with role, content, and timestamp.\n */\n @Output()\n onMessage = new EventEmitter<AIMessage>();\n\n /**\n * Emitted when the user cancels an ongoing operation during loading state.\n */\n @Output()\n onCancel = new EventEmitter<void>();\n\n /**\n * Child message components displayed in the chat.\n */\n readonly messages = contentChildren(AiChatMessageComponent);\n\n /**\n * Reference to the scroll container for the chat messages.\n */\n private readonly scrollContainer = viewChild<ElementRef<HTMLDivElement>>('chatScrollContainer');\n\n readonly componentId = `chat-${crypto.randomUUID()}`;\n\n private _config: ChatConfig = {\n headline: gettext('Welcome!'),\n welcomeText: '',\n welcomePosition: 'top',\n title: gettext('What can I help you with?'),\n placeholder: gettext('Type your message here...'),\n scrollbarOnlyOnHover: false,\n sendButtonText: gettext('Send'),\n cancelButtonText: gettext('Cancel'),\n disclaimerText: gettext(\n 'AI-generated responses can contain errors. Verify the details before use.'\n ),\n userInterfaceIcons: {\n send: 'arrow-circle-up',\n cancel: 'stop-circle'\n }\n };\n\n constructor() {\n // Auto-scroll to bottom when messages change\n effect(() => {\n this.messages(); // track changes\n const container = this.scrollContainer()?.nativeElement;\n if (!container) return;\n // In column-reverse, scrollTop=0 IS the visual bottom.\n // Only snap back if user is already near the bottom (wasn't scrolled up).\n if (container.scrollTop < 50) {\n container.scrollTop = 0;\n }\n });\n }\n\n /**\n * Configuration object for customizing labels, placeholders, and icons.\n * Accepts partial configuration to override defaults.\n * @param value Partial configuration to merge with defaults.\n * @returns The complete configuration object.\n */\n @Input()\n set config(value: Partial<ChatConfig>) {\n this._config = { ...this._config, ...value };\n }\n get config(): ChatConfig {\n return this._config;\n }\n\n /**\n * Handles message submission when the user sends a message.\n * Emits the onMessage event and clears the input.\n * @param $event The event object from the form submission\n */\n sendMessage($event: Event): void {\n $event.preventDefault();\n if (!this.prompt) return;\n this.onMessage.emit({\n role: 'user',\n content: this.prompt,\n timestamp: new Date().toISOString()\n });\n this.prompt = '';\n }\n\n /**\n * Handles cancellation of ongoing operations during loading state.\n * Emits the onCancel event.\n */\n cancel(): void {\n this.onCancel.emit();\n }\n}\n","<div\n class=\"d-col fit-h fit-w flex-grow min-height-0\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages().length > 0) {\n <div\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n #chatScrollContainer\n [ngClass]=\"{\n 'inner-scroll': true,\n 'd-col-reverse': true,\n 'scrollbar-only-on-hover': config.scrollbarOnlyOnHover,\n 'flex-grow': true,\n 'min-height-0': true,\n 'bg-level-0': true\n }\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"[slot='before-messages']\"></ng-content>\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content select=\"[slot='after-messages']\"></ng-content>\n </div>\n </div>\n }\n <div\n [ngClass]=\"{\n 'd-col fit-h': messages().length === 0\n }\"\n >\n @if (messages().length === 0) {\n <div\n class=\"p-24 d-col fit-h inner-scroll\"\n aria-live=\"polite\"\n role=\"status\"\n [ngClass]=\"{\n 'j-c-start': config.welcomePosition === 'top',\n 'j-c-center': config.welcomePosition === 'center',\n 'j-c-end': config.welcomePosition === 'bottom'\n }\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n @if (config.title.length > 0) {\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n }\n <div class=\"text-balance chat-message min-height-0\">\n <div\n class=\"text-muted\"\n [innerHTML]=\"config.welcomeText | translate | markdownToHtml | async\"\n ></div>\n @if (welcomeTemplate) {\n <ng-container *ngTemplateOutlet=\"welcomeTemplate\"></ng-container>\n }\n </div>\n </div>\n }\n <div\n class=\"chat-input\"\n [class.bg-level-1]=\"config.appearance !== 'flat'\"\n >\n <!-- For simple cases allow ng-content projection; however this doesn't seem to work with dynamic \n suggestion lists from a signal (e.g. returned from the AI) so also support `suggestionsTemplate` for that. \n -->\n @if (!isLoading) {\n <div\n [class]=\"\n 'd-flex inner-scroll gap-8 p-l-16 p-r-16 p-b-8 ' +\n (config.suggestionsLayout === 'vertical' ? 'flex-wrap' : 'a-i-center')\n \"\n >\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n\n @if (suggestionsTemplate) {\n <ng-container *ngTemplateOutlet=\"suggestionsTemplate\"></ng-container>\n }\n </div>\n }\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n [class.text-muted]=\"isLoading\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n placeholder=\"{{ config.placeholder | translate }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"!isLoading && sendMessage($event)\"\n [disabled]=\"disabled\"\n c8y-textarea-autoresize\n ></textarea>\n <div class=\"chat-input-group-btn\">\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText || '' | translate\"\n [attr.aria-label]=\"config.sendButtonText || '' | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText || '' | translate\"\n [attr.aria-label]=\"config.cancelButtonText || '' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"d-flex\">\n @if (config.disclaimerText) {\n <div\n class=\"text-muted m-b-8 text-10 p-l-16\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n @if (cumulativeUsage) {\n <span\n class=\"tag tag--info m-l-auto\"\n [tooltip]=\"\n 'Input tokens: {{ input }}\\nOutput tokens: {{ output }}'\n | translate\n : {\n input: cumulativeUsage?.inputTokens || 0 | c8yNumber: 'floor' : '1.0-0',\n output: cumulativeUsage?.outputTokens || 0 | c8yNumber: 'floor' : '1.0-0'\n }\n \"\n >\n {{ 'Tokens used: {{total}}' | translate: { total: (cumulativeUsage?.totalTokens || 0) |\n c8yNumber : 'floor':'1.0-0' } }}\n </span>\n }\n </div>\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"c8y-ngx-components-ai-ai-chat.mjs","sources":["../../ai/ai-chat/ai-chat-action.component.ts","../../ai/ai-chat/ai-chat-action.component.html","../../ai/ai-chat/ai-chat-tool-call.component.ts","../../ai/ai-chat/ai-chat-tool-call.component.html","../../ai/ai-chat/json-to-markdown.pipe.ts","../../ai/ai-chat/ai-chat-assistant-part.component.ts","../../ai/ai-chat/ai-chat-assistant-part.component.html","../../ai/ai-chat/ai-chat-assistant-message.component.ts","../../ai/ai-chat/ai-chat-assistant-message.component.html","../../ai/ai-chat/ai-chat-message-action.component.ts","../../ai/ai-chat/ai-chat-message-action.component.html","../../ai/ai-chat/ai-chat-message.component.ts","../../ai/ai-chat/ai-chat-message.component.html","../../ai/ai-chat/speech-recognition.service.ts","../../ai/ai-chat/ai-chat-speech-to-text.component.ts","../../ai/ai-chat/ai-chat-speech-to-text.component.html","../../ai/ai-chat/ai-chat-suggestion.component.ts","../../ai/ai-chat/ai-chat-suggestion.component.html","../../ai/ai-chat/ai-chat.component.ts","../../ai/ai-chat/ai-chat.component.html","../../ai/ai-chat/c8y-ngx-components-ai-ai-chat.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input, TemplateRef, viewChild } from '@angular/core';\n\n/**\n * Projects arbitrary content into the action bar beneath the `c8y-ai-chat` input box.\n *\n * Place one or more `<c8y-ai-chat-action>` elements inside a `<c8y-ai-chat>` (or `<c8y-agent-chat>`)\n * and use the `placement` input to position them. The projected content is rendered as-is, so it can\n * hold any component or control (buttons, dropdowns, tags, and so on).\n *\n * @example\n * ```html\n * <c8y-ai-chat-action placement=\"left\">\n * <button class=\"btn btn-link btn-sm\"><i c8yIcon=\"attach\"></i></button>\n * </c8y-ai-chat-action>\n * ```\n */\n@Component({\n selector: 'c8y-ai-chat-action',\n templateUrl: './ai-chat-action.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'd-contents' }\n})\nexport class AiChatActionComponent {\n /**\n * Where the action is placed in the action bar. `more` collects the action into an overflow\n * dropdown on the right side.\n */\n readonly placement = input<'left' | 'right' | 'more'>('left');\n\n /** The projected content, exposed as a template so the host chat can render it in the right group. */\n readonly template = viewChild.required(TemplateRef);\n}\n","<ng-template>\n <ng-content></ng-content>\n</ng-template>\n","import {\n ChangeDetectionStrategy,\n Component,\n effect,\n inject,\n input,\n output,\n signal,\n Type\n} from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { ToolApprovalDecision, ToolCallConfig, ToolCallPart } from '@c8y/ngx-components/ai';\nimport {\n C8yTranslateModule,\n C8yTranslatePipe,\n DropdownFocusTrapDirective,\n IconDirective\n} from '@c8y/ngx-components';\nimport { JsonPipe, NgComponentOutlet } from '@angular/common';\nimport { TranslateService } from '@ngx-translate/core';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\nimport { BsDropdownModule } from 'ngx-bootstrap/dropdown';\n\n@Component({\n selector: 'c8y-ai-chat-tool-call',\n templateUrl: './ai-chat-tool-call.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgComponentOutlet,\n JsonPipe,\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n C8yTranslateModule,\n BsDropdownModule,\n DropdownFocusTrapDirective\n ]\n})\nexport class AiChatToolCallComponent {\n /**\n * The tool call part to render. This includes all information about the tool call, including the name of the tool,\n * the input provided and (once available) the output from the tool.\n */\n readonly tool = input.required<ToolCallPart>();\n\n /**\n * Whether the tool call is still in progress.\n */\n readonly isExecuting = input.required<boolean>();\n\n /**\n * A custom component to render the details of the tool call. If not provided, the default details section will be shown.\n */\n readonly toolDetailsComponent = input<Type<unknown> | undefined>(undefined);\n\n /**\n * Shows the default details section for a tool call.\n */\n readonly showDefaultToolDetails = input<boolean>(false);\n\n /**\n * The label to show while the tool is executing. If not provided, a default label will be generated based on the tool name.\n */\n readonly executingLabel = input<string | undefined>(undefined);\n /**\n * The label to show once the tool has completed. If not provided, a default label will be generated based on the tool name and whether the tool call was successful or resulted in an error.\n */\n readonly completedLabel = input<string | undefined>(undefined);\n\n /**\n * A function that can generate a label for this tool call based on the tool call data,\n * including for the `tool-approval-requested` state - e.g. \"Delete device weather-station-12\"\n * instead of the generic \"Tool delete_device requires approval\". When this returns nothing for\n * a pending approval, the details section is auto-expanded so the raw input is visible instead.\n */\n readonly labelProvider = input<ToolCallConfig['labelProvider']>();\n\n /**\n * Whether the approve/deny actions are offered when the tool is in the `tool-approval-requested` state.\n * Only enabled for the latest message while no response is streaming.\n */\n readonly approvalEnabled = input<boolean>(false);\n\n /**\n * Whether the \"always approve\" options are offered next to the approve action. Disabled for\n * tools that must be approved explicitly on every call (configured via `needsApproval`),\n * which show plain approve/deny buttons without the dropdown.\n */\n readonly rememberApprovalEnabled = input<boolean>(true);\n\n /** Emits the user's decision for a tool call awaiting approval. */\n readonly approvalResponse = output<ToolApprovalDecision>();\n\n protected readonly expanded = signal(false);\n protected readonly everExpanded = signal(false);\n\n private readonly translateService = inject(TranslateService);\n\n /** Guards the auto-expand-on-approval effect so it only ever applies its initial decision once. */\n private hasSetInitialApprovalExpansion = false;\n\n constructor() {\n // A tool call awaiting approval with no dynamic label (see `getDynamicLabel`) has nothing but\n // generic text in its header, so auto-expand the details once so the user can inspect the raw\n // input before deciding. Tools with a dynamic label already convey what's about to happen, so\n // details stay collapsed as usual.\n effect(() => {\n const tool = this.tool();\n if (this.hasSetInitialApprovalExpansion || tool.type !== 'tool-approval-requested') return;\n this.hasSetInitialApprovalExpansion = true;\n if (!this.getDynamicLabel(tool)) {\n this.expanded.set(true);\n this.everExpanded.set(true);\n }\n });\n }\n\n getToolLabel(tool: ToolCallPart): string {\n const dynamicLabel = this.getDynamicLabel(tool);\n if (dynamicLabel) return dynamicLabel;\n\n if (tool.type === 'tool-approval-requested') {\n return this.translateService.instant(gettext('Tool {{toolName}} requires approval'), {\n toolName: tool.toolName\n });\n }\n if (tool.type === 'tool-approval-responded') {\n return this.translateService.instant(\n tool.approval?.approved\n ? gettext('Approved tool {{toolName}}')\n : gettext('Denied tool {{toolName}}'),\n { toolName: tool.toolName }\n );\n }\n\n const isExecuting = tool.type !== 'tool-result';\n if (isExecuting && this.executingLabel()) {\n return this.executingLabel();\n }\n if (!isExecuting && this.completedLabel()) {\n return this.completedLabel();\n }\n\n return this.translateService.instant(\n isExecuting ? gettext('Calling tool {{toolName}}') : gettext('Used tool {{toolName}}'),\n { toolName: tool.toolName }\n );\n }\n\n /**\n * The fieldset's accessible name (and, for a pending approval, also its visible legend - see the\n * template). Both must stay in sync so sighted and screen-reader users see/hear the same thing.\n */\n getFieldsetLabel(tool: ToolCallPart): string {\n return this.translateService.instant(\n tool.type === 'tool-approval-requested'\n ? gettext('Tool request: {{toolName}}')\n : gettext('Tool call: {{toolName}}'),\n { toolName: tool.toolName }\n );\n }\n\n protected toggleExpanded(): void {\n const willExpand = !this.expanded();\n this.expanded.set(willExpand);\n if (willExpand) {\n this.everExpanded.set(true);\n }\n }\n\n private getDynamicLabel(tool: ToolCallPart): string | undefined {\n const labelProvider = this.labelProvider();\n if (!labelProvider) return undefined;\n try {\n return labelProvider(tool, this.translateService);\n } catch (err) {\n // Should never happen, report it then fall back to default logic\n console.error(`Error in labelProvider for tool ${tool.toolName}:`, err);\n return undefined;\n }\n }\n}\n","@let _tool = tool();\n@let isApprovalRequested = _tool.type === 'tool-approval-requested';\n@let showDetails =\n showDefaultToolDetails() || toolDetailsComponent() || _tool.error || isApprovalRequested;\n@let isToolExpanded = expanded();\n\n<fieldset\n class=\"c8y-fieldset p-b-4 ai-tool-call__fieldset\"\n [class.fit-w]=\"isApprovalRequested\"\n [attr.aria-label]=\"getFieldsetLabel(_tool)\"\n>\n @if (isApprovalRequested) {\n <legend>\n <i\n class=\"icon-16 text-warning m-r-4\"\n [c8yIcon]=\"'exclamation-triangle'\"\n aria-hidden=\"true\"\n ></i>\n {{ getFieldsetLabel(_tool) }}\n </legend>\n }\n\n <button\n class=\"btn-clean ai-tool-call__btn\"\n [attr.aria-expanded]=\"showDetails ? isToolExpanded : null\"\n [attr.aria-controls]=\"showDetails ? 'tool-call-' + _tool.toolCallId : null\"\n type=\"button\"\n [attr.data-cy]=\"'tool-call-' + _tool.toolName\"\n [disabled]=\"!showDetails || null\"\n (click)=\"toggleExpanded()\"\n >\n @if (_tool.type === 'tool-approval-responded') {\n <i\n class=\"icon-16 m-r-4\"\n [class.text-success]=\"_tool.approval?.approved\"\n [class.text-muted]=\"!_tool.approval?.approved\"\n [c8yIcon]=\"_tool.approval?.approved ? 'check' : 'ban'\"\n aria-hidden=\"true\"\n ></i>\n } @else if (isExecuting()) {\n <i\n class=\"icon-spin icon-16 text-primary m-r-4\"\n c8yIcon=\"spinner\"\n aria-hidden=\"true\"\n ></i>\n } @else {\n <!-- Treat it as an error if a tool still thinks its executing when the message containing it is not -->\n @if (_tool.error || isExecuting()) {\n <i\n class=\"icon-16 text-danger m-r-4\"\n [c8yIcon]=\"'exclamation-circle'\"\n aria-hidden=\"true\"\n ></i>\n } @else if (!isApprovalRequested) {\n <i\n class=\"icon-16 text-success m-r-4\"\n [c8yIcon]=\"'check'\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n @if (showDetails) {\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"isToolExpanded ? 'expand-arrow' : 'forward'\"\n aria-hidden=\"true\"\n ></i>\n }\n <span\n [class.small]=\"!isApprovalRequested\"\n [class.flex-grow]=\"isApprovalRequested\"\n >\n {{ getToolLabel(_tool) | translate }}\n </span>\n </button>\n <!-- If this is an artifact tool, render it - but do so lazily only on first open,\n since these components could be heavyweight (e.g. Monaco)\n -->\n @if (showDetails && (isToolExpanded || everExpanded())) {\n <div\n class=\"collapse tool-details m-t-8 p-8\"\n [attr.aria-label]=\"'Tool details for message latest tool: ' + _tool.toolName\"\n role=\"region\"\n [collapse]=\"!isToolExpanded\"\n [id]=\"'tool-call-' + _tool.toolCallId\"\n [isAnimated]=\"true\"\n data-cy=\"ai-tool-component\"\n >\n @if (toolDetailsComponent()) {\n <ng-container\n [ngComponentOutlet]=\"toolDetailsComponent()\"\n [ngComponentOutletInputs]=\"{ tool: _tool }\"\n ></ng-container>\n } @else {\n @let noneLabel = '(no data)' | translate;\n <pre\n class=\"fit-w small text-pre-wrap text-break-word\"\n [attr.data-label]=\"'Tool input' | translate\"\n >{{ _tool.input || noneLabel | json }}</pre\n >\n\n @if (_tool.type === 'tool-result') {\n @if (\n typeof _tool.output === 'string' || _tool.output === undefined || _tool.output === null\n ) {\n <pre\n class=\"fit-w small text-pre-wrap text-break-word\"\n [attr.data-label]=\"'Tool output' | translate\"\n >{{ _tool.output || noneLabel }}</pre\n >\n } @else {\n <pre class=\"fit-w small text-pre-wrap text-break-word\">{{ _tool.output | json }}</pre>\n }\n }\n }\n </div>\n }\n\n @if (isApprovalRequested && approvalEnabled()) {\n <div\n class=\"btn-toolbar m-l-0 m-t-8 m-b-8\"\n [attr.aria-label]=\"'Tool approval actions' | translate\"\n role=\"toolbar\"\n >\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n [attr.data-cy]=\"'tool-deny-' + _tool.toolName\"\n (click)=\"approvalResponse.emit({ approved: false })\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"'block'\"\n aria-hidden=\"true\"\n ></i>\n {{ 'Deny' | translate }}\n </button>\n @if (!rememberApprovalEnabled()) {\n <!-- Tools requiring explicit approval on every call get no \"always approve\" options -->\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n [attr.data-cy]=\"'tool-approve-' + _tool.toolName\"\n (click)=\"approvalResponse.emit({ approved: true })\"\n >\n {{ 'Approve' | translate }}\n </button>\n } @else {\n <div\n class=\"btn-group\"\n role=\"group\"\n >\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n [attr.data-cy]=\"'tool-approve-' + _tool.toolName\"\n (click)=\"approvalResponse.emit({ approved: true })\"\n >\n {{ 'Approve' | translate }}\n </button>\n <div\n class=\"btn-group\"\n dropdown\n [container]=\"'body'\"\n c8yDropdownFocusTrap\n #approveDropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default btn-sm dropdown-toggle\"\n aria-label=\"{{ 'More approval options' | translate }}\"\n aria-haspopup=\"true\"\n [attr.aria-expanded]=\"approveDropdown.isOpen\"\n type=\"button\"\n dropdownToggle\n [attr.data-cy]=\"'tool-approve-options-' + _tool.toolName\"\n >\n <i\n c8yIcon=\"caret-down\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <ul\n class=\"dropdown-menu\"\n role=\"menu\"\n *dropdownMenu\n >\n <li>\n <button\n class=\"a-i-start\"\n title=\"{{ 'Always approve this tool' | translate }}\"\n type=\"button\"\n [attr.data-cy]=\"'tool-approve-always-' + _tool.toolName\"\n (click)=\"approvalResponse.emit({ approved: true, remember: 'tool' })\"\n >\n <i\n class=\"icon-16\"\n c8yIcon=\"ok\"\n aria-hidden=\"true\"\n ></i>\n <span>\n {{ 'Always approve this tool' | translate }}\n <small class=\"d-block text-muted\">\n {{ 'For this conversation only' | translate }}\n </small>\n </span>\n </button>\n </li>\n <li>\n <button\n class=\"a-i-start\"\n title=\"{{ 'Always approve all tools' | translate }}\"\n type=\"button\"\n [attr.data-cy]=\"'tool-approve-always-all-' + _tool.toolName\"\n (click)=\"approvalResponse.emit({ approved: true, remember: 'all' })\"\n >\n <i\n class=\"icon-16\"\n c8yIcon=\"approval\"\n aria-hidden=\"true\"\n ></i>\n <span>\n {{ 'Always approve all tools' | translate }}\n <small class=\"d-block text-muted\">\n {{\n 'For this conversation only, unlike the global auto-approve mode'\n | translate\n }}\n </small>\n </span>\n </button>\n </li>\n </ul>\n </div>\n </div>\n }\n </div>\n }\n</fieldset>\n","import { Pipe, PipeTransform } from '@angular/core';\n\n/**\n * Converts a JSON string to a markdown code block.\n */\n@Pipe({\n name: 'jsonToMarkdown',\n standalone: true\n})\nexport class JsonToMarkdownPipe implements PipeTransform {\n transform(value: string | null | undefined): string {\n if (!value) {\n return '```json\\nnull\\n```';\n }\n\n const escapedValue = value.replace(/\\\\/g, '\\\\\\\\').replace(/`/g, '\\\\`');\n return `\\`\\`\\`json\\n${escapedValue}\\n\\`\\`\\``;\n }\n}\n","import { ChangeDetectionStrategy, Component, input, signal } from '@angular/core';\nimport { AIMessagePart } from '@c8y/ngx-components/ai';\nimport {\n C8yTranslateDirective,\n C8yTranslatePipe,\n IconDirective,\n MarkdownToHtmlPipe\n} from '@c8y/ngx-components';\nimport { AsyncPipe, NgComponentOutlet } from '@angular/common';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\nimport { AssistantMessageContext } from './ai-chat-assistant-message.component';\nimport { AiChatToolCallComponent } from './ai-chat-tool-call.component';\nimport { JsonToMarkdownPipe } from './json-to-markdown.pipe';\n\n/** This renders a part of an assistant message. Currently only ToolCallPart is supported, but later we can expand this to deal with all part types. */\n@Component({\n selector: 'c8y-ai-chat-assistant-part',\n templateUrl: './ai-chat-assistant-part.component.html',\n standalone: true,\n imports: [\n NgComponentOutlet,\n C8yTranslateDirective,\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n MarkdownToHtmlPipe,\n AsyncPipe,\n AiChatToolCallComponent,\n JsonToMarkdownPipe\n ],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AiChatAssistantPartComponent {\n readonly part = input.required<AIMessagePart>();\n\n /** Whether this part is rendered as part of the main answer, or is an intermediate step with more muted rendering. */\n readonly displayAsPartOfMainAnswer = input(true);\n\n /**\n * The context needed to render a message.\n * This is a single input so we can extend in future without breaking people who have a custom rendering implementation.\n */\n readonly assistantMessageContext = input.required<AssistantMessageContext>();\n\n /** Tracks whether this is currently expanded (used for reasoning section). */\n protected readonly expanded = signal(false);\n\n protected toggleExpanded(): void {\n this.expanded.update(v => !v);\n }\n}\n","@let ctx = assistantMessageContext();\n@let _config = ctx.config;\n@let toolCallConfig = _config.toolCallConfig || {};\n@let _part = part();\n\n@if (_part.type === 'text') {\n <p\n [class.text-muted]=\"!displayAsPartOfMainAnswer()\"\n [innerHTML]=\"_part.text | markdownToHtml | async\"\n ></p>\n} @else if (_part.type === 'reasoning') {\n @let reasoningExpanded = expanded();\n\n <fieldset\n class=\"c8y-fieldset p-b-4 ai-tool-call__fieldset\"\n data-cy=\"ai-reasoning\"\n >\n <button\n class=\"btn-clean ai-tool-call__btn\"\n aria-label=\"{{ 'Toggle display of the reasoning section' | translate }}\"\n [attr.aria-expanded]=\"reasoningExpanded\"\n [attr.aria-controls]=\"'reasoning-content-message' + ctx.messageDisplayIndex\"\n type=\"button\"\n (click)=\"toggleExpanded()\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"'ai-sparkles'\"\n ></i>\n @let hideReasoning = 'Hide reasoning' | translate;\n @let showReasoning = 'Show reasoning' | translate;\n <span class=\"small\">{{ reasoningExpanded ? hideReasoning : showReasoning }}</span>\n <i\n class=\"m-l-4 icon-12 text-muted\"\n [c8yIcon]=\"reasoningExpanded ? 'collapse-arrow' : 'expand-arrow'\"\n ></i>\n </button>\n\n @let ariaLabel =\n 'Reasoning for message number {{ number }}' | translate: { number: ctx.messageDisplayIndex };\n <div\n class=\"collapse reasoning-content\"\n [attr.aria-label]=\"ariaLabel\"\n role=\"region\"\n [collapse]=\"!reasoningExpanded\"\n [id]=\"'reasoning-content-message' + ctx.messageDisplayIndex\"\n [isAnimated]=\"true\"\n data-cy=\"ai-reasoning-content\"\n >\n <div\n class=\"m-t-8 p-b-4 text-muted\"\n [innerHTML]=\"_part.text | markdownToHtml | async\"\n ></div>\n </div>\n </fieldset>\n} @else if (_part.type === 'object') {\n <p\n [class.text-muted]=\"!displayAsPartOfMainAnswer()\"\n [innerHTML]=\"_part.jsonContent | jsonToMarkdown | markdownToHtml | async\"\n data-cy=\"ai-object-content\"\n ></p>\n} @else if (_part.type === 'step-start') {\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"ai-step-start hidden-copy-label\"\n aria-hidden=\"true\"\n data-cy=\"ai-step-start-separator\"\n translate\n >--- (step separator) ---</span\n >\n} @else if (_part.type.startsWith('tool')) {\n @let tool = $any(_part);\n @let toolDisplay = toolCallConfig[tool.toolName];\n\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"hidden-copy-label\"\n aria-hidden=\"true\"\n translate\n [translateParams]=\"{ toolName: tool.toolName }\"\n ngNonBindable\n >--- Tool call: {{ toolName }} ---</span\n >\n\n @if (toolDisplay?.component) {\n <div data-cy=\"ai-tool-with-custom-component\">\n <ng-container\n [ngComponentOutlet]=\"toolDisplay.component\"\n [ngComponentOutletInputs]=\"{\n tool: tool,\n ctx: ctx\n }\"\n ></ng-container>\n </div>\n } @else if (!toolDisplay?.isHidden) {\n <!-- Don't allow expanding while tool call is in progress - it's unlikely to have anything worth rendering,\n and complicates implementation for the client to have to check for the isExecuting case.\n -->\n <c8y-ai-chat-tool-call\n [tool]=\"tool\"\n [isExecuting]=\"\n tool.type !== 'tool-result' &&\n !tool.type.startsWith('tool-approval') &&\n ctx.isMessageLoading\n \"\n [toolDetailsComponent]=\"_config.toolDetailsComponent?.(tool)\"\n [showDefaultToolDetails]=\"_config.showDefaultToolDetails === 'all'\"\n [executingLabel]=\"toolDisplay?.executingLabel\"\n [completedLabel]=\"toolDisplay?.completedLabel\"\n [labelProvider]=\"toolDisplay?.labelProvider\"\n [approvalEnabled]=\"\n ctx.messageDisplayIndex === 0 && !ctx.isMessageLoading && !!ctx.onToolApprovalResponse\n \"\n [rememberApprovalEnabled]=\"!ctx.canRememberToolApproval || ctx.canRememberToolApproval(tool)\"\n (approvalResponse)=\"ctx.onToolApprovalResponse?.(tool, $event)\"\n ></c8y-ai-chat-tool-call>\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n signal\n} from '@angular/core';\nimport { C8yTranslateModule, C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport {\n AIAssistantMessage,\n AIMessagePart,\n AssistantMessageDisplayConfig,\n ToolApprovalDecision,\n ToolCallPart\n} from '@c8y/ngx-components/ai';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { TranslateService } from '@ngx-translate/core';\nimport { CollapseModule } from 'ngx-bootstrap/collapse';\nimport { AiChatAssistantPartComponent } from './ai-chat-assistant-part.component';\n\n/**\n * Context object which includes the inputs needed for assistant message rendering.\n * If creating a custom component for assistant message rendering, you will receive this as an input.\n */\nexport interface AssistantMessageContext {\n message: AIAssistantMessage;\n config: AssistantMessageDisplayConfig;\n\n /** The message response is currently streaming in (not yet complete). */\n isMessageLoading: boolean;\n\n /** A number identifying this message in the chat history numbered from the latest - 0 is the latest, -1 is the previous, etc. */\n messageDisplayIndex: number;\n\n /**\n * Callback invoked when the user approves or denies a tool call that requires approval.\n * When set, approve/deny actions are offered on tool calls in the `tool-approval-requested` state.\n */\n onToolApprovalResponse?: (part: ToolCallPart, decision: ToolApprovalDecision) => void;\n\n /**\n * Whether the \"always approve\" options may be offered for a tool call awaiting approval.\n * Returns false for tools that must be approved explicitly on every call (configured via\n * `needsApproval`), which show plain approve/deny buttons instead. Defaults to true when\n * not provided.\n */\n canRememberToolApproval?: (part: ToolCallPart) => boolean;\n}\n\n/**\n * This is the default component used to render the contents of a message from the AI assistant, including\n * the main answer text, text from earlier steps, reasoning text and tool calls.\n */\n@Component({\n selector: 'c8y-ai-chat-assistant-message',\n templateUrl: './ai-chat-assistant-message.component.html',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n C8yTranslatePipe,\n IconDirective,\n CollapseModule,\n C8yTranslateModule,\n AiChatAssistantPartComponent\n ]\n})\nexport class AiChatAssistantMessageComponent {\n /**\n * The context needed to render a message.\n * This is a single input so we can extend in future without breaking people who have a custom rendering implementation.\n */\n readonly assistantMessageContext = input.required<AssistantMessageContext>();\n\n /**\n * By default this component will render a \"Working...\" indicator while streaming results. This input can turn that off if required.\n */\n readonly showWorkingIndicator = input(true);\n\n /**\n * Whether the thinking section is expanded. Initialized to false unless the message is still loading.\n * Call setThinkingExpanded() via viewChild to control this programmatically. Does nothing if appearance does not distinguish thinking steps.\n */\n protected readonly thinkingExpanded = signal(false);\n\n /**\n * Tracks which reasoning sections are expanded, keyed by step index.\n */\n protected readonly expandedReasoningStepIndices = signal(new Set<number>());\n\n private readonly translateService = inject(TranslateService);\n\n protected readonly thinkingAndMainAnswerParts = computed(() =>\n this.splitContentIntoThinkingAndMainAnswer(this.assistantMessageContext())\n );\n\n constructor() {\n // Expand when we initially set the message loading flag, without overwriting the value\n // any other time\n effect(() => {\n if (this.assistantMessageContext().isMessageLoading) {\n this.thinkingExpanded.set(true);\n }\n });\n }\n\n /**\n * This is public and exists for agent-chat to collapse older messages.\n * @param expanded Whether the thinking section should be expanded or not.\n */\n setThinkingExpanded(expanded: boolean): void {\n this.thinkingExpanded.set(expanded);\n }\n\n /**\n * Get a translated/translateable label for the specified tool.\n * @param tool The tool call part to get the label for.\n * @return The label to show for this tool call.\n */\n getToolLabel(tool: ToolCallPart): string {\n const isExecuting = tool.type !== 'tool-result';\n const config = this.assistantMessageContext().config;\n const toolCallConfig = config?.toolCallConfig?.[tool.toolName];\n if (toolCallConfig?.labelProvider) {\n try {\n const dynamicLabel = toolCallConfig.labelProvider(tool, this.translateService);\n // Run it through translate in case it contains gettext values\n if (dynamicLabel) return dynamicLabel;\n } catch (err) {\n // Should never happen, so report this - then fallback to default logic\n console.warn(`Error in labelProvider for tool ${tool.toolName}:`, err);\n }\n }\n\n if (isExecuting && toolCallConfig?.executingLabel) {\n return toolCallConfig.executingLabel;\n }\n if (!isExecuting && toolCallConfig?.completedLabel) {\n return toolCallConfig.completedLabel;\n }\n\n // If we have no specific label configured, use the default\n return this.translateService.instant(\n isExecuting ? gettext('Calling tool {{toolName}}') : gettext('Used tool {{toolName}}'),\n // Have to use the tool id since that's all we have\n { toolName: tool.toolName }\n );\n }\n\n protected toggleReasoningExpanded(stepIndex: number): void {\n this.expandedReasoningStepIndices.update(s => {\n const next = new Set(s);\n if (s.has(stepIndex)) {\n next.delete(stepIndex);\n } else {\n next.add(stepIndex);\n }\n return next;\n });\n }\n\n /**\n * Note: ctx is passed as a parameter rather than reading the signal in the template to ensure\n * it's totally aligned with what the template is rendering.\n * @param ctx The context for the assistant message.\n * @return The label to display for the reasoning section.\n */\n protected getThinkingLabel(ctx: AssistantMessageContext): string {\n return ctx.isMessageLoading\n ? gettext('Reasoning')\n : this.thinkingExpanded()\n ? gettext('Hide reasoning')\n : gettext('Show reasoning');\n }\n\n protected getToolName(part: AIMessagePart): string | undefined {\n return part.type.startsWith('tool-') ? (part as ToolCallPart).toolName : undefined;\n }\n\n protected experimental_nonFinalStepTextDisplay(\n ctx: AssistantMessageContext\n ): AssistantMessageDisplayConfig['experimental_nonFinalStepTextDisplay'] {\n // For now be conservative with the old behaviour, but hope to change this once we've got working really smoothly.\n return ctx.config?.experimental_nonFinalStepTextDisplay || 'main-answer';\n }\n\n /**\n * Splits the assistant message content into two arrays: thinking content and main answer content.\n * This also removes hidden tools.\n *\n * If using the experimental rendering modes, main answer content is text in the final step (if conditions are met) plus any tool calls configured to be shown with the main answer.\n * Thinking content is everything else (reasoning, earlier text, tool calls not shown with main answer).\n *\n * @param ctx The context for the assistant message.\n * @return An object with thinkingParts and mainAnswerParts arrays.\n */\n protected splitContentIntoThinkingAndMainAnswer(ctx: AssistantMessageContext): {\n thinkingParts: AIMessagePart[];\n mainAnswerParts: AIMessagePart[];\n } {\n // Remove hidden tools\n let content = ctx.message?.content || [];\n if (Object.values(ctx.config?.toolCallConfig || {}).some(c => c?.isHidden)) {\n content = (ctx.message?.content || []).filter(\n part => !ctx.config?.toolCallConfig?.[this.getToolName(part) || '']?.isHidden\n );\n }\n\n // Putting this check here keeps things safe by ensuring there is no chance of any rendering differences\n // during streaming unless in one of the experimental modes. This means the rest of this method only applies\n // to the experimental rendering.\n if (this.experimental_nonFinalStepTextDisplay(ctx) === 'main-answer') {\n return { thinkingParts: [], mainAnswerParts: content };\n }\n\n const { finalStepStart, finalStepHasText } = this.findFinalStepWithText(content);\n\n const hasToolCalls = content.some(part => part.type.startsWith('tool-'));\n // Since we don't bother with a step-start at index 0 for the first step, add one\n const stepCount =\n content.filter((part, index) => index > 0 && part.type === 'step-start').length + 1;\n\n // The final step text goes in the main answer area if there are no pending tool calls\n // (since otherwise the tools would show below it), and\n // message has finished loading, or we're expecting more steps than this.\n // Note that we check all steps for toolCalls not just the current one, for the sake of \"fake\" tool calls created by preprocessAgentMessage\n // where additional step boundaries may be added to simplify parsing.\n const shouldShowLastTextAsMainAnswer =\n finalStepHasText &&\n finalStepStart !== -1 &&\n !hasToolCalls &&\n (!ctx.isMessageLoading || stepCount >= (ctx.config?.experimental_expectedStepCount || 2));\n\n if (!shouldShowLastTextAsMainAnswer) {\n return { thinkingParts: content, mainAnswerParts: [] };\n }\n\n const thinkingParts: AIMessagePart[] = [];\n const mainAnswerParts: AIMessagePart[] = [];\n\n // Split the content: final step and promoted tool calls go to main answer, everything else to thinking\n content.forEach((part, index) => {\n const isPromotedToolCall =\n ctx.config?.toolCallConfig?.[this.getToolName(part) || '']?.isShownWithMainAnswer;\n\n // This ensures promoted tool calls never go to the collapseable thinking area\n if (index >= finalStepStart || isPromotedToolCall) {\n mainAnswerParts.push(part);\n } else {\n thinkingParts.push(part);\n }\n });\n\n return { thinkingParts, mainAnswerParts };\n }\n\n /**\n * Scans backwards through the content parts to find the step-start index for the last step\n * that contains at least one text part. Skips trailing empty steps (step-start with no text after).\n *\n * @returns `finalStepStart` — index of the step-start part, or 0 if content belongs to the implicit first step.\n * `finalStepHasText` — whether a step with text was found at all.\n */\n private findFinalStepWithText(content: AIMessagePart[]): {\n finalStepStart: number;\n finalStepHasText: boolean;\n } {\n let finalStepStart = 0;\n let finalStepHasText = false;\n for (let i = content.length - 1; i >= 0; i--) {\n if (content[i].type === 'text') {\n finalStepHasText = true;\n }\n if (content[i].type === 'step-start') {\n if (finalStepHasText) {\n finalStepStart = i;\n break;\n } else if (i === content.length - 1) {\n // Trailing empty step-start — keep looking\n continue;\n } else {\n // step-start found but no text in that step\n finalStepStart = -1;\n break;\n }\n }\n }\n return { finalStepStart, finalStepHasText };\n }\n}\n","@let ctx = assistantMessageContext();\n@let parts = ctx.message.content;\n@let _config = ctx.config;\n\n<!-- \nWe show the assistant message in (up to) 3 slots:\n- collapsible thinking block (for intermediate step text, standard tool calls, etc)\n- special \"artifact\" tools that update user artifacts and need prominent display (e.g. for code edits made by the AI)\n- the main answer (typically from the final step)\n\nThis is a standard approach for AI chats - step text and tools from an LLM are treated as a work log, i.e. useful to \ndisplay progress while streaming the response, but only the text from the last step after all tool calls gives the main answer of the AI to the user. \n\nDepending on configuration, we have an experimental option (if we need it) to style the thinking block the same as the main answer. \n\nOnce the message finishes loading we know the final step IS the main content, but if it's still steaming \nwe don't know for sure which step has the final/main answer until the LLM has actually finished so have to take a heuistic guess \n(and minimize jumping in the UI). \n\nFor applications where we expect tool calls in most responses, assume the 2nd step is probably the final text; \nfor applications where tool calls are less ubiquitous, assume the first step is main answer until proved otherwise. \nThis minimizes jumping (except when there are >2 steps, which is rare).\n\n-->\n\n@let contentSplit = thinkingAndMainAnswerParts();\n@let nonFinalStepTextDisplay = experimental_nonFinalStepTextDisplay(ctx);\n\n<!-- Thinking steps section - holds reasoning, text from non-final steps, and standard/non-artifact tool calls -->\n\n@if (contentSplit.thinkingParts.length > 0) {\n <div\n class=\"m-b-8 text-muted\"\n [class.thinking-block]=\"nonFinalStepTextDisplay === 'collapsible-thinking-block'\"\n [class.small]=\"nonFinalStepTextDisplay === 'muted-main-answer'\"\n [class.thinking-steps-appearance]=\"nonFinalStepTextDisplay\"\n data-cy=\"thinking-steps\"\n >\n @if (nonFinalStepTextDisplay === 'collapsible-thinking-block') {\n <button\n class=\"btn btn-clean btn-xs text-muted p-l-0\"\n aria-label=\"{{ 'Toggle collapse of the reasoning section' | translate }}\"\n [attr.aria-expanded]=\"thinkingExpanded()\"\n [attr.aria-controls]=\"'thinking-content-' + ctx.messageDisplayIndex\"\n type=\"button\"\n (click)=\"thinkingExpanded.set(!thinkingExpanded())\"\n >\n <span class=\"small\">{{ getThinkingLabel(ctx) }}</span>\n <i\n class=\"m-l-4 icon-12\"\n [c8yIcon]=\"thinkingExpanded() ? 'collapse-arrow' : 'expand-arrow'\"\n ></i>\n </button>\n }\n\n @let ariaLabel =\n 'Reasoning for message number {{ number }}' | translate: { number: ctx.messageDisplayIndex };\n <div\n class=\"collapse\"\n [attr.aria-label]=\"ariaLabel\"\n role=\"region\"\n [collapse]=\"nonFinalStepTextDisplay === 'collapsible-thinking-block' && !thinkingExpanded()\"\n [id]=\"'thinking-content-' + ctx.messageDisplayIndex\"\n [isAnimated]=\"true\"\n >\n <div\n [class]=\"\n nonFinalStepTextDisplay === 'collapsible-thinking-block'\n ? 'thinking-content bg-level-1 m-t-8 p-8 border-left-accent small m-b-0 text-muted'\n : ''\n \"\n >\n @for (part of contentSplit.thinkingParts; track $index) {\n @if (part.type !== 'step-start' || $index > 0) {\n <c8y-ai-chat-assistant-part\n [part]=\"part\"\n [assistantMessageContext]=\"ctx\"\n [displayAsPartOfMainAnswer]=\"nonFinalStepTextDisplay !== 'muted-main-answer'\"\n ></c8y-ai-chat-assistant-part>\n }\n }\n </div>\n </div>\n </div>\n}\n\n<!-- Main answer area contains the text from the final step, and \n any promoted tool calls which are too important to be hidden in the collapeable thinking area -->\n<div\n class=\"message-content\"\n data-cy=\"ai-main-answer-content\"\n>\n @for (part of contentSplit.mainAnswerParts; track $index) {\n <c8y-ai-chat-assistant-part\n [part]=\"part\"\n [assistantMessageContext]=\"ctx\"\n [displayAsPartOfMainAnswer]=\"true\"\n ></c8y-ai-chat-assistant-part>\n }\n</div>\n\n@if (ctx.isMessageLoading && showWorkingIndicator()) {\n <!-- Once the message starts to stream, show a small/low-key thinking indicator -->\n <div\n class=\"text-muted text-12 gap-4 fade-in-out d-flex j-c-start a-i-center\"\n aria-live=\"polite\"\n role=\"status\"\n data-cy=\"working-indicator\"\n >\n <em>\n {{ 'Working' | translate }}\n </em>\n <span\n class=\"working-indicator__dots\"\n aria-hidden=\"true\"\n >\n <span></span>\n <span></span>\n <span></span>\n </span>\n </div>\n}\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An action button that can be added to chat messages.\n * Typically used for actions like copying, regenerating, or providing feedback on messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message-action',\n templateUrl: './ai-chat-message-action.component.html',\n standalone: true,\n imports: [TooltipModule, C8yTranslatePipe, IconDirective]\n})\nexport class AiChatMessageActionComponent {\n /**\n * Set to true to use content projection for custom action button content.\n */\n @Input()\n custom = false;\n\n /**\n * Disables the action button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Tooltip text displayed when hovering over the action button.\n */\n @Input()\n tooltip = '';\n\n /**\n * Icon to display in the action button.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'cog';\n\n /**\n * Emitted when the action button is clicked.\n */\n @Output()\n actionClicked = new EventEmitter<void>();\n}\n","@if (!custom) {\n <button\n class=\"btn btn-dot text-muted\"\n [attr.aria-label]=\"tooltip | translate\"\n [tooltip]=\"tooltip | translate\"\n [adaptivePosition]=\"true\"\n [delay]=\"500\"\n (click)=\"actionClicked.emit()\"\n [disabled]=\"disabled\"\n >\n <i\n class=\"text-12\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n} @else {\n <ng-content></ng-content>\n}\n","import { Component, computed, input, inject, ChangeDetectionStrategy } from '@angular/core';\n\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { C8yTranslatePipe, DatePipe } from '@c8y/ngx-components';\nimport { NgClass } from '@angular/common';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { TranslateService } from '@ngx-translate/core';\n\n/**\n * A container for content and actions that should be rendered for each chat message.\n *\n * Project content into this component to display the message, for example add an `<ai-chat-assistant-message>`\n * for assistant messages, and a simple `markdownToHtml | async` rendering of the content for user messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message',\n templateUrl: './ai-chat-message.component.html',\n styleUrl: './ai-chat-message.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgClass, TooltipModule, C8yTranslatePipe, DatePipe]\n})\nexport class AiChatMessageComponent {\n readonly role = input<AIMessage['role']>();\n readonly message = input<AIMessage>();\n\n private readonly translateService = inject(TranslateService);\n\n private readonly roleResolved = computed(() => {\n return this.message()?.role || this.role();\n });\n\n /**\n * Generates an accessible label for the message container: role (user or assistant) and\n * timestamp if available.\n *\n * Deliberately short - the actual message content is already exposed to assistive technology via\n * the normal (structured) DOM content, so duplicating it here as a flat string would just repeat\n * a long, unstructured block of text, especially for multi-paragraph assistant responses.\n * @returns The aria-label string for screen readers\n */\n readonly ariaLabel = computed(() => this.messageContentAriaLabel());\n\n /**\n * Generates an accessible label for the message content.\n * Prefixes the content with contextual information about who sent it.\n * @returns The aria-label string with prefixed role information\n */\n readonly messageContentAriaLabel = computed(() => {\n const msg = this.message();\n const time =\n msg.role != 'system' && msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : '';\n let tpl: string;\n if (time) {\n tpl =\n this.roleResolved() === 'user'\n ? gettext('User message at {{ time }}')\n : gettext('Assistant message at {{ time }}');\n } else {\n tpl = this.roleResolved() === 'user' ? gettext('User message') : gettext('Assistant message');\n }\n return this.translateService.instant(tpl, { time });\n });\n}\n","<div\n class=\"d-col\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"article\"\n>\n <div\n class=\"chat-message text-break-word\"\n [ngClass]=\"{\n 'user-message': message()?.role === 'user' || role() === 'user',\n 'agent-message': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->\n <span\n class=\"hidden-copy-label\"\n aria-hidden=\"true\"\n >\n {{ `====== ${messageContentAriaLabel()} ======` }}</span\n >\n\n <!-- Apply the class and aria-label to both the main content and whatever is projected, so we get the same styling by default -->\n <div\n class=\"message-content\"\n [attr.aria-label]=\"messageContentAriaLabel()\"\n >\n <div style=\"display: contents\">\n <ng-content select=\":not(c8y-ai-chat-message-action)\"></ng-content>\n </div>\n </div>\n @if (message()?.timestamp) {\n <div class=\"message-timestamp\">\n <span\n tabindex=\"0\"\n [tooltip]=\"message()?.timestamp | c8yDate\"\n >\n {{ message()?.timestamp | c8yDate: 'adaptiveDate' }}\n </span>\n </div>\n }\n </div>\n <div\n class=\"message-action\"\n [attr.aria-label]=\"'Message actions' | translate\"\n role=\"toolbar\"\n [ngClass]=\"{\n 'user-action showOnHover': message()?.role === 'user' || role() === 'user',\n 'agent-action p-l-16': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <ng-content select=\"c8y-ai-chat-message-action\"></ng-content>\n </div>\n</div>\n","import { Injectable, NgZone, inject } from '@angular/core';\nimport { Observable } from 'rxjs';\n\n/**\n * Minimal typing for a Web Speech API recognition result event. The `SpeechRecognition` interface\n * and its events are not part of the DOM library types shipped with the TypeScript version used in\n * this repo, so only the shape actually consumed here is declared. The nested result types\n * (`SpeechRecognitionResultList` and friends) are provided by `lib.dom`.\n */\ninterface SpeechRecognitionResultEvent {\n readonly resultIndex: number;\n readonly results: SpeechRecognitionResultList;\n}\n\n/** Minimal typing for a Web Speech API recognition error event. */\ninterface SpeechRecognitionErrorEvent {\n readonly error: string;\n readonly message: string;\n}\n\n/** Minimal typing for a Web Speech API recognition instance. */\ninterface SpeechRecognitionInstance {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n onresult: ((event: SpeechRecognitionResultEvent) => void) | null;\n onerror: ((event: SpeechRecognitionErrorEvent) => void) | null;\n onend: ((event: Event) => void) | null;\n start(): void;\n stop(): void;\n abort(): void;\n}\n\n/** Constructor for the browser's speech recognition object (standard or `webkit`-prefixed). */\ntype SpeechRecognitionConstructor = new () => SpeechRecognitionInstance;\n\n/** Options accepted when starting a recognition session. */\nexport interface SpeechRecognitionOptions {\n /** BCP-47 language tag to recognize, e.g. `en-US`. Defaults to the browser language. */\n lang?: string;\n /** Whether to emit interim (not yet final) results as the user speaks. Default: true. */\n interimResults?: boolean;\n}\n\n/**\n * Thin wrapper around the browser's Web Speech API (`SpeechRecognition`) used to transcribe speech\n * to text. The API is not available in every browser, so consumers must check {@link isSupported}\n * before offering speech input.\n */\n@Injectable({ providedIn: 'root' })\nexport class SpeechRecognitionService {\n private readonly ngZone = inject(NgZone);\n private readonly recognitionConstructor = this.resolveConstructor();\n\n /** Whether the current browser exposes the Web Speech API required for speech-to-text. */\n get isSupported(): boolean {\n return !!this.recognitionConstructor;\n }\n\n /**\n * Starts a recognition session and emits the cumulative transcript recognized so far on every\n * update (including interim results, when enabled). The observable completes when recognition\n * ends and errors with the API error code (a string such as `not-allowed`) when it fails.\n * Unsubscribing aborts an in-progress recognition.\n */\n listen(options: SpeechRecognitionOptions = {}): Observable<string> {\n return new Observable<string>(subscriber => {\n if (!this.recognitionConstructor) {\n subscriber.error('not-supported');\n return undefined;\n }\n\n const recognition = new this.recognitionConstructor();\n recognition.lang = options.lang || navigator.language;\n recognition.interimResults = options.interimResults ?? true;\n recognition.continuous = true;\n recognition.maxAlternatives = 1;\n\n // The Web Speech API callbacks are not patched by zone.js, so run them inside the Angular\n // zone to keep change detection working for consumers.\n recognition.onresult = event =>\n this.ngZone.run(() => subscriber.next(this.collectTranscript(event)));\n recognition.onerror = event => this.ngZone.run(() => subscriber.error(event.error));\n recognition.onend = () => this.ngZone.run(() => subscriber.complete());\n\n recognition.start();\n\n return () => {\n recognition.onresult = null;\n recognition.onerror = null;\n recognition.onend = null;\n recognition.abort();\n };\n });\n }\n\n /** Joins the transcripts of every recognition result into a single string. */\n private collectTranscript(event: SpeechRecognitionResultEvent): string {\n let transcript = '';\n for (let i = 0; i < event.results.length; i++) {\n transcript += event.results[i][0].transcript;\n }\n return transcript;\n }\n\n /** Resolves the recognition constructor from the window, handling the `webkit` prefix. */\n private resolveConstructor(): SpeechRecognitionConstructor | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n const speechWindow = window as typeof window & {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n };\n return speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition;\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n computed,\n inject,\n input,\n model,\n output,\n signal\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n AlertService,\n AppStateService,\n C8yTranslatePipe,\n IconDirective\n} from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { Subscription } from 'rxjs';\nimport { SpeechRecognitionService } from './speech-recognition.service';\n\n/**\n * A microphone button for the `c8y-ai-chat` action bar that transcribes speech into the chat input\n * using the browser's Web Speech API. Recognized text is appended to the current `prompt`.\n *\n * The button is only rendered when the current browser supports the Web Speech API, so it stays\n * hidden where speech input is unavailable. While a recognition session is running the microphone\n * icon pulses.\n *\n * `c8y-ai-chat` renders this button automatically unless `config.enableSpeechToText` is `false`, so\n * you normally do not place it yourself.\n */\n@Component({\n selector: 'c8y-ai-chat-speech-to-text',\n templateUrl: './ai-chat-speech-to-text.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [C8yTranslatePipe, IconDirective],\n host: { class: 'd-contents' }\n})\nexport class AiChatSpeechToTextComponent {\n private readonly speechRecognition = inject(SpeechRecognitionService);\n private readonly alertService = inject(AlertService);\n private readonly destroyRef = inject(DestroyRef);\n private readonly appState = inject(AppStateService);\n\n /**\n * Disables the button, for example while the chat is loading or otherwise unavailable. The\n * button is still rendered (see {@link isAvailable} for whether it is offered at all), just\n * not interactive.\n */\n readonly disabled = input(false);\n\n /**\n * BCP-47 language tag to recognize, e.g. `en-US`. When not set, the application's active UI\n * language is used (falling back to the browser language).\n */\n readonly lang = input<string>();\n\n /**\n * The chat input text. Recognized speech is appended to it. Supports two-way binding with\n * `[(prompt)]`.\n */\n readonly prompt = model<string>('');\n\n /**\n * Whether a recognition session is currently running. Drives the pulsing microphone icon.\n */\n readonly isListening = signal(false);\n\n /**\n * Emits whenever listening starts (`true`) or stops (`false`), so the host can react, for example\n * by adapting the chat input placeholder while the user is dictating.\n */\n readonly listeningChange = output<boolean>();\n\n /**\n * Whether the button should be shown at all: the browser supports the Web Speech API. Callers\n * that want to withhold the feature entirely (as `c8y-ai-chat` does via\n * `config.enableSpeechToText`) should not render this component rather than pass a \"disabled\"\n * flag here - `disabled` only controls interactivity of an already-shown button.\n */\n readonly isAvailable = computed(() => this.speechRecognition.isSupported);\n\n protected readonly startLabel = gettext('Start voice input');\n protected readonly stopLabel = gettext('Stop voice input');\n\n /**\n * The input text present when listening started, so recognized speech is appended to it.\n */\n private textBeforeListening = '';\n private listenSubscription?: Subscription;\n\n /**\n * Starts listening when idle, or stops the current session when already listening.\n */\n toggleListening(): void {\n if (this.isListening()) {\n this.stopListening();\n } else {\n this.startListening();\n }\n }\n\n private startListening(): void {\n this.listenSubscription?.unsubscribe();\n this.textBeforeListening = (this.prompt() ?? '').trim();\n this.setListening(true);\n this.listenSubscription = this.speechRecognition\n .listen({ lang: this.resolveLang() })\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: transcript => this.prompt.set(this.appendTranscript(transcript)),\n error: error => this.handleError(error),\n complete: () => this.setListening(false)\n });\n }\n\n private stopListening(): void {\n this.listenSubscription?.unsubscribe();\n this.setListening(false);\n }\n\n /**\n * Resolves the language to recognize: the explicit {@link lang} input when set, otherwise the\n * application's active UI language. The stored language uses an underscore region separator\n * (e.g. `zh_CN`), so it is normalized to the hyphenated BCP-47 form the Web Speech API expects.\n */\n private resolveLang(): string | undefined {\n return this.lang() || this.appState.state.lang?.replace('_', '-');\n }\n\n /** Updates the listening state and notifies the host, ignoring no-op transitions. */\n private setListening(listening: boolean): void {\n if (this.isListening() === listening) {\n return;\n }\n this.isListening.set(listening);\n this.listeningChange.emit(listening);\n }\n\n /**\n * Appends the recognized transcript to the text that was present when listening started.\n */\n private appendTranscript(transcript: string): string {\n const recognized = transcript.trim();\n if (!recognized) {\n return this.textBeforeListening;\n }\n return this.textBeforeListening ? `${this.textBeforeListening} ${recognized}` : recognized;\n }\n\n /**\n * Ends the session and, for errors the user can act on (such as a denied microphone permission),\n * shows an alert. Benign outcomes like \"no speech detected\" or a user-initiated stop are ignored.\n */\n private handleError(error: unknown): void {\n this.setListening(false);\n if (error === 'no-speech' || error === 'aborted') {\n return;\n }\n console.error('Speech recognition failed:', error);\n if (error === 'not-allowed' || error === 'service-not-allowed') {\n this.alertService.danger(\n gettext('Microphone access is blocked. Allow microphone access to use voice input.')\n );\n } else {\n this.alertService.danger(gettext('Voice input failed. Try again.'));\n }\n }\n}\n","@if (isAvailable()) {\n @let label = (isListening() ? stopLabel : startLabel) | translate;\n <button\n class=\"btn btn-dot c8y-speech-to-text-btn\"\n [class.c8y-speech-to-text-btn--listening]=\"isListening()\"\n [attr.title]=\"label\"\n [attr.aria-label]=\"label\"\n [attr.aria-pressed]=\"isListening()\"\n type=\"button\"\n [disabled]=\"disabled()\"\n (click)=\"toggleListening()\"\n >\n <i\n class=\"c8y-speech-to-text-btn__icon\"\n [c8yIcon]=\"'microphone'\"\n aria-hidden=\"true\"\n ></i>\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n role=\"status\"\n >\n @if (isListening()) {\n {{ 'Listening…' | translate }}\n }\n </span>\n </button>\n}\n","import { Component, input, output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\n\n/**\n * A suggestion chip that can be displayed in the chat interface.\n * When clicked, it automatically populates and sends a predefined prompt.\n */\n@Component({\n selector: 'c8y-ai-chat-suggestion',\n templateUrl: './ai-chat-suggestion.component.html',\n host: { class: 'd-contents' },\n standalone: true,\n imports: [IconDirective, C8yTranslatePipe]\n})\nexport class AiChatSuggestionComponent {\n /**\n * The visible label text displayed on the suggestion chip.\n */\n readonly label = input.required<string>();\n\n /**\n * The prompt text that will be sent when the suggestion is clicked.\n */\n readonly prompt = input.required<string>();\n\n /**\n * Icon to display alongside the suggestion label.\n */\n readonly icon = input<SupportedIconsSuggestions>('c8y-bulb');\n\n /**\n * When true, uses AI-styled buttons instead of default styling.\n */\n readonly useAiButtons = input(false);\n\n /**\n * Disables the suggestion chip when true.\n */\n readonly disabled = input(false);\n\n /**\n * Emitted when the suggestion is clicked, providing the prompt as an AIMessage.\n */\n readonly suggestionClicked = output<AIMessage>();\n\n /**\n * Handles suggestion click and emits the prompt as a user message.\n */\n suggest() {\n this.suggestionClicked.emit({\n content: this.prompt(),\n role: 'user',\n timestamp: new Date().toISOString()\n });\n }\n}\n","@if (!useAiButtons()) {\n <button\n class=\"btn btn-default btn-sm\"\n [title]=\"prompt() | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled()\"\n >\n <i [c8yIcon]=\"icon()\"></i>\n {{ label() | translate }}\n </button>\n} @else {\n <button\n class=\"btn btn-sm btn-ai\"\n [title]=\"prompt() | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled()\"\n >\n <span>{{ label() | translate }}</span>\n </button>\n}\n","import { AsyncPipe, NgClass, NgTemplateOutlet } from '@angular/common';\nimport { CdkTrapFocus } from '@angular/cdk/a11y';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n effect,\n ElementRef,\n EventEmitter,\n Input,\n input,\n Output,\n signal,\n TemplateRef,\n viewChild\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n C8yTranslatePipe,\n IconDirective,\n MarkdownToHtmlPipe,\n NumberPipe,\n TextareaAutoresizeDirective\n} from '@c8y/ngx-components';\nimport { AIMessage, ChatConfig } from '@c8y/ngx-components/ai';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AiChatActionComponent } from './ai-chat-action.component';\nimport { AiChatMessageComponent } from './ai-chat-message.component';\nimport { AiChatSpeechToTextComponent } from './ai-chat-speech-to-text.component';\nimport { BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An interactive chat interface component for AI-powered conversations.\n * Displays messages in a conversation format with support for loading states,\n * custom configuration, and markdown formatting.\n */\n@Component({\n selector: 'c8y-ai-chat',\n templateUrl: './ai-chat.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n C8yTranslatePipe,\n FormsModule,\n TextareaAutoresizeDirective,\n IconDirective,\n NgClass,\n NgTemplateOutlet,\n MarkdownToHtmlPipe,\n AsyncPipe,\n TooltipModule,\n BsDropdownModule,\n NumberPipe,\n AiChatSpeechToTextComponent,\n CdkTrapFocus\n ],\n standalone: true,\n host: { class: 'd-contents' }\n})\nexport class AiChatComponent {\n /**\n * Indicates whether the chat is currently processing a request.\n * When true, displays a cancel button instead of send button and disables the input.\n */\n @Input()\n set isLoading(value: boolean) {\n if (value === this._isLoading) return;\n this._isLoading = value;\n // `aria-busy` on the log holds streamed tokens back, so announce start and end instead.\n this.statusAnnouncement.set(\n value ? gettext('Generating response…') : gettext('Response complete')\n );\n }\n get isLoading(): boolean {\n return this._isLoading;\n }\n private _isLoading = false;\n\n /** Announced politely when the response starts and when it finishes. */\n readonly statusAnnouncement = signal('');\n\n /**\n * Disables the chat input and send button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * The current text in the chat input field. Supports two-way binding.\n */\n @Input()\n prompt = '';\n\n /**\n * Template for rendering custom suggestions below the input field. Can be used to provide predefined prompts or actions\n * from a dynamic source such as the AI. To use this, wrap your suggestion components in an `<ng-template #suggestionsRef>`\n * (where `suggestionsRef` matches the suggestionsTemplate reference);\n */\n @Input()\n suggestionsTemplate?: TemplateRef<any>;\n\n /** Template for customizing the welcome view using `<ng-template>`. */\n @Input() welcomeTemplate?: TemplateRef<any>;\n\n @Input() cumulativeUsage?: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n } | null = null;\n\n /**\n * Emitted when the user sends a message.\n * Provides an AIMessage object with role, content, and timestamp.\n */\n @Output()\n onMessage = new EventEmitter<AIMessage>();\n\n /**\n * Emitted when the user cancels an ongoing operation during loading state.\n */\n @Output()\n onCancel = new EventEmitter<void>();\n\n /**\n * Child message components displayed in the chat.\n */\n readonly messages = contentChildren(AiChatMessageComponent);\n\n /**\n * Action components projected into the action bar beneath the input box.\n */\n private readonly projectedActions = contentChildren(AiChatActionComponent);\n\n /**\n * Action components provided programmatically. Used by wrapper components (such as\n * `c8y-agent-chat`) to forward actions projected by their own consumers, since content queries do\n * not reach components re-projected through a nested `ng-content`.\n */\n readonly actions = input<readonly AiChatActionComponent[]>([]);\n\n /** All actions from content projection and the `actions` input, in declaration order. */\n private readonly allActions = computed(() => [...this.projectedActions(), ...this.actions()]);\n\n /** Whether any action is present, i.e. whether the action bar should be rendered. */\n readonly hasActionBar = computed(() => this.allActions().length > 0);\n\n /** Actions placed on the left side of the action bar. */\n readonly leftActions = computed(() =>\n this.allActions().filter(action => action.placement() === 'left')\n );\n\n /** Actions placed on the right side of the action bar. */\n readonly rightActions = computed(() =>\n this.allActions().filter(action => action.placement() === 'right')\n );\n\n /** Actions collected into the overflow (`more`) dropdown on the right side. */\n readonly moreActions = computed(() =>\n this.allActions().filter(action => action.placement() === 'more')\n );\n\n /**\n * Reference to the scroll container for the chat messages.\n */\n private readonly scrollContainer = viewChild<ElementRef<HTMLDivElement>>('chatScrollContainer');\n\n private readonly chatInput = viewChild<ElementRef<HTMLTextAreaElement>>('chatInput');\n\n readonly componentId = `chat-${crypto.randomUUID()}`;\n\n /** Whether the speech-to-text button is currently listening; swaps the input placeholder. */\n readonly isListeningForSpeech = signal(false);\n\n private _config: ChatConfig = {\n headline: gettext('Welcome!'),\n welcomeText: '',\n welcomePosition: 'top',\n title: gettext('What can I help you with?'),\n placeholder: gettext('Type your message here...'),\n listeningPlaceholder: gettext('Listening…'),\n scrollbarOnlyOnHover: false,\n sendButtonText: gettext('Send'),\n cancelButtonText: gettext('Cancel'),\n disclaimerText: gettext(\n 'AI-generated responses can contain errors. Verify the details before use.'\n ),\n userInterfaceIcons: {\n send: 'arrow-circle-up',\n cancel: 'stop-circle'\n }\n };\n\n constructor() {\n // Auto-scroll to bottom when messages change\n effect(() => {\n this.messages(); // track changes\n const container = this.scrollContainer()?.nativeElement;\n if (!container) return;\n // In column-reverse, scrollTop=0 IS the visual bottom.\n // Only snap back if user is already near the bottom (wasn't scrolled up).\n if (container.scrollTop < 50) {\n container.scrollTop = 0;\n }\n });\n }\n\n /**\n * Configuration object for customizing labels, placeholders, and icons.\n * Accepts partial configuration to override defaults.\n * @param value Partial configuration to merge with defaults.\n * @returns The complete configuration object.\n */\n @Input()\n set config(value: Partial<ChatConfig>) {\n this._config = { ...this._config, ...value };\n }\n get config(): ChatConfig {\n return this._config;\n }\n\n /**\n * Handles message submission when the user sends a message.\n * Emits the onMessage event and clears the input.\n * @param $event The event object from the form submission\n */\n sendMessage($event: Event): void {\n $event.preventDefault();\n if (!this.prompt) return;\n this.onMessage.emit({\n role: 'user',\n content: this.prompt,\n timestamp: new Date().toISOString()\n });\n this.prompt = '';\n }\n\n /**\n * Handles cancellation of ongoing operations during loading state.\n * Emits the onCancel event.\n */\n cancel(): void {\n this.onCancel.emit();\n }\n\n /**\n * Moves keyboard focus to the prompt input. Call this after removing or replacing messages, so\n * that focus is not lost with the element the user was on.\n */\n focusInput(): void {\n this.chatInput()?.nativeElement.focus();\n }\n}\n","<div\n class=\"d-col fit-w flex-grow min-height-0\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n <!-- Streamed tokens are withheld while the log is busy, so announce start and end here. -->\n <div\n class=\"sr-only\"\n aria-live=\"polite\"\n role=\"status\"\n >\n {{ statusAnnouncement() | translate }}\n </div>\n @if (messages().length > 0) {\n <div\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n [attr.aria-busy]=\"isLoading\"\n role=\"log\"\n #chatScrollContainer\n [ngClass]=\"{\n 'inner-scroll': true,\n 'd-col-reverse': true,\n 'scrollbar-only-on-hover': config.scrollbarOnlyOnHover,\n 'flex-grow': true,\n 'min-height-0': true,\n 'bg-level-0': true\n }\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"[slot='before-messages']\"></ng-content>\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content select=\"[slot='after-messages']\"></ng-content>\n </div>\n </div>\n }\n <div\n [ngClass]=\"{\n 'd-col fit-h': messages().length === 0\n }\"\n >\n @if (messages().length === 0) {\n <div\n class=\"p-24 d-col fit-h inner-scroll\"\n aria-live=\"polite\"\n role=\"status\"\n [ngClass]=\"{\n 'j-c-start': config.welcomePosition === 'top',\n 'j-c-center': config.welcomePosition === 'center',\n 'j-c-end': config.welcomePosition === 'bottom'\n }\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n @if (config.title.length > 0) {\n <p class=\"p-b-8 text-pretty\">{{ config.title | translate }}</p>\n }\n <div class=\"text-pretty chat-message min-height-0\">\n <div\n class=\"text-muted\"\n [innerHTML]=\"config.welcomeText | translate | markdownToHtml | async\"\n ></div>\n @if (welcomeTemplate) {\n <ng-container *ngTemplateOutlet=\"welcomeTemplate\"></ng-container>\n }\n </div>\n </div>\n }\n <div\n class=\"chat-input\"\n [class.bg-level-1]=\"config.appearance !== 'flat'\"\n >\n <!-- For simple cases allow ng-content projection; however this doesn't seem to work with dynamic \n suggestion lists from a signal (e.g. returned from the AI) so also support `suggestionsTemplate` for that. \n -->\n @if (!isLoading) {\n <div\n [class]=\"\n 'd-flex inner-scroll gap-8 p-l-16 p-r-16 p-b-16 ' +\n (config.suggestionsLayout === 'vertical' ? 'flex-wrap' : 'a-i-center')\n \"\n [attr.aria-label]=\"'Suggested prompts' | translate\"\n role=\"group\"\n >\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n\n @if (suggestionsTemplate) {\n <ng-container *ngTemplateOutlet=\"suggestionsTemplate\"></ng-container>\n }\n </div>\n }\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n [class.text-muted]=\"isLoading\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n placeholder=\"{{\n (isListeningForSpeech() && config.listeningPlaceholder\n ? config.listeningPlaceholder\n : config.placeholder\n ) | translate\n }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"!isLoading && sendMessage($event)\"\n [disabled]=\"disabled\"\n c8y-textarea-autoresize\n #chatInput\n ></textarea>\n <div class=\"chat-input-group-btn\">\n <ng-content select=\"[slot='input-actions']\"></ng-content>\n @if (config.enableSpeechToText !== false) {\n <c8y-ai-chat-speech-to-text\n [(prompt)]=\"prompt\"\n [disabled]=\"disabled || isLoading\"\n (listeningChange)=\"isListeningForSpeech.set($event)\"\n ></c8y-ai-chat-speech-to-text>\n }\n </div>\n </div>\n <div class=\"chat-action-bar d-flex a-i-center gap-4 bg-level-0\">\n <div class=\"d-flex a-i-center gap-4\">\n @if (moreActions().length > 0) {\n <div\n class=\"dropdown\"\n dropdown\n #moreChatActions=\"bs-dropdown\"\n [cdkTrapFocus]=\"moreChatActions.isOpen\"\n [dropup]=\"true\"\n >\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"'More actions' | translate\"\n [attr.aria-label]=\"'More actions' | translate\"\n aria-haspopup=\"true\"\n type=\"button\"\n dropdownToggle\n >\n <i [c8yIcon]=\"'ellipsis-h'\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropup\"\n role=\"menu\"\n *dropdownMenu\n >\n @for (action of moreActions(); track action) {\n <li>\n <ng-container *ngTemplateOutlet=\"action.template()\"></ng-container>\n </li>\n }\n </ul>\n </div>\n }\n @for (action of leftActions(); track action) {\n <ng-container *ngTemplateOutlet=\"action.template()\"></ng-container>\n }\n </div>\n <div class=\"d-flex a-i-center gap-4 m-l-auto\">\n @for (action of rightActions(); track action) {\n <ng-container *ngTemplateOutlet=\"action.template()\"></ng-container>\n }\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText || '' | translate\"\n [attr.aria-label]=\"config.sendButtonText || '' | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText || '' | translate\"\n [attr.aria-label]=\"config.cancelButtonText || '' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"d-flex p-t-8 p-l-16 p-r-16 p-b-8 gap-8\">\n @if (config.disclaimerText) {\n <div\n class=\"text-muted text-10\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n @if (cumulativeUsage) {\n <button\n class=\"btn-clean m-l-auto d-flex a-s-center\"\n [attr.aria-label]=\"\n 'Input tokens: {{ input }}\\nOutput tokens: {{ output }}'\n | translate\n : {\n input: cumulativeUsage?.inputTokens || 0 | c8yNumber: 'floor' : '1.0-0',\n output: cumulativeUsage?.outputTokens || 0 | c8yNumber: 'floor' : '1.0-0'\n }\n \"\n tabindex=\"0\"\n [tooltip]=\"\n 'Input tokens: {{ input }}\\nOutput tokens: {{ output }}'\n | translate\n : {\n input: cumulativeUsage?.inputTokens || 0 | c8yNumber: 'floor' : '1.0-0',\n output: cumulativeUsage?.outputTokens || 0 | c8yNumber: 'floor' : '1.0-0'\n }\n \"\n >\n <span class=\"tag tag--info a-s-center\">\n {{ 'Tokens used: {{total}}' | translate: { total: (cumulativeUsage?.totalTokens || 0)\n | c8yNumber : 'floor':'1.0-0' } }}\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3"],"mappings":"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"}
|