@c8y/ngx-components 1023.68.7 → 1023.70.0
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/ai/agent-chat/index.d.ts +235 -75
- package/ai/agent-chat/index.d.ts.map +1 -1
- package/ai/ai-chat/index.d.ts +176 -26
- package/ai/ai-chat/index.d.ts.map +1 -1
- package/ai/index.d.ts +309 -75
- package/ai/index.d.ts.map +1 -1
- package/asset-properties/index.d.ts.map +1 -1
- package/echart/index.d.ts +4 -0
- package/echart/index.d.ts.map +1 -1
- package/echart/models/index.d.ts +2 -0
- package/echart/models/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +680 -242
- package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +343 -44
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ai.mjs +187 -75
- package/fesm2022/c8y-ngx-components-ai.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-asset-properties.mjs +11 -5
- package/fesm2022/c8y-ngx-components-asset-properties.mjs.map +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-B2cy8gI7.mjs → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-CPLDClTp.mjs} +3 -3
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-B2cy8gI7.mjs.map → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-CPLDClTp.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-BYHnA-5R.mjs → c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-9be_iMQg.mjs} +30 -13
- package/fesm2022/c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-9be_iMQg.mjs.map +1 -0
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-C4oL39m8.mjs → c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-B2em01_W.mjs} +3 -3
- package/fesm2022/c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-B2em01_W.mjs.map +1 -0
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-event-count-config.component-DGwm6_C9.mjs → c8y-ngx-components-computed-asset-properties-event-count-config.component-CQuGa1RI.mjs} +3 -3
- package/fesm2022/c8y-ngx-components-computed-asset-properties-event-count-config.component-CQuGa1RI.mjs.map +1 -0
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-BxfCjbYY.mjs → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-CkmurxJv.mjs} +5 -5
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-BxfCjbYY.mjs.map → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-CkmurxJv.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CTK9zNUh.mjs +86 -0
- package/fesm2022/c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CTK9zNUh.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs +1 -1
- package/fesm2022/c8y-ngx-components-echart-models.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +39 -18
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +106 -4
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs +14 -122
- package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs.map +1 -1
- package/locales/locales.pot +83 -30
- package/package.json +1 -1
- package/widgets/implementations/html-widget/index.d.ts +11 -50
- package/widgets/implementations/html-widget/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-BYHnA-5R.mjs.map +0 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-C4oL39m8.mjs.map +0 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties-event-count-config.component-DGwm6_C9.mjs.map +0 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties-last-measurement-config.component-C1cuxN3L.mjs +0 -92
- package/fesm2022/c8y-ngx-components-computed-asset-properties-last-measurement-config.component-C1cuxN3L.mjs.map +0 -1
|
@@ -8,8 +8,10 @@ import { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';
|
|
|
8
8
|
import { map, combineLatest, from, first } from 'rxjs';
|
|
9
9
|
import { HTML_AGENT } from '@c8y/ngx-components/ai/agents/html';
|
|
10
10
|
|
|
11
|
+
// Treat as "production" when run from Jest
|
|
12
|
+
const mode = (typeof __MODE__ !== 'undefined' ? __MODE__ : 'production');
|
|
11
13
|
const HTML_WIDGET_AGENT_DEFINITIONS = {
|
|
12
|
-
snapshot:
|
|
14
|
+
snapshot: mode === 'development',
|
|
13
15
|
label: gettext('HTML Widget Code assistant'),
|
|
14
16
|
definition: HTML_AGENT
|
|
15
17
|
};
|
|
@@ -18,21 +20,28 @@ class AIHtmlWidgetConfigFactory {
|
|
|
18
20
|
constructor() {
|
|
19
21
|
this.betaPreviewService = inject(PreviewService);
|
|
20
22
|
this.aiService = inject(AIService);
|
|
23
|
+
/** The root injector (nb: components cannot be injected from here). */
|
|
21
24
|
this.injector = inject(Injector);
|
|
25
|
+
this.codeTag = 'c8y-code-extract';
|
|
26
|
+
this.codeToolName = 'c8y-html-widget-code';
|
|
27
|
+
this.queryToolName = 'cumulocity-api-request';
|
|
22
28
|
this.widgetConfigService = inject(WidgetConfigService);
|
|
23
29
|
this.aiWidgetConfigDefinition = {
|
|
24
30
|
widgetId: defaultWidgetIds.HTML,
|
|
25
31
|
label: gettext('AI Code Assistant'),
|
|
26
32
|
loadComponent: () => import('@c8y/ngx-components/ai/agent-chat').then(m => m.WidgetAiChatSectionComponent),
|
|
27
33
|
initialState: {
|
|
34
|
+
// configuration to pass to WidgetAiChatSectionComponent
|
|
28
35
|
agent: HTML_WIDGET_AGENT_DEFINITIONS,
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
chatConfig: {
|
|
37
|
+
title: gettext('I’m your AI Code Assistant, here to help you build powerful widgets for your dashboard.'),
|
|
38
|
+
welcomeText: gettext('Describe the widget you want or select one of the options below to get started.')
|
|
39
|
+
},
|
|
40
|
+
loadComponentConfig: this.loadWidgetAiChatComponentConfig.bind(this),
|
|
31
41
|
variables: this.widgetConfigService.currentConfig$.pipe(map((htmlWidgetConfig) => ({
|
|
32
42
|
currentHtmlWidgetCode: htmlWidgetConfig?.config?.code || '',
|
|
33
43
|
c8yContext: htmlWidgetConfig?.device || {}
|
|
34
44
|
}))),
|
|
35
|
-
loadRenderStepComponent: () => import('@c8y/ngx-components/widgets/implementations/html-widget').then(m => m.HtmlAiChatFeedbackComponent),
|
|
36
45
|
suggestions: [
|
|
37
46
|
{
|
|
38
47
|
label: gettext('Measurement widget'),
|
|
@@ -63,6 +72,99 @@ class AIHtmlWidgetConfigFactory {
|
|
|
63
72
|
return [];
|
|
64
73
|
}));
|
|
65
74
|
}
|
|
75
|
+
async loadWidgetAiChatComponentConfig(componentInjector) {
|
|
76
|
+
const { HtmlWidgetConfigService, HtmlAiChatToolDetailsComponent } = await import('@c8y/ngx-components/widgets/implementations/html-widget');
|
|
77
|
+
const htmlWidgetConfigService = componentInjector.get(HtmlWidgetConfigService);
|
|
78
|
+
return {
|
|
79
|
+
preprocessAgentMessage: (message, changed) => this.preprocessAgentMessage(message, changed, htmlWidgetConfigService),
|
|
80
|
+
assistantMessageDisplayConfig: {
|
|
81
|
+
toolDetailsComponent: toolCallPart => {
|
|
82
|
+
if (toolCallPart.toolName === this.codeToolName) {
|
|
83
|
+
return HtmlAiChatToolDetailsComponent;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
},
|
|
87
|
+
toolCallConfig: {
|
|
88
|
+
[this.queryToolName]: {
|
|
89
|
+
executingLabel: gettext('Analyzing query…'),
|
|
90
|
+
completedLabel: gettext('Query analyzed')
|
|
91
|
+
},
|
|
92
|
+
[this.codeToolName]: {
|
|
93
|
+
executingLabel: gettext('Creating widget…'),
|
|
94
|
+
completedLabel: gettext('Widget created')
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
// To match current behaviour and to help with development, for now we show the JSON for all tool calls
|
|
98
|
+
showDefaultToolDetails: 'all'
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
applyCurrentCode(code, htmlWidgetConfigService) {
|
|
103
|
+
const newConfig = {
|
|
104
|
+
code: code,
|
|
105
|
+
css: '',
|
|
106
|
+
devMode: true,
|
|
107
|
+
legacy: false,
|
|
108
|
+
options: { advancedSecurity: false, cssEncapsulation: false }
|
|
109
|
+
};
|
|
110
|
+
htmlWidgetConfigService.configChanged$.next(newConfig);
|
|
111
|
+
htmlWidgetConfigService.widgetConfigService.updateConfig({ config: newConfig });
|
|
112
|
+
}
|
|
113
|
+
preprocessAgentMessage(message, changedPart, htmlWidgetConfigService) {
|
|
114
|
+
// Rewrite HTML content generated by the agent in as text content as if it had come from a tool call
|
|
115
|
+
if (!message.steps?.length)
|
|
116
|
+
return message;
|
|
117
|
+
const step = message.steps[message.steps.length - 1];
|
|
118
|
+
const codeToolIndex = step.toolCalls?.findIndex(tc => tc.toolName === this.codeToolName);
|
|
119
|
+
const codeTool = step.toolCalls?.[codeToolIndex];
|
|
120
|
+
if (codeTool && codeTool.type !== 'tool-result') {
|
|
121
|
+
// A code update tool call is in progress - accumulate text into input
|
|
122
|
+
const input = `${codeTool.input?.code || ''}${step.text}`;
|
|
123
|
+
codeTool.input.code = input;
|
|
124
|
+
step.text = '';
|
|
125
|
+
const closeIdx = input.indexOf(`</${this.codeTag}>`);
|
|
126
|
+
if (closeIdx !== -1) {
|
|
127
|
+
// Found closing tag - convert to result and start new step
|
|
128
|
+
const beforeClose = input.substring(0, closeIdx);
|
|
129
|
+
const afterClose = input.substring(closeIdx + `</${this.codeTag}>`.length);
|
|
130
|
+
codeTool.input.code = beforeClose;
|
|
131
|
+
codeTool.type = 'tool-result';
|
|
132
|
+
// Move it from calls to results
|
|
133
|
+
step.toolCalls = [];
|
|
134
|
+
step.toolResults = [{ ...codeTool }];
|
|
135
|
+
// Always create a new (fake) step after this (just like a real AI), to keep any future text and code update calls separate from this one
|
|
136
|
+
message.steps.push({ type: 'text', text: afterClose });
|
|
137
|
+
// Since this is a fake tool call not a real one, the tool result callback won't trigger so do this manually
|
|
138
|
+
this.applyCurrentCode(codeTool.input.code, htmlWidgetConfigService);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Replace with a new instance so that change detections works
|
|
142
|
+
step.toolCalls[codeToolIndex] = { ...codeTool };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (step.text) {
|
|
146
|
+
// No in-progress code tag, so check for one
|
|
147
|
+
const openIdx = step.text.indexOf(`<${this.codeTag}>`);
|
|
148
|
+
if (openIdx !== -1) {
|
|
149
|
+
const afterOpen = step.text.substring(openIdx + `<${this.codeTag}>`.length);
|
|
150
|
+
step.text = step.text.substring(0, openIdx);
|
|
151
|
+
// Start a new "step" to keep it separate and simple
|
|
152
|
+
message.steps.push({
|
|
153
|
+
type: 'text',
|
|
154
|
+
text: '',
|
|
155
|
+
toolCalls: [
|
|
156
|
+
{
|
|
157
|
+
type: 'tool-input-streaming',
|
|
158
|
+
toolName: this.codeToolName,
|
|
159
|
+
toolCallId: this.codeToolName + message.steps.length, // add step number just to ensure uniqueness
|
|
160
|
+
input: { code: afterOpen }
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return message;
|
|
167
|
+
}
|
|
66
168
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AIHtmlWidgetConfigFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
67
169
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AIHtmlWidgetConfigFactory, providedIn: 'root' }); }
|
|
68
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs","sources":["../../widgets/definitions/html-widget-ai-config/html-widget-agent.definitions.ts","../../widgets/definitions/html-widget-ai-config/ai-html-widget-config.factory.ts","../../widgets/definitions/html-widget-ai-config/index.ts","../../widgets/definitions/html-widget-ai-config/c8y-ngx-components-widgets-definitions-html-widget-ai-config.ts"],"sourcesContent":["import type { ClientAgentDefinition } from '@c8y/ngx-components/ai';\nimport { HTML_AGENT } from '@c8y/ngx-components/ai/agents/html';\nimport { gettext } from '@c8y/ngx-components/gettext';\n\ndeclare const __MODE__: 'development' | 'production';\n\nexport const HTML_WIDGET_AGENT_DEFINITIONS: ClientAgentDefinition = {\n snapshot: __MODE__ === 'development',\n label: gettext('HTML Widget Code assistant'),\n definition: HTML_AGENT\n};\n","import { inject, Injectable, Injector } from '@angular/core';\nimport { ExtensionFactory, PreviewService } from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIService } from '@c8y/ngx-components/ai';\nimport type { WidgetAiChatSectionComponent } from '@c8y/ngx-components/ai/agent-chat';\nimport type { WidgetConfigSectionDefinition } from '@c8y/ngx-components/context-dashboard';\nimport { WidgetConfigService } from '@c8y/ngx-components/context-dashboard';\nimport { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';\nimport { combineLatest, first, from, map, Observable } from 'rxjs';\nimport { HTML_WIDGET_AGENT_DEFINITIONS } from './html-widget-agent.definitions';\nimport type { HtmlWidgetConfig } from '@c8y/ngx-components/widgets/implementations/html-widget';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AIHtmlWidgetConfigFactory implements ExtensionFactory<WidgetConfigSectionDefinition> {\n private readonly betaPreviewService = inject(PreviewService);\n private readonly aiService = inject(AIService);\n private readonly injector = inject(Injector);\n private readonly widgetConfigService = inject(WidgetConfigService);\n private readonly aiWidgetConfigDefinition: WidgetConfigSectionDefinition<WidgetAiChatSectionComponent> =\n {\n widgetId: defaultWidgetIds.HTML,\n label: gettext('AI Code Assistant'),\n loadComponent: () =>\n import('@c8y/ngx-components/ai/agent-chat').then(m => m.WidgetAiChatSectionComponent),\n initialState: {\n agent: HTML_WIDGET_AGENT_DEFINITIONS,\n title: gettext(\n 'I’m your AI Code Assistant, here to help you build powerful widgets for your dashboard.'\n ),\n welcomeText: gettext(\n 'Describe the widget you want or select one of the options below to get started.'\n ),\n\n variables: this.widgetConfigService.currentConfig$.pipe(\n map((htmlWidgetConfig: HtmlWidgetConfig) => ({\n currentHtmlWidgetCode: htmlWidgetConfig?.config?.code || '',\n c8yContext: htmlWidgetConfig?.device || {}\n }))\n ),\n\n loadRenderStepComponent: () =>\n import('@c8y/ngx-components/widgets/implementations/html-widget').then(\n m => m.HtmlAiChatFeedbackComponent\n ),\n\n suggestions: [\n {\n label: gettext('Measurement widget'),\n prompt: gettext('Create a widget that shows the current measurement of this device.')\n },\n {\n label: gettext('Device status widget'),\n prompt: gettext('Create a widget that shows the status of my devices.')\n },\n {\n label: gettext('Critical alarm widget'),\n prompt: gettext('Create a widget that shows all critical alarms.')\n }\n ]\n },\n priority: 100,\n injector: this.injector\n };\n\n get(): Observable<WidgetConfigSectionDefinition[]> {\n return combineLatest([\n from(this.aiService.getAgentHealth()),\n this.betaPreviewService.getState$('ui.html-widget.v2').pipe(first())\n ]).pipe(\n map(([aiHealthCheck, state]) => {\n if (state && aiHealthCheck.isProviderConfigured) {\n return [this.aiWidgetConfigDefinition];\n }\n return [];\n })\n );\n }\n}\n","import { hookWidgetConfig } from '@c8y/ngx-components/context-dashboard';\nimport { AIHtmlWidgetConfigFactory } from './ai-html-widget-config.factory';\n\nexport const htmlWidgetAIChatProviders = [hookWidgetConfig(AIHtmlWidgetConfigFactory)];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs","sources":["../../widgets/definitions/html-widget-ai-config/html-widget-agent.definitions.ts","../../widgets/definitions/html-widget-ai-config/ai-html-widget-config.factory.ts","../../widgets/definitions/html-widget-ai-config/index.ts","../../widgets/definitions/html-widget-ai-config/c8y-ngx-components-widgets-definitions-html-widget-ai-config.ts"],"sourcesContent":["import type { ClientAgentDefinition } from '@c8y/ngx-components/ai';\nimport { HTML_AGENT } from '@c8y/ngx-components/ai/agents/html';\nimport { gettext } from '@c8y/ngx-components/gettext';\n\ndeclare const __MODE__: 'development' | 'production' | undefined;\n\n// Treat as \"production\" when run from Jest\nconst mode = (typeof __MODE__ !== 'undefined' ? __MODE__ : 'production') as\n | 'development'\n | 'production';\n\nexport const HTML_WIDGET_AGENT_DEFINITIONS: ClientAgentDefinition = {\n snapshot: mode === 'development',\n label: gettext('HTML Widget Code assistant'),\n definition: HTML_AGENT\n};\n","import { inject, Injectable, Injector } from '@angular/core';\nimport { ExtensionFactory, PreviewService } from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport {\n AIMessage,\n AIService,\n AIStreamResponse,\n WidgetAiChatSectionComponentConfig,\n ToolCallPart\n} from '@c8y/ngx-components/ai';\nimport { WidgetAiChatSectionComponent } from '@c8y/ngx-components/ai/agent-chat';\nimport type { WidgetConfigSectionDefinition } from '@c8y/ngx-components/context-dashboard';\nimport { WidgetConfigService } from '@c8y/ngx-components/context-dashboard';\nimport { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';\nimport { combineLatest, first, from, map, Observable } from 'rxjs';\nimport { HTML_WIDGET_AGENT_DEFINITIONS } from './html-widget-agent.definitions';\nimport type {\n HtmlWidgetConfig,\n HtmlWidgetConfigService\n} from '@c8y/ngx-components/widgets/implementations/html-widget';\n\ntype CodeChangeToolCall = ToolCallPart<{ code: string }>;\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AIHtmlWidgetConfigFactory implements ExtensionFactory<WidgetConfigSectionDefinition> {\n private readonly betaPreviewService = inject(PreviewService);\n private readonly aiService = inject(AIService);\n /** The root injector (nb: components cannot be injected from here). */\n private readonly injector = inject(Injector);\n\n private readonly codeTag = 'c8y-code-extract';\n private readonly codeToolName = 'c8y-html-widget-code';\n private readonly queryToolName = 'cumulocity-api-request';\n private readonly widgetConfigService = inject(WidgetConfigService);\n\n private readonly aiWidgetConfigDefinition: WidgetConfigSectionDefinition<WidgetAiChatSectionComponent> =\n {\n widgetId: defaultWidgetIds.HTML,\n label: gettext('AI Code Assistant'),\n loadComponent: () =>\n import('@c8y/ngx-components/ai/agent-chat').then(m => m.WidgetAiChatSectionComponent),\n initialState: {\n // configuration to pass to WidgetAiChatSectionComponent\n agent: HTML_WIDGET_AGENT_DEFINITIONS,\n chatConfig: {\n title: gettext(\n 'I’m your AI Code Assistant, here to help you build powerful widgets for your dashboard.'\n ),\n welcomeText: gettext(\n 'Describe the widget you want or select one of the options below to get started.'\n )\n },\n\n loadComponentConfig: this.loadWidgetAiChatComponentConfig.bind(this),\n\n variables: this.widgetConfigService.currentConfig$.pipe(\n map((htmlWidgetConfig: HtmlWidgetConfig) => ({\n currentHtmlWidgetCode: htmlWidgetConfig?.config?.code || '',\n c8yContext: htmlWidgetConfig?.device || {}\n }))\n ),\n\n suggestions: [\n {\n label: gettext('Measurement widget'),\n prompt: gettext('Create a widget that shows the current measurement of this device.')\n },\n {\n label: gettext('Device status widget'),\n prompt: gettext('Create a widget that shows the status of my devices.')\n },\n {\n label: gettext('Critical alarm widget'),\n prompt: gettext('Create a widget that shows all critical alarms.')\n }\n ]\n },\n priority: 100,\n injector: this.injector\n };\n\n get(): Observable<WidgetConfigSectionDefinition[]> {\n return combineLatest([\n from(this.aiService.getAgentHealth()),\n this.betaPreviewService.getState$('ui.html-widget.v2').pipe(first())\n ]).pipe(\n map(([aiHealthCheck, state]) => {\n if (state && aiHealthCheck.isProviderConfigured) {\n return [this.aiWidgetConfigDefinition];\n }\n return [];\n })\n );\n }\n\n private async loadWidgetAiChatComponentConfig(\n componentInjector: Injector\n ): Promise<WidgetAiChatSectionComponentConfig> {\n const { HtmlWidgetConfigService, HtmlAiChatToolDetailsComponent } = await import(\n '@c8y/ngx-components/widgets/implementations/html-widget'\n );\n const htmlWidgetConfigService = componentInjector.get(HtmlWidgetConfigService);\n\n return {\n preprocessAgentMessage: (message, changed) =>\n this.preprocessAgentMessage(message, changed, htmlWidgetConfigService),\n\n assistantMessageDisplayConfig: {\n toolDetailsComponent: toolCallPart => {\n if (toolCallPart.toolName === this.codeToolName) {\n return HtmlAiChatToolDetailsComponent;\n }\n return undefined;\n },\n\n toolCallConfig: {\n [this.queryToolName]: {\n executingLabel: gettext('Analyzing query…'),\n completedLabel: gettext('Query analyzed')\n },\n [this.codeToolName]: {\n executingLabel: gettext('Creating widget…'),\n completedLabel: gettext('Widget created')\n }\n },\n // To match current behaviour and to help with development, for now we show the JSON for all tool calls\n showDefaultToolDetails: 'all'\n }\n };\n }\n\n private applyCurrentCode(code: string, htmlWidgetConfigService: HtmlWidgetConfigService) {\n const newConfig = {\n code: code,\n css: '',\n devMode: true,\n legacy: false,\n options: { advancedSecurity: false, cssEncapsulation: false }\n };\n htmlWidgetConfigService.configChanged$.next(newConfig);\n htmlWidgetConfigService.widgetConfigService.updateConfig({ config: newConfig });\n }\n\n protected preprocessAgentMessage(\n message: AIMessage,\n changedPart: AIStreamResponse['changedPart'],\n htmlWidgetConfigService: HtmlWidgetConfigService\n ): AIMessage {\n // Rewrite HTML content generated by the agent in as text content as if it had come from a tool call\n\n if (!message.steps?.length) return message;\n\n const step = message.steps[message.steps.length - 1];\n const codeToolIndex = step.toolCalls?.findIndex(tc => tc.toolName === this.codeToolName);\n const codeTool = step.toolCalls?.[codeToolIndex] as CodeChangeToolCall | undefined;\n\n if (codeTool && codeTool.type !== 'tool-result') {\n // A code update tool call is in progress - accumulate text into input\n const input = `${codeTool.input?.code || ''}${step.text}`;\n codeTool.input.code = input;\n step.text = '';\n\n const closeIdx = input.indexOf(`</${this.codeTag}>`);\n if (closeIdx !== -1) {\n // Found closing tag - convert to result and start new step\n const beforeClose = input.substring(0, closeIdx);\n const afterClose = input.substring(closeIdx + `</${this.codeTag}>`.length);\n\n codeTool.input.code = beforeClose;\n codeTool.type = 'tool-result';\n // Move it from calls to results\n step.toolCalls = [];\n step.toolResults = [{ ...codeTool }];\n\n // Always create a new (fake) step after this (just like a real AI), to keep any future text and code update calls separate from this one\n message.steps.push({ type: 'text', text: afterClose });\n\n // Since this is a fake tool call not a real one, the tool result callback won't trigger so do this manually\n this.applyCurrentCode(codeTool.input.code, htmlWidgetConfigService);\n } else {\n // Replace with a new instance so that change detections works\n step.toolCalls[codeToolIndex] = { ...codeTool };\n }\n } else if (step.text) {\n // No in-progress code tag, so check for one\n const openIdx = step.text.indexOf(`<${this.codeTag}>`);\n if (openIdx !== -1) {\n const afterOpen = step.text.substring(openIdx + `<${this.codeTag}>`.length);\n step.text = step.text.substring(0, openIdx);\n\n // Start a new \"step\" to keep it separate and simple\n message.steps.push({\n type: 'text',\n text: '',\n toolCalls: [\n {\n type: 'tool-input-streaming',\n toolName: this.codeToolName,\n toolCallId: this.codeToolName + message.steps.length, // add step number just to ensure uniqueness\n input: { code: afterOpen }\n } satisfies CodeChangeToolCall\n ]\n });\n }\n }\n\n return message;\n }\n}\n","import { hookWidgetConfig } from '@c8y/ngx-components/context-dashboard';\nimport { AIHtmlWidgetConfigFactory } from './ai-html-widget-config.factory';\n\nexport const htmlWidgetAIChatProviders = [hookWidgetConfig(AIHtmlWidgetConfigFactory)];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { NgIf, NgClass,
|
|
1
|
+
import { NgIf, NgClass, AsyncPipe } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, Input, Component, viewChild, SecurityContext, ViewChild } from '@angular/core';
|
|
3
|
+
import { inject, Injectable, Input, Component, input, computed, ChangeDetectionStrategy, viewChild, SecurityContext, ViewChild } from '@angular/core';
|
|
4
4
|
import * as i2 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
6
|
import { Router, RouterModule } from '@angular/router';
|
|
7
7
|
import { gettext } from '@c8y/ngx-components/gettext';
|
|
8
8
|
import * as i2$1 from '@c8y/ngx-components';
|
|
9
|
-
import { AppStateService, Permissions, IconDirective, C8yTranslatePipe,
|
|
9
|
+
import { AppStateService, Permissions, IconDirective, C8yTranslatePipe, TabsModule, LoadingComponent, OptionsService, ClipboardService } from '@c8y/ngx-components';
|
|
10
10
|
import { WidgetConfigService, WidgetConfigFeedbackComponent } from '@c8y/ngx-components/context-dashboard';
|
|
11
11
|
import * as i1 from 'ngx-bootstrap/popover';
|
|
12
12
|
import { PopoverModule } from 'ngx-bootstrap/popover';
|
|
@@ -304,114 +304,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
304
304
|
type: Input
|
|
305
305
|
}] } });
|
|
306
306
|
|
|
307
|
-
class
|
|
307
|
+
class HtmlAiChatToolDetailsComponent {
|
|
308
308
|
constructor() {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
this.loading = false;
|
|
313
|
-
/**
|
|
314
|
-
* Indicates whether the detailed feedback section is collapsed.
|
|
315
|
-
*/
|
|
316
|
-
this.collapsed = true;
|
|
317
|
-
/**
|
|
318
|
-
* Indicates whether the feedback section can be collapsed.
|
|
319
|
-
*/
|
|
320
|
-
this.canCollapse = false;
|
|
321
|
-
/**
|
|
322
|
-
* The code extracted from the agent step (if any).
|
|
323
|
-
*/
|
|
324
|
-
this.code = '';
|
|
325
|
-
/**
|
|
326
|
-
* The text before the code block (if any).
|
|
327
|
-
*/
|
|
328
|
-
this.textBeforeCode = '';
|
|
329
|
-
/**
|
|
330
|
-
* The text after the code block (if any).
|
|
331
|
-
*/
|
|
332
|
-
this.textAfterCode = '';
|
|
333
|
-
this.codeTag = 'c8y-code-extract';
|
|
309
|
+
this.tool = input.required(...(ngDevMode ? [{ debugName: "tool" }] : []));
|
|
310
|
+
this.code = computed(() => this.tool().input?.code || '', ...(ngDevMode ? [{ debugName: "code" }] : []));
|
|
311
|
+
this.isExecuting = computed(() => this.tool().type !== 'tool-result', ...(ngDevMode ? [{ debugName: "isExecuting" }] : []));
|
|
334
312
|
this.htmlWidgetConfigService = inject(HtmlWidgetConfigService);
|
|
335
313
|
}
|
|
336
|
-
/**
|
|
337
|
-
* @ignore
|
|
338
|
-
*/
|
|
339
|
-
ngOnInit() {
|
|
340
|
-
if (this.step) {
|
|
341
|
-
this.parseAgentStep(this.step);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* @ignore
|
|
346
|
-
*/
|
|
347
|
-
ngOnChanges(changes) {
|
|
348
|
-
if (changes.step) {
|
|
349
|
-
this.parseAgentStep(changes.step.currentValue);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Parse the agent step. Extracts the code block if present and updates the state accordingly.
|
|
354
|
-
* @param step The agent step to parse.
|
|
355
|
-
*/
|
|
356
|
-
parseAgentStep(step) {
|
|
357
|
-
if (step.aborted) {
|
|
358
|
-
queueMicrotask(() => {
|
|
359
|
-
this.loading = false;
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
if (step.reasoning) {
|
|
363
|
-
this.label = gettext('Reasoning');
|
|
364
|
-
this.loading = false;
|
|
365
|
-
this.canCollapse = true;
|
|
366
|
-
this.collapsed = false;
|
|
367
|
-
}
|
|
368
|
-
if (step.toolCalls?.length > 0 && !step.toolResults?.length) {
|
|
369
|
-
this.label = gettext('Analyzing query…');
|
|
370
|
-
this.loading = true;
|
|
371
|
-
this.canCollapse = false;
|
|
372
|
-
this.collapsed = true;
|
|
373
|
-
}
|
|
374
|
-
else if (step.toolResults?.length > 0) {
|
|
375
|
-
this.label = gettext('Query analyzed.');
|
|
376
|
-
this.loading = false;
|
|
377
|
-
this.canCollapse = true;
|
|
378
|
-
this.collapsed = true;
|
|
379
|
-
}
|
|
380
|
-
this.parseCodeBlock(step);
|
|
381
|
-
}
|
|
382
314
|
/**
|
|
383
315
|
* Revert to the last applied code.
|
|
384
316
|
*/
|
|
385
317
|
revert() {
|
|
386
318
|
this.applyCurrentCode();
|
|
387
319
|
}
|
|
388
|
-
parseCodeBlock(step) {
|
|
389
|
-
const text = step.text;
|
|
390
|
-
const codeBlockStart = text.lastIndexOf(`<${this.codeTag}>`);
|
|
391
|
-
const codeBlockEnd = text.lastIndexOf(`</${this.codeTag}>`);
|
|
392
|
-
const codeBlockStartLength = this.codeTag.length + 2;
|
|
393
|
-
const codeBlockEndLength = this.codeTag.length + 3;
|
|
394
|
-
if (codeBlockStart !== -1) {
|
|
395
|
-
this.code = text.substring(codeBlockStart + codeBlockStartLength);
|
|
396
|
-
this.textBeforeCode = text.substring(0, codeBlockStart + codeBlockStartLength);
|
|
397
|
-
this.label = gettext('Creating widget…');
|
|
398
|
-
this.loading = true;
|
|
399
|
-
this.canCollapse = true;
|
|
400
|
-
this.collapsed = true;
|
|
401
|
-
}
|
|
402
|
-
if (codeBlockEnd !== -1) {
|
|
403
|
-
this.label = gettext('Widget created');
|
|
404
|
-
this.code = text.substring(codeBlockStart + codeBlockStartLength, codeBlockEnd);
|
|
405
|
-
this.loading = false;
|
|
406
|
-
this.textAfterCode = text.substring(codeBlockEnd + codeBlockEndLength);
|
|
407
|
-
this.canCollapse = true;
|
|
408
|
-
this.collapsed = true;
|
|
409
|
-
this.applyCurrentCode();
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
320
|
applyCurrentCode() {
|
|
413
321
|
const newConfig = {
|
|
414
|
-
code: this.code,
|
|
322
|
+
code: this.code(),
|
|
415
323
|
css: '',
|
|
416
324
|
devMode: true,
|
|
417
325
|
legacy: false,
|
|
@@ -420,29 +328,13 @@ class HtmlAiChatFeedbackComponent {
|
|
|
420
328
|
this.htmlWidgetConfigService.configChanged$.next(newConfig);
|
|
421
329
|
this.htmlWidgetConfigService.widgetConfigService.updateConfig({ config: newConfig });
|
|
422
330
|
}
|
|
423
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type:
|
|
424
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type:
|
|
331
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlAiChatToolDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
332
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: HtmlAiChatToolDetailsComponent, isStandalone: true, selector: "c8y-html-ai-chat-tool-details", inputs: { tool: { classPropertyName: "tool", publicName: "tool", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<pre\n class=\"fit-w\"\n style=\"max-height: 320px\"\n >{{ code() }}</pre\n>\n@if (!isExecuting()) {\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Revert to this version' | translate\"\n [tooltip]=\"'Revert to this version' | translate\"\n container=\"body\"\n (click)=\"revert()\"\n >\n <i c8yIcon=\"undo\"></i>\n </button>\n}\n", dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
425
333
|
}
|
|
426
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type:
|
|
334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlAiChatToolDetailsComponent, decorators: [{
|
|
427
335
|
type: Component,
|
|
428
|
-
args: [{ selector: 'c8y-html-ai-chat-
|
|
429
|
-
|
|
430
|
-
ListItemComponent,
|
|
431
|
-
ListItemCollapseComponent,
|
|
432
|
-
ListItemBodyComponent,
|
|
433
|
-
ListItemIconComponent,
|
|
434
|
-
NgClass,
|
|
435
|
-
JsonPipe,
|
|
436
|
-
MarkdownToHtmlPipe,
|
|
437
|
-
TooltipDirective,
|
|
438
|
-
AsyncPipe,
|
|
439
|
-
C8yTranslatePipe,
|
|
440
|
-
IconDirective
|
|
441
|
-
], standalone: true, host: { class: 'agent-step-feedback' }, template: "@if (!step.reasoning && !code) {\n <div [innerHTML]=\"step.text | markdownToHtml | async\"></div>\n}\n@if (code) {\n <div [innerHTML]=\"textBeforeCode | 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 }}\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 (code) {\n <pre\n class=\"fit-w\"\n style=\"max-height: 320px\"\n >{{ code }}</pre\n >\n @if (!loading) {\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Revert to this version' | translate\"\n [tooltip]=\"'Revert to this version' | translate\"\n container=\"body\"\n (click)=\"revert()\"\n >\n <i c8yIcon=\"undo\"></i>\n </button>\n }\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\n@if (code) {\n <div [innerHTML]=\"textAfterCode | markdownToHtml | async\"></div>\n}\n" }]
|
|
442
|
-
}], propDecorators: { step: [{
|
|
443
|
-
type: Input,
|
|
444
|
-
args: [{ required: true }]
|
|
445
|
-
}] } });
|
|
336
|
+
args: [{ selector: 'c8y-html-ai-chat-tool-details', imports: [TooltipDirective, C8yTranslatePipe, IconDirective], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<pre\n class=\"fit-w\"\n style=\"max-height: 320px\"\n >{{ code() }}</pre\n>\n@if (!isExecuting()) {\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Revert to this version' | translate\"\n [tooltip]=\"'Revert to this version' | translate\"\n container=\"body\"\n (click)=\"revert()\"\n >\n <i c8yIcon=\"undo\"></i>\n </button>\n}\n" }]
|
|
337
|
+
}], propDecorators: { tool: [{ type: i0.Input, args: [{ isSignal: true, alias: "tool", required: true }] }] } });
|
|
446
338
|
|
|
447
339
|
class HtmlFrameComponent {
|
|
448
340
|
constructor() {
|
|
@@ -822,5 +714,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
822
714
|
* Generated bundle index. Do not edit.
|
|
823
715
|
*/
|
|
824
716
|
|
|
825
|
-
export { AdvancedSettingsComponent,
|
|
717
|
+
export { AdvancedSettingsComponent, HtmlAiChatToolDetailsComponent, HtmlFrameComponent, HtmlWidgetComponent, HtmlWidgetConfigComponent, HtmlWidgetConfigService, HtmlWidgetPropertiesSelectorComponent, INITIAL_CSS_FORMATTED, INITIAL_HTML_FORMATTED, WidgetCodeEditorComponent, defaultWebComponentAttributeNameContext, defaultWebComponentName, legacyTemplate, webComponentTemplate };
|
|
826
718
|
//# sourceMappingURL=c8y-ngx-components-widgets-implementations-html-widget.mjs.map
|