UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

388 lines (382 loc) 30.9 kB
import { NgClass, JsonPipe, AsyncPipe, NgComponentOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { Input, Component, EventEmitter, inject, Output } from '@angular/core'; import { ListGroupComponent, ListItemComponent, ListItemCollapseComponent, ListItemBodyComponent, ListItemIconComponent, MarkdownToHtmlPipe, C8yTranslatePipe, GainsightService, AlertService, LoadingComponent, EmptyStateComponent, ContextRouteService } from '@c8y/ngx-components'; import { AIService } from '@c8y/ngx-components/ai'; import { AiChatComponent, AiChatSuggestionComponent, AiChatMessageComponent, AiChatMessageActionComponent } from '@c8y/ngx-components/ai/ai-chat'; import { gettext } from '@c8y/ngx-components/gettext'; import { BehaviorSubject, map, of } from 'rxjs'; import { WidgetConfigService, WidgetConfigFeedbackComponent } from '@c8y/ngx-components/context-dashboard'; class AgentStepFeedbackComponent { constructor() { this.loading = false; this.collapsed = true; this.canCollapse = false; } ngOnInit() { if (this.step) { this.parseDefaultAgentStep(this.step); } } ngOnChanges(changes) { if (changes.step) { this.parseDefaultAgentStep(changes.step.currentValue); } } parseDefaultAgentStep(step) { if (step.reasoning) { this.label = gettext('Reasoning'); this.loading = false; this.canCollapse = true; this.collapsed = false; } if (step.toolCalls.length > 0 && !step.toolResults?.length) { this.label = gettext('Calling a tool'); this.loading = true; this.canCollapse = true; this.collapsed = true; } else if (step.toolResults?.length > 0) { this.label = gettext('Tool result'); this.loading = false; this.canCollapse = true; this.collapsed = true; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AgentStepFeedbackComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AgentStepFeedbackComponent, isStandalone: true, selector: "c8y-agent-step-feedback", inputs: { step: "step", label: "label", loading: "loading", collapsed: "collapsed", canCollapse: "canCollapse" }, host: { classAttribute: "agent-step-feedback" }, usesOnChanges: true, ngImport: i0, template: "@if (!step.reasoning) {\n <div [innerHTML]=\"step.text | markdownToHtml | async\"></div>\n}\n@if (label) {\n <c8y-list-group class=\"m-t-16 m-b-16\">\n <c8y-li\n [active]=\"!loading\"\n [collapsed]=\"collapsed\"\n >\n <c8y-li-icon>\n <span\n class=\"btn-ai btn-ai-hint btn-sm\"\n [ngClass]=\"{ working: loading }\"\n >\n <span></span>\n </span>\n </c8y-li-icon>\n <c8y-li-body>\n {{ label | translate }}\n </c8y-li-body>\n\n @if (canCollapse) {\n <c8y-li-collapse>\n @if (step.reasoning) {\n <div [innerHTML]=\"step.reasoning | markdownToHtml | async\"></div>\n } @else if (step) {\n <pre\n class=\"fit-w\"\n style=\"max-height: 320px\"\n >{{ step | json }}</pre\n >\n }\n </c8y-li-collapse>\n }\n </c8y-li>\n </c8y-list-group>\n}\n", dependencies: [{ kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AgentStepFeedbackComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-agent-step-feedback', standalone: true, imports: [ ListGroupComponent, ListItemComponent, ListItemCollapseComponent, ListItemBodyComponent, ListItemIconComponent, NgClass, JsonPipe, MarkdownToHtmlPipe, AsyncPipe, C8yTranslatePipe ], host: { class: 'agent-step-feedback' }, template: "@if (!step.reasoning) {\n <div [innerHTML]=\"step.text | markdownToHtml | async\"></div>\n}\n@if (label) {\n <c8y-list-group class=\"m-t-16 m-b-16\">\n <c8y-li\n [active]=\"!loading\"\n [collapsed]=\"collapsed\"\n >\n <c8y-li-icon>\n <span\n class=\"btn-ai btn-ai-hint btn-sm\"\n [ngClass]=\"{ working: loading }\"\n >\n <span></span>\n </span>\n </c8y-li-icon>\n <c8y-li-body>\n {{ label | translate }}\n </c8y-li-body>\n\n @if (canCollapse) {\n <c8y-li-collapse>\n @if (step.reasoning) {\n <div [innerHTML]=\"step.reasoning | markdownToHtml | async\"></div>\n } @else if (step) {\n <pre\n class=\"fit-w\"\n style=\"max-height: 320px\"\n >{{ step | json }}</pre\n >\n }\n </c8y-li-collapse>\n }\n </c8y-li>\n </c8y-list-group>\n}\n" }] }], propDecorators: { step: [{ type: Input, args: [{ required: true }] }], label: [{ type: Input }], loading: [{ type: Input }], collapsed: [{ type: Input }], canCollapse: [{ type: Input }] } }); class AgentChatComponent { constructor() { this.suggestions = []; this.headline = gettext('Welcome!'); this.autoInstallAgents = true; this.variables = {}; this.stepRenderComponent = AgentStepFeedbackComponent; this.onMessageDelta = new EventEmitter(); this.onMessageText = new EventEmitter(); this.onMessageFinish = new EventEmitter(); this.onToolResult = new EventEmitter(); this.isLoading = false; /** * A stream of AI messages representing the conversation. */ this.messages$ = new BehaviorSubject([]); this.hasError = true; this.canCreate = false; this.errorMsg = ''; this.prompt = ''; this.aiService = inject(AIService); this.gainsightService = inject(GainsightService); this.alertService = inject(AlertService); this.defaultAgentStepRendererPipe = (source) => { return source.pipe(map(steps => steps.map(step => { if (step.reasoning || step.toolCalls || step.toolResults) { return { content: this.stepRenderComponent, origin: { ...step } }; } return { content: step.text, origin: { ...step } }; }))); }; } async ngOnInit() { this.isLoading = true; this.agentName = typeof this.agent === 'string' ? this.agent : this.agent.definitions[0].name; try { const agentHealth = await this.aiService.getAgentHealth(this.agentName); this.composeErrorMessage(agentHealth); if (typeof this.agent !== 'string' && this.agent.snapshot) { this.createAgent(); } } catch (ex) { this.errorMsg = gettext('Microservice not found. Please contact your administrator.'); this.hasError = true; } this.isLoading = false; } async sendMessage(message) { this.messages$.next([...this.messages$.value, message]); this.isLoading = true; this.abortController = new AbortController(); const currentAssistantMessage = { role: 'assistant', content: '' }; this.messages$.next([...this.messages$.value, currentAssistantMessage]); const stream = await this.aiService.stream$(this.agentName, this.messages$.value.filter(m => m !== currentAssistantMessage), this.variables, this.abortController); if (this.assistantSubscription) { this.assistantSubscription.unsubscribe(); } this.assistantSubscription = stream.subscribe((messageFromAssistant) => this.processAgentMessage(currentAssistantMessage, messageFromAssistant, this.agentName, message)); } ngOnDestroy() { this.cancel(); } reprompt(userMessage) { const index = this.messages$.value.indexOf(userMessage); if (index > -1) { this.messages$.next(this.messages$.value.slice(0, index)); this.prompt = userMessage.content; } } rate(assistantMessage, positive) { const agentName = typeof this.agent === 'string' ? this.agent : this.agent.label; this.gainsightService.triggerEvent('ai.agent.feedback', { positive, assistant: assistantMessage, user: this.messages$.value[this.messages$.value.indexOf(assistantMessage) - 1], agent: agentName }); } reload(assistantMessage) { const index = this.messages$.value.indexOf(assistantMessage); const userMessage = this.messages$.value[index - 1]; if (index > -1) { this.messages$.next(this.messages$.value.slice(0, index - 1)); this.sendMessage({ role: 'user', content: userMessage.content, timestamp: new Date().toISOString() }); } } cancel() { if (this.abortController) { this.abortController.abort(); } if (this.assistantSubscription) { this.assistantSubscription.unsubscribe(); } this.isLoading = false; } async createAgent() { this.isLoading = true; try { await this.aiService.createOrUpdateAgent(this.agent); this.hasError = false; } catch (ex) { this.alertService.danger(gettext('Failed to create the agent.')); this.hasError = true; } this.isLoading = false; } composeErrorMessage(agentHealth) { if (agentHealth.exists) { this.errorMsg = ''; this.hasError = false; return; } this.hasError = true; if (!agentHealth.isProviderConfigured) { this.errorMsg = gettext('AI provider is not configured. Please contact your administrator.'); return; } if (agentHealth.canCreate && typeof this.agent === 'string') { this.errorMsg = gettext('The agent does not exist. Provide the agent definition in the agent manager to use it.'); return; } if (agentHealth.canCreate && typeof this.agent !== 'string') { this.canCreate = true; if (this.autoInstallAgents) { this.createAgent(); return; } this.errorMsg = gettext('The agent does not exist. You can create it now.'); return; } if (!agentHealth.canCreate) { this.errorMsg = gettext('The agent does not exist. Please contact your administrator.'); if (agentHealth.messages?.length) { this.errorMsg += '\n' + agentHealth.messages.join(' '); } return; } this.errorMsg = gettext('Unknown error. Please contact your administrator.'); } processAgentMessage(currentAssistantMessage, messageFromAssistant, agentName, message) { currentAssistantMessage.content = messageFromAssistant.content; const steps = messageFromAssistant.steps || []; const lastStep = steps.length ? steps[steps.length - 1] : null; this.onMessageDelta.emit(lastStep.textDelta); this.onMessageText.emit(lastStep.text); currentAssistantMessage.componentSteps$ = of(steps).pipe(this.defaultAgentStepRendererPipe); if (messageFromAssistant.finishReason === 'stop') { currentAssistantMessage.timestamp = new Date().toISOString(); this.onMessageFinish.emit(currentAssistantMessage.content); this.gainsightService.triggerEvent('ai.agent.message', { agent: agentName, user: message, assistant: currentAssistantMessage.content }); this.isLoading = false; } if (messageFromAssistant.finishReason === 'error') { currentAssistantMessage.timestamp = new Date().toISOString(); this.isLoading = false; } if (lastStep?.toolResults) { lastStep.toolResults.forEach(toolResult => { this.onToolResult.emit(toolResult); }); } // as we are mutating the currentAssistantMessage object // which is already in the messages array we need to emit a new array reference this.messages$.next([...this.messages$.value]); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AgentChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AgentChatComponent, isStandalone: true, selector: "c8y-agent-chat", inputs: { agent: "agent", suggestions: "suggestions", title: "title", headline: "headline", welcomeText: "welcomeText", autoInstallAgents: "autoInstallAgents", variables: "variables", stepRenderComponent: "stepRenderComponent" }, outputs: { onMessageDelta: "onMessageDelta", onMessageText: "onMessageText", onMessageFinish: "onMessageFinish", onToolResult: "onToolResult" }, ngImport: i0, template: "@if (hasError && isLoading) {\n <c8y-loading class=\"m-auto\"></c8y-loading>\n}\n@if (hasError && !isLoading) {\n <c8y-ui-empty-state\n class=\"m-auto\"\n [icon]=\"'disclaimer'\"\n [title]=\"'An error occurred' | translate\"\n [subtitle]=\"errorMsg | translate\"\n [horizontal]=\"true\"\n >\n @if (canCreate) {\n <div class=\"text-center m-t-16 m-b-16\">\n <button\n class=\"btn btn-primary\"\n (click)=\"createAgent()\"\n >\n {{ 'Create agent' | translate }}\n </button>\n </div>\n }\n </c8y-ui-empty-state>\n}\n\n@if (!hasError) {\n <c8y-ai-chat\n (onMessage)=\"sendMessage($event)\"\n [isLoading]=\"isLoading\"\n (onCancel)=\"cancel()\"\n [config]=\"{ title: title, headline: headline, welcomeText: welcomeText }\"\n [prompt]=\"prompt\"\n >\n @for (message of messages$ | async; track $index; let i = $index) {\n <c8y-ai-chat-message\n [message]=\"{ role: message.role, content: '', timestamp: message.timestamp }\"\n >\n @if (!message.componentSteps$) {\n <div [innerHTML]=\"message.content | markdownToHtml | async\"></div>\n }\n @for (step of message.componentSteps$ | async; track $index) {\n @if (typeof step.content === 'string') {\n <div [innerHTML]=\"step.content | markdownToHtml | async\"></div>\n } @else {\n <ng-container\n [ngComponentOutlet]=\"step.content\"\n [ngComponentOutletInputs]=\"{ step: step.origin }\"\n ></ng-container>\n }\n }\n\n @if (message.role === 'user') {\n <c8y-ai-chat-message-action\n icon=\"pencil\"\n [tooltip]=\"'Edit and resend this message' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"reprompt(message)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"thumbs-up\"\n [tooltip]=\"'This is useful' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"rate(message, true)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"thumbs-down\"\n [tooltip]=\"'This is not useful' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"rate(message, false)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"refresh\"\n [tooltip]=\"'Regenerate this response' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"reload(message)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (\n !message.content && message.role === 'assistant' && i === (messages$ | async)?.length - 1\n ) {\n <div class=\"text-center\">\n <c8y-loading></c8y-loading>\n </div>\n }\n </c8y-ai-chat-message>\n }\n\n @for (suggestion of suggestions; track $index) {\n <c8y-ai-chat-suggestion\n [icon]=\"suggestion.icon || 'c8y-bulb'\"\n [useAiButtons]=\"true\"\n [label]=\"suggestion.label\"\n [prompt]=\"suggestion.prompt\"\n (suggestionClicked)=\"sendMessage($event)\"\n [disabled]=\"isLoading\"\n ></c8y-ai-chat-suggestion>\n }\n </c8y-ai-chat>\n}\n", dependencies: [{ kind: "component", type: AiChatComponent, selector: "c8y-ai-chat", inputs: ["isLoading", "disabled", "prompt", "config"], outputs: ["onMessage", "onCancel"] }, { kind: "component", type: AiChatSuggestionComponent, selector: "c8y-ai-chat-suggestion", inputs: ["label", "prompt", "icon", "useAiButtons", "disabled"], outputs: ["suggestionClicked"] }, { kind: "component", type: AiChatMessageComponent, selector: "c8y-ai-chat-message", inputs: ["role", "message"] }, { kind: "component", type: AiChatMessageActionComponent, selector: "c8y-ai-chat-message-action", inputs: ["disabled", "tooltip", "icon"], outputs: ["click"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AgentChatComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-agent-chat', imports: [ AiChatComponent, AiChatSuggestionComponent, AiChatMessageComponent, AiChatMessageActionComponent, LoadingComponent, MarkdownToHtmlPipe, AsyncPipe, NgComponentOutlet, C8yTranslatePipe, EmptyStateComponent ], template: "@if (hasError && isLoading) {\n <c8y-loading class=\"m-auto\"></c8y-loading>\n}\n@if (hasError && !isLoading) {\n <c8y-ui-empty-state\n class=\"m-auto\"\n [icon]=\"'disclaimer'\"\n [title]=\"'An error occurred' | translate\"\n [subtitle]=\"errorMsg | translate\"\n [horizontal]=\"true\"\n >\n @if (canCreate) {\n <div class=\"text-center m-t-16 m-b-16\">\n <button\n class=\"btn btn-primary\"\n (click)=\"createAgent()\"\n >\n {{ 'Create agent' | translate }}\n </button>\n </div>\n }\n </c8y-ui-empty-state>\n}\n\n@if (!hasError) {\n <c8y-ai-chat\n (onMessage)=\"sendMessage($event)\"\n [isLoading]=\"isLoading\"\n (onCancel)=\"cancel()\"\n [config]=\"{ title: title, headline: headline, welcomeText: welcomeText }\"\n [prompt]=\"prompt\"\n >\n @for (message of messages$ | async; track $index; let i = $index) {\n <c8y-ai-chat-message\n [message]=\"{ role: message.role, content: '', timestamp: message.timestamp }\"\n >\n @if (!message.componentSteps$) {\n <div [innerHTML]=\"message.content | markdownToHtml | async\"></div>\n }\n @for (step of message.componentSteps$ | async; track $index) {\n @if (typeof step.content === 'string') {\n <div [innerHTML]=\"step.content | markdownToHtml | async\"></div>\n } @else {\n <ng-container\n [ngComponentOutlet]=\"step.content\"\n [ngComponentOutletInputs]=\"{ step: step.origin }\"\n ></ng-container>\n }\n }\n\n @if (message.role === 'user') {\n <c8y-ai-chat-message-action\n icon=\"pencil\"\n [tooltip]=\"'Edit and resend this message' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"reprompt(message)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"thumbs-up\"\n [tooltip]=\"'This is useful' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"rate(message, true)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"thumbs-down\"\n [tooltip]=\"'This is not useful' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"rate(message, false)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (message.role === 'assistant' && (i < (messages$ | async)?.length - 1 || !isLoading)) {\n <c8y-ai-chat-message-action\n icon=\"refresh\"\n [tooltip]=\"'Regenerate this response' | translate\"\n [disabled]=\"isLoading\"\n (click)=\"reload(message)\"\n ></c8y-ai-chat-message-action>\n }\n\n @if (\n !message.content && message.role === 'assistant' && i === (messages$ | async)?.length - 1\n ) {\n <div class=\"text-center\">\n <c8y-loading></c8y-loading>\n </div>\n }\n </c8y-ai-chat-message>\n }\n\n @for (suggestion of suggestions; track $index) {\n <c8y-ai-chat-suggestion\n [icon]=\"suggestion.icon || 'c8y-bulb'\"\n [useAiButtons]=\"true\"\n [label]=\"suggestion.label\"\n [prompt]=\"suggestion.prompt\"\n (suggestionClicked)=\"sendMessage($event)\"\n [disabled]=\"isLoading\"\n ></c8y-ai-chat-suggestion>\n }\n </c8y-ai-chat>\n}\n" }] }], propDecorators: { agent: [{ type: Input, args: [{ required: true }] }], suggestions: [{ type: Input }], title: [{ type: Input }], headline: [{ type: Input }], welcomeText: [{ type: Input }], autoInstallAgents: [{ type: Input }], variables: [{ type: Input }], stepRenderComponent: [{ type: Input }], onMessageDelta: [{ type: Output }], onMessageText: [{ type: Output }], onMessageFinish: [{ type: Output }], onToolResult: [{ type: Output }] } }); class WidgetAiChatSectionComponent { constructor() { this.suggestions = []; this.headline = gettext('Welcome!'); this.title = gettext('What can I help you with?'); this.useContextAsVariable = true; this.contextVariableName = 'c8yContext'; this.widgetConfigService = inject(WidgetConfigService); this.alertService = inject(AlertService); this.contextRouteService = inject(ContextRouteService); /** * A component that is used to render each step in the chat. By default, it uses the `AgentStepFeedbackComponent`. * You can provide your own component by returning it from this callback. * * @returns A promise that resolves to a component type. */ this.loadRenderStepComponent = () => Promise.resolve(AgentStepFeedbackComponent); /** * A callback that is invoked when a tool result is returned. The function can return either: * - `undefined` or `void`: No action is taken. * - an object which is stored to the widget configuration. */ this.onToolResult = () => undefined; } /** * @ignore */ async ngOnInit() { if (!this.variables && this.useContextAsVariable) { const { contextData } = this.contextRouteService.activatedContextData; this.variables = { [this.contextVariableName]: contextData || this.widgetConfigService.currentConfig.device }; } this._renderStepComponent = await this.loadRenderStepComponent(); } /** * Handles the tool result returned from the AI agent. * @param tool The tool result returned from the AI agent. */ toolResultHandler(tool) { try { const parsedResult = this.onToolResult(tool); if (!parsedResult) { return; } this.widgetConfigService.updateConfig({ config: { ...this.widgetConfigService.currentConfig, ...parsedResult } }, true); } catch (e) { this.alertService.danger(gettext('There was an error processing the AI response.')); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WidgetAiChatSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: WidgetAiChatSectionComponent, isStandalone: true, selector: "c8y-widget-ai-chat-section", inputs: { suggestions: "suggestions", agent: "agent", headline: "headline", title: "title", welcomeText: "welcomeText", variables: "variables", useContextAsVariable: "useContextAsVariable", contextVariableName: "contextVariableName", loadRenderStepComponent: "loadRenderStepComponent" }, ngImport: i0, template: "<c8y-widget-config-feedback>\n <div\n class=\"m-l-4 btn-ai btn-ai-hint btn-sm\"\n [title]=\"'AI code assistant' | translate\"\n >\n <span></span>\n </div>\n</c8y-widget-config-feedback>\n\n<c8y-agent-chat\n [title]=\"title | translate\"\n [headline]=\"headline | translate\"\n [welcomeText]=\"welcomeText | translate\"\n #agentChat\n [suggestions]=\"(agentChat.messages$ | async)?.length === 0 ? suggestions : []\"\n [agent]=\"agent\"\n [variables]=\"variables\"\n [stepRenderComponent]=\"_renderStepComponent\"\n (onToolResult)=\"toolResultHandler($event)\"\n></c8y-agent-chat>\n", dependencies: [{ kind: "component", type: AgentChatComponent, selector: "c8y-agent-chat", inputs: ["agent", "suggestions", "title", "headline", "welcomeText", "autoInstallAgents", "variables", "stepRenderComponent"], outputs: ["onMessageDelta", "onMessageText", "onMessageFinish", "onToolResult"] }, { kind: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WidgetAiChatSectionComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-widget-ai-chat-section', imports: [AgentChatComponent, C8yTranslatePipe, AsyncPipe, WidgetConfigFeedbackComponent], standalone: true, template: "<c8y-widget-config-feedback>\n <div\n class=\"m-l-4 btn-ai btn-ai-hint btn-sm\"\n [title]=\"'AI code assistant' | translate\"\n >\n <span></span>\n </div>\n</c8y-widget-config-feedback>\n\n<c8y-agent-chat\n [title]=\"title | translate\"\n [headline]=\"headline | translate\"\n [welcomeText]=\"welcomeText | translate\"\n #agentChat\n [suggestions]=\"(agentChat.messages$ | async)?.length === 0 ? suggestions : []\"\n [agent]=\"agent\"\n [variables]=\"variables\"\n [stepRenderComponent]=\"_renderStepComponent\"\n (onToolResult)=\"toolResultHandler($event)\"\n></c8y-agent-chat>\n" }] }], propDecorators: { suggestions: [{ type: Input }], agent: [{ type: Input }], headline: [{ type: Input }], title: [{ type: Input }], welcomeText: [{ type: Input }], variables: [{ type: Input }], useContextAsVariable: [{ type: Input }], contextVariableName: [{ type: Input }], loadRenderStepComponent: [{ type: Input }] } }); /** * Generated bundle index. Do not edit. */ export { AgentChatComponent, AgentStepFeedbackComponent, WidgetAiChatSectionComponent }; //# sourceMappingURL=c8y-ngx-components-ai-agent-chat.mjs.map