@meshmakers/shared-ui 3.4.1490 → 3.5.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/README.md +18 -0
- package/assets/octobot/lg/octo_blink.webp +0 -0
- package/assets/octobot/lg/octo_blink_still.png +0 -0
- package/assets/octobot/lg/octo_idle.webp +0 -0
- package/assets/octobot/lg/octo_idle_still.png +0 -0
- package/assets/octobot/lg/octo_look.webp +0 -0
- package/assets/octobot/lg/octo_look_still.png +0 -0
- package/assets/octobot/lg/octo_swim.webp +0 -0
- package/assets/octobot/lg/octo_swim_still.png +0 -0
- package/assets/octobot/lg/octo_thinking.webp +0 -0
- package/assets/octobot/lg/octo_thinking_still.png +0 -0
- package/assets/octobot/lg/octo_wave.webp +0 -0
- package/assets/octobot/lg/octo_wave_still.png +0 -0
- package/assets/octobot/md/octo_blink.webp +0 -0
- package/assets/octobot/md/octo_blink_still.png +0 -0
- package/assets/octobot/md/octo_idle.webp +0 -0
- package/assets/octobot/md/octo_idle_still.png +0 -0
- package/assets/octobot/md/octo_look.webp +0 -0
- package/assets/octobot/md/octo_look_still.png +0 -0
- package/assets/octobot/md/octo_swim.webp +0 -0
- package/assets/octobot/md/octo_swim_still.png +0 -0
- package/assets/octobot/md/octo_thinking.webp +0 -0
- package/assets/octobot/md/octo_thinking_still.png +0 -0
- package/assets/octobot/md/octo_wave.webp +0 -0
- package/assets/octobot/md/octo_wave_still.png +0 -0
- package/assets/octobot/sm/octo_blink.webp +0 -0
- package/assets/octobot/sm/octo_blink_still.png +0 -0
- package/assets/octobot/sm/octo_idle.webp +0 -0
- package/assets/octobot/sm/octo_idle_still.png +0 -0
- package/assets/octobot/sm/octo_look.webp +0 -0
- package/assets/octobot/sm/octo_look_still.png +0 -0
- package/assets/octobot/sm/octo_swim.webp +0 -0
- package/assets/octobot/sm/octo_swim_still.png +0 -0
- package/assets/octobot/sm/octo_thinking.webp +0 -0
- package/assets/octobot/sm/octo_thinking_still.png +0 -0
- package/assets/octobot/sm/octo_wave.webp +0 -0
- package/assets/octobot/sm/octo_wave_still.png +0 -0
- package/fesm2022/meshmakers-shared-ui-assistant-core.mjs +2 -0
- package/fesm2022/meshmakers-shared-ui-assistant-core.mjs.map +1 -1
- package/fesm2022/meshmakers-shared-ui-assistant.mjs +28 -5
- package/fesm2022/meshmakers-shared-ui-assistant.mjs.map +1 -1
- package/fesm2022/meshmakers-shared-ui.mjs +402 -21
- package/fesm2022/meshmakers-shared-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/meshmakers-shared-ui-assistant-core.d.ts +4 -0
- package/types/meshmakers-shared-ui-assistant.d.ts +11 -0
- package/types/meshmakers-shared-ui.d.ts +270 -6
|
@@ -6,6 +6,7 @@ import { Marked } from 'marked';
|
|
|
6
6
|
import { SVGIconComponent } from '@progress/kendo-angular-icons';
|
|
7
7
|
import { xIcon, paperclipIcon, plusIcon, clockArrowRotateIcon, trashIcon } from '@progress/kendo-svg-icons';
|
|
8
8
|
import { NgComponentOutlet } from '@angular/common';
|
|
9
|
+
import { OctoBotComponent } from '@meshmakers/shared-ui';
|
|
9
10
|
|
|
10
11
|
/** Protocols an assistant link may use; everything else (javascript:, data:, vbscript: …) renders as text. */
|
|
11
12
|
const SAFE_PROTOCOLS = new Set(['http:', 'https:', 'mailto:']);
|
|
@@ -283,6 +284,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
283
284
|
* A user turn sent through a slash command's `expand` (AB#5621) shows the expanded prompt with the
|
|
284
285
|
* typed command (`slashCommand`) as a small label above it.
|
|
285
286
|
*
|
|
287
|
+
* While an assistant turn streams it shows the OctoBot `thinking` with "Thinking…" (AB#3444);
|
|
288
|
+
* once the reply is complete the newest assistant turn keeps the OctoBot as a still frame. The
|
|
289
|
+
* figure is decorative — the text carries the meaning — and appears at most once in the thread.
|
|
290
|
+
*
|
|
286
291
|
* The list is an `aria-live` log; it is `aria-busy` while a turn streams so a
|
|
287
292
|
* screen reader announces finished messages instead of every token. Nothing
|
|
288
293
|
* inside it carries its own live role, so each addition is announced once.
|
|
@@ -297,6 +302,17 @@ class AssistantThreadComponent {
|
|
|
297
302
|
...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
|
|
298
303
|
m = assistantMessages(this.messages);
|
|
299
304
|
toolCallComponent = inject(ASSISTANT_TOOL_CALL_COMPONENT);
|
|
305
|
+
/** Id of the newest assistant turn: the only one that shows the resting OctoBot. */
|
|
306
|
+
lastAssistantId = computed(() => {
|
|
307
|
+
const items = this.items();
|
|
308
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
309
|
+
if (items[i].kind === 'assistant') {
|
|
310
|
+
return items[i].id;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}, /* @ts-ignore */
|
|
315
|
+
...(ngDevMode ? [{ debugName: "lastAssistantId" }] : /* istanbul ignore next */ []));
|
|
300
316
|
streaming = computed(() => this.items().some(item => item.kind === 'assistant' && item.streaming), /* @ts-ignore */
|
|
301
317
|
...(ngDevMode ? [{ debugName: "streaming" }] : /* istanbul ignore next */ []));
|
|
302
318
|
constructor() {
|
|
@@ -310,11 +326,11 @@ class AssistantThreadComponent {
|
|
|
310
326
|
});
|
|
311
327
|
}
|
|
312
328
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AssistantThreadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
313
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AssistantThreadComponent, isStandalone: true, selector: "mm-assistant-thread", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { proposalDecision: "proposalDecision" }, ngImport: i0, template: "<ol class=\"thread\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions text\" [attr.aria-label]=\"m().conversationLabel\"\n [attr.aria-busy]=\"streaming()\">\n @for (item of items(); track item.id) {\n @switch (item.kind) {\n @case ('user') {\n <li class=\"msg user\"><span class=\"sr-only\">{{ m().youPrefix }}</span>@if (item.slashCommand) {<span class=\"slash-command\"><span class=\"sr-only\">{{ m().slashCommandPrefix }}</span>{{ item.slashCommand }}</span>}{{ item.text }}@if (item.attachments?.length) {<ul class=\"attachments\" [attr.aria-label]=\"m().attachmentsLabel\">@for (file of item.attachments; track $index) {<li class=\"attachment\">{{ file.name }}</li>}</ul>}</li>\n }\n @case ('assistant') {\n <li class=\"msg bot\">\n <span class=\"sr-only\">{{ m().assistantPrefix }}</span>\n <div class=\"md\" [innerHTML]=\"item.markdown | assistantMarkdown\"></div>\n @if (item.streaming) {\n <span class=\"streaming\"
|
|
329
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AssistantThreadComponent, isStandalone: true, selector: "mm-assistant-thread", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { proposalDecision: "proposalDecision" }, ngImport: i0, template: "<ol class=\"thread\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions text\" [attr.aria-label]=\"m().conversationLabel\"\n [attr.aria-busy]=\"streaming()\">\n @for (item of items(); track item.id) {\n @switch (item.kind) {\n @case ('user') {\n <li class=\"msg user\"><span class=\"sr-only\">{{ m().youPrefix }}</span>@if (item.slashCommand) {<span class=\"slash-command\"><span class=\"sr-only\">{{ m().slashCommandPrefix }}</span>{{ item.slashCommand }}</span>}{{ item.text }}@if (item.attachments?.length) {<ul class=\"attachments\" [attr.aria-label]=\"m().attachmentsLabel\">@for (file of item.attachments; track $index) {<li class=\"attachment\">{{ file.name }}</li>}</ul>}</li>\n }\n @case ('assistant') {\n <li class=\"msg bot\">\n <span class=\"sr-only\">{{ m().assistantPrefix }}</span>\n <div class=\"md\" [innerHTML]=\"item.markdown | assistantMarkdown\"></div>\n @if (item.streaming) {\n <span class=\"streaming\" data-testid=\"assistant-thinking\">\n <mm-octobot animation=\"thinking\" size=\"sm\" />\n <span class=\"streaming-text\">{{ m().thinking }}</span>\n </span>\n } @else if (item.id === lastAssistantId()) {\n <mm-octobot class=\"settled\" animation=\"thinking\" size=\"sm\" still data-testid=\"assistant-settled\" />\n }\n </li>\n }\n @case ('tool-call') {\n <li class=\"msg tool\"><ng-container *ngComponentOutlet=\"toolCallComponent; inputs: { call: item.call }\"></ng-container></li>\n }\n @case ('proposal') {\n <li class=\"msg\">\n <mm-assistant-proposal-card\n [messages]=\"messages()\"\n [proposal]=\"item.proposal\"\n [decision]=\"item.decision\"\n (run)=\"proposalDecision.emit({ kind: 'run', proposal: $event })\"\n (edit)=\"proposalDecision.emit({ kind: 'edit', proposal: $event })\"\n (discard)=\"proposalDecision.emit({ kind: 'discard', proposal: $event })\">\n </mm-assistant-proposal-card>\n </li>\n }\n @case ('error') {\n <li class=\"msg error\"><span class=\"sr-only\">{{ m().errorPrefix }}</span>{{ item.text }}</li>\n }\n }\n }\n</ol>\n", styles: [":host{display:block;overflow:auto}.thread{display:grid;align-content:start;gap:var(--theme-space-3);margin:0;padding:14px;list-style:none}.msg{display:grid;gap:6px;min-width:0;overflow-wrap:anywhere}.user{justify-self:end;max-width:85%;padding:8px 12px;border-radius:var(--theme-radius-md);background:var(--theme-bg-overlay);white-space:pre-wrap}.slash-command{color:var(--theme-text-muted);font-family:var(--theme-font-mono, monospace);font-size:.71875rem;overflow-wrap:anywhere}.attachments{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0 0;padding:0;list-style:none;white-space:normal}.attachment{padding:0 6px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);color:var(--theme-text-secondary);font-size:.75rem}.bot{padding-left:12px;border-left:2px solid var(--theme-ai)}.bot ::ng-deep p{margin:0 0 var(--theme-space-2)}.bot ::ng-deep a{color:var(--theme-text-accent)}.streaming{display:inline-flex;align-items:center;gap:var(--theme-space-2);color:var(--theme-text-secondary);font-size:.8125rem}.settled{opacity:.85}.error{color:var(--theme-status-error)}mm-ai-tool-call{--mm-ai-tool-bg: var(--theme-bg-app);--mm-ai-tool-border: var(--theme-border-default);--mm-ai-tool-text: var(--theme-text-primary);--mm-ai-tool-muted: var(--theme-text-secondary);--mm-ai-tool-success: var(--theme-status-success);--mm-ai-tool-failed: var(--theme-status-error);--mm-ai-tool-rejected: var(--theme-status-warning);--mm-ai-tool-pending: var(--theme-status-neutral);--mm-ai-tool-code-bg: var(--theme-bg-sunken)}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AssistantProposalCardComponent, selector: "mm-assistant-proposal-card", inputs: ["proposal", "decision", "messages"], outputs: ["run", "edit", "discard"] }, { kind: "component", type: OctoBotComponent, selector: "mm-octobot", inputs: ["animation", "size", "label", "loading", "still", "playOnce"] }, { kind: "pipe", type: AssistantMarkdownPipe, name: "assistantMarkdown" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
314
330
|
}
|
|
315
331
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AssistantThreadComponent, decorators: [{
|
|
316
332
|
type: Component,
|
|
317
|
-
args: [{ selector: 'mm-assistant-thread', imports: [NgComponentOutlet, AssistantMarkdownPipe, AssistantProposalCardComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ol class=\"thread\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions text\" [attr.aria-label]=\"m().conversationLabel\"\n [attr.aria-busy]=\"streaming()\">\n @for (item of items(); track item.id) {\n @switch (item.kind) {\n @case ('user') {\n <li class=\"msg user\"><span class=\"sr-only\">{{ m().youPrefix }}</span>@if (item.slashCommand) {<span class=\"slash-command\"><span class=\"sr-only\">{{ m().slashCommandPrefix }}</span>{{ item.slashCommand }}</span>}{{ item.text }}@if (item.attachments?.length) {<ul class=\"attachments\" [attr.aria-label]=\"m().attachmentsLabel\">@for (file of item.attachments; track $index) {<li class=\"attachment\">{{ file.name }}</li>}</ul>}</li>\n }\n @case ('assistant') {\n <li class=\"msg bot\">\n <span class=\"sr-only\">{{ m().assistantPrefix }}</span>\n <div class=\"md\" [innerHTML]=\"item.markdown | assistantMarkdown\"></div>\n @if (item.streaming) {\n <span class=\"streaming\"
|
|
333
|
+
args: [{ selector: 'mm-assistant-thread', imports: [NgComponentOutlet, AssistantMarkdownPipe, AssistantProposalCardComponent, OctoBotComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ol class=\"thread\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions text\" [attr.aria-label]=\"m().conversationLabel\"\n [attr.aria-busy]=\"streaming()\">\n @for (item of items(); track item.id) {\n @switch (item.kind) {\n @case ('user') {\n <li class=\"msg user\"><span class=\"sr-only\">{{ m().youPrefix }}</span>@if (item.slashCommand) {<span class=\"slash-command\"><span class=\"sr-only\">{{ m().slashCommandPrefix }}</span>{{ item.slashCommand }}</span>}{{ item.text }}@if (item.attachments?.length) {<ul class=\"attachments\" [attr.aria-label]=\"m().attachmentsLabel\">@for (file of item.attachments; track $index) {<li class=\"attachment\">{{ file.name }}</li>}</ul>}</li>\n }\n @case ('assistant') {\n <li class=\"msg bot\">\n <span class=\"sr-only\">{{ m().assistantPrefix }}</span>\n <div class=\"md\" [innerHTML]=\"item.markdown | assistantMarkdown\"></div>\n @if (item.streaming) {\n <span class=\"streaming\" data-testid=\"assistant-thinking\">\n <mm-octobot animation=\"thinking\" size=\"sm\" />\n <span class=\"streaming-text\">{{ m().thinking }}</span>\n </span>\n } @else if (item.id === lastAssistantId()) {\n <mm-octobot class=\"settled\" animation=\"thinking\" size=\"sm\" still data-testid=\"assistant-settled\" />\n }\n </li>\n }\n @case ('tool-call') {\n <li class=\"msg tool\"><ng-container *ngComponentOutlet=\"toolCallComponent; inputs: { call: item.call }\"></ng-container></li>\n }\n @case ('proposal') {\n <li class=\"msg\">\n <mm-assistant-proposal-card\n [messages]=\"messages()\"\n [proposal]=\"item.proposal\"\n [decision]=\"item.decision\"\n (run)=\"proposalDecision.emit({ kind: 'run', proposal: $event })\"\n (edit)=\"proposalDecision.emit({ kind: 'edit', proposal: $event })\"\n (discard)=\"proposalDecision.emit({ kind: 'discard', proposal: $event })\">\n </mm-assistant-proposal-card>\n </li>\n }\n @case ('error') {\n <li class=\"msg error\"><span class=\"sr-only\">{{ m().errorPrefix }}</span>{{ item.text }}</li>\n }\n }\n }\n</ol>\n", styles: [":host{display:block;overflow:auto}.thread{display:grid;align-content:start;gap:var(--theme-space-3);margin:0;padding:14px;list-style:none}.msg{display:grid;gap:6px;min-width:0;overflow-wrap:anywhere}.user{justify-self:end;max-width:85%;padding:8px 12px;border-radius:var(--theme-radius-md);background:var(--theme-bg-overlay);white-space:pre-wrap}.slash-command{color:var(--theme-text-muted);font-family:var(--theme-font-mono, monospace);font-size:.71875rem;overflow-wrap:anywhere}.attachments{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0 0;padding:0;list-style:none;white-space:normal}.attachment{padding:0 6px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);color:var(--theme-text-secondary);font-size:.75rem}.bot{padding-left:12px;border-left:2px solid var(--theme-ai)}.bot ::ng-deep p{margin:0 0 var(--theme-space-2)}.bot ::ng-deep a{color:var(--theme-text-accent)}.streaming{display:inline-flex;align-items:center;gap:var(--theme-space-2);color:var(--theme-text-secondary);font-size:.8125rem}.settled{opacity:.85}.error{color:var(--theme-status-error)}mm-ai-tool-call{--mm-ai-tool-bg: var(--theme-bg-app);--mm-ai-tool-border: var(--theme-border-default);--mm-ai-tool-text: var(--theme-text-primary);--mm-ai-tool-muted: var(--theme-text-secondary);--mm-ai-tool-success: var(--theme-status-success);--mm-ai-tool-failed: var(--theme-status-error);--mm-ai-tool-rejected: var(--theme-status-warning);--mm-ai-tool-pending: var(--theme-status-neutral);--mm-ai-tool-code-bg: var(--theme-bg-sunken)}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}\n"] }]
|
|
318
334
|
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], proposalDecision: [{ type: i0.Output, args: ["proposalDecision"] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }] } });
|
|
319
335
|
|
|
320
336
|
/** Width of the panel before anyone resized it (CSS: 400 px, 340 px ≤ 1180 px), used until measured. */
|
|
@@ -478,6 +494,13 @@ class AssistantPanelComponent {
|
|
|
478
494
|
/** Session being opened or deleted (its buttons are disabled meanwhile). */
|
|
479
495
|
busySession = signal(null, /* @ts-ignore */
|
|
480
496
|
...(ngDevMode ? [{ debugName: "busySession" }] : /* istanbul ignore next */ []));
|
|
497
|
+
/**
|
|
498
|
+
* Greeting of an empty chat (AB#3444): the OctoBot waves once, then rests on its still frame.
|
|
499
|
+
* Not shown while the assistant is unavailable (the panel says so instead).
|
|
500
|
+
*/
|
|
501
|
+
showGreeting = computed(() => this.view() === 'chat' && this.assistant.thread().length === 0 && this.connected()
|
|
502
|
+
&& this.assistant.transportStatus() !== 'error', /* @ts-ignore */
|
|
503
|
+
...(ngDevMode ? [{ debugName: "showGreeting" }] : /* istanbul ignore next */ []));
|
|
481
504
|
/** Starter questions on an empty thread (transports with `starterQuestions` only). */
|
|
482
505
|
showStarters = computed(() => this.view() === 'chat' && this.assistant.thread().length === 0 && this.assistant.starterQuestions().length > 0, /* @ts-ignore */
|
|
483
506
|
...(ngDevMode ? [{ debugName: "showStarters" }] : /* istanbul ignore next */ []));
|
|
@@ -710,11 +733,11 @@ class AssistantPanelComponent {
|
|
|
710
733
|
this.assistant.decideProposal(decision.kind, decision.proposal);
|
|
711
734
|
}
|
|
712
735
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AssistantPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
713
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AssistantPanelComponent, isStandalone: true, selector: "mm-assistant-panel", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-labelledby": "assistant-panel-title", "id": "assistant-panel" }, listeners: { "keydown.escape": "onEscape($event)", "keydown.tab": "onTab($event)", "keydown.shift.tab": "onTab($event)" }, properties: { "attr.role": "isPhone() ? \"dialog\" : \"complementary\"", "attr.aria-modal": "isPhone() ? \"true\" : null", "class.mm-assistant-overlay": "overlay()", "class.mm-assistant-resizing": "resizing()", "attr.data-mode": "effectiveMode()", "style.width.px": "isPhone() ? null : appliedWidth()" } }, viewQueries: [{ propertyName: "composer", first: true, predicate: AssistantComposerComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (canResize()) {\n <div class=\"resize-handle\" role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\" aria-controls=\"assistant-panel\"\n [attr.aria-label]=\"m().resizePanel\" [title]=\"m().resizePanel\"\n [attr.aria-valuenow]=\"currentWidth()\" [attr.aria-valuemin]=\"effectiveMin()\" [attr.aria-valuemax]=\"effectiveMax()\"\n (pointerdown)=\"startResize($event)\" (keydown)=\"onResizeKey($event)\" (dblclick)=\"resetWidth()\"></div>\n}\n\n<header class=\"head\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <h2 class=\"title\" id=\"assistant-panel-title\">{{ m().title }}</h2>\n @if (connected()) {\n <span class=\"chip-neutral\" [title]=\"m().readsWithYourPermissions\">{{ m().readsWithYourPermissions }}</span>\n }\n @if (assistant.sessionsSupported) {\n <div class=\"head-actions\">\n <button type=\"button\" class=\"icon-btn new-chat\" [attr.aria-label]=\"m().newChat\" [title]=\"m().newChat\" (click)=\"newChat()\">\n <kendo-svg-icon [icon]=\"plusIcon\"></kendo-svg-icon>\n </button>\n <button type=\"button\" class=\"icon-btn sessions-toggle\" aria-controls=\"assistant-sessions\"\n [attr.aria-label]=\"m().sessions\" [title]=\"m().sessions\"\n [attr.aria-expanded]=\"view() === 'sessions'\"\n (click)=\"view() === 'sessions' ? backToChat() : showSessions()\">\n <kendo-svg-icon [icon]=\"historyIcon\"></kendo-svg-icon>\n </button>\n </div>\n }\n <button type=\"button\" class=\"icon-btn close\" [attr.aria-label]=\"m().closeAssistant\" [title]=\"m().closeAssistant\" (click)=\"assistant.close()\">\n <kendo-svg-icon [icon]=\"xIcon\"></kendo-svg-icon>\n </button>\n</header>\n\n@if (assistant.contextChips().length) {\n <ul class=\"ctx\" [attr.aria-label]=\"m().contextLabel\">\n @for (chip of assistant.contextChips(); track chip.id; let i = $index) {\n <li class=\"ctx-chip\" [attr.data-kind]=\"chip.kind\" [title]=\"chip.value\">\n <span class=\"ctx-label\">{{ chip.label }}</span>\n <button type=\"button\" [attr.aria-label]=\"format(m().removeContext, { label: chip.label })\" [title]=\"format(m().removeContext, { label: chip.label })\" (click)=\"removeChip(chip.id, i)\"><kendo-svg-icon [icon]=\"xIcon\" size=\"small\"></kendo-svg-icon></button>\n </li>\n }\n </ul>\n}\n\n@if (view() === 'sessions') {\n <section class=\"sessions\" id=\"assistant-sessions\" [attr.aria-label]=\"m().sessionsLabel\">\n <button type=\"button\" class=\"text-btn back\" (click)=\"backToChat()\">\u2190 {{ m().backToChat }}</button>\n <ul class=\"session-list\">\n @for (session of assistant.sessions(); track session.id) {\n <li class=\"session-row\" [attr.data-session-id]=\"session.id\"\n [class.active]=\"session.id === assistant.activeSessionId()\">\n @if (confirmingDelete() === session.id) {\n <div class=\"session-confirm\" role=\"group\" [attr.aria-label]=\"format(m().deleteSessionConfirm, { title: session.title })\">\n <span class=\"confirm-text\">{{ format(m().deleteSessionConfirm, { title: session.title }) }}</span>\n <button type=\"button\" class=\"text-btn danger confirm-delete\" [disabled]=\"busySession() === session.id\"\n (click)=\"confirmDelete(session)\">{{ m().delete }}</button>\n <button type=\"button\" class=\"text-btn cancel-delete\" (click)=\"cancelDelete()\">{{ m().cancel }}</button>\n </div>\n } @else {\n <button type=\"button\" class=\"session-open\" [title]=\"session.title\"\n [attr.aria-current]=\"session.id === assistant.activeSessionId() ? 'true' : null\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"openSession(session)\">\n <span class=\"session-title\">{{ session.title }}</span>\n @if (sessionDate(session); as date) {\n <span class=\"session-date\">{{ date }}</span>\n }\n </button>\n @if (assistant.sessionDeleteSupported) {\n <button type=\"button\" class=\"icon-btn session-delete\"\n [attr.aria-label]=\"format(m().deleteSession, { title: session.title })\"\n [title]=\"format(m().deleteSession, { title: session.title })\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"askDelete(session)\">\n <kendo-svg-icon [icon]=\"trashIcon\" size=\"small\"></kendo-svg-icon>\n </button>\n }\n }\n </li>\n } @empty {\n <li class=\"session-empty\">{{ m().noSessions }}</li>\n }\n </ul>\n </section>\n} @else {\n @if (showStarters()) {\n <section class=\"starters\" aria-labelledby=\"assistant-starters-title\">\n <h3 class=\"starters-title\" id=\"assistant-starters-title\">{{ m().startersTitle }}</h3>\n <ul class=\"starter-list\">\n @for (question of assistant.starterQuestions(); track $index) {\n <li><button type=\"button\" class=\"starter\" [disabled]=\"!assistant.canSend()\" (click)=\"sendStarter(question)\">{{ question }}</button></li>\n }\n </ul>\n </section>\n }\n\n <mm-assistant-thread class=\"thread\" [items]=\"assistant.thread()\" [messages]=\"messages()\" (proposalDecision)=\"onDecision($event)\"></mm-assistant-thread>\n\n @if (!connected() || assistant.transportStatus() === 'error') {\n <div class=\"unavailable\" role=\"status\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <p>{{ assistant.transportMessage() ?? m().notAvailable }}</p>\n </div>\n }\n\n <mm-assistant-composer\n [messages]=\"messages()\"\n [text]=\"assistant.draft()\"\n (textChange)=\"assistant.setDraft($event)\"\n [attachments]=\"assistant.attachments\"\n [files]=\"assistant.draftFiles()\"\n (filesChange)=\"assistant.setDraftFiles($event)\"\n [canSend]=\"assistant.canSend()\"\n [sending]=\"assistant.sending()\"\n (send)=\"assistant.send($event)\"\n (stop)=\"assistant.stop()\">\n </mm-assistant-composer>\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;width:400px;min-height:0;border-left:1px solid var(--theme-border-subtle);background:var(--theme-bg-surface);color:var(--theme-text-primary)}.head{display:flex;align-items:center;gap:var(--theme-space-2);padding:10px 14px;border-bottom:1px solid var(--theme-border-subtle)}.title{flex:none;margin:0;white-space:nowrap;font-family:var(--theme-font-display);font-size:.8125rem;font-weight:600}.sparkle{color:var(--theme-ai)}.chip-neutral{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:6px;padding:0 7px;border-radius:var(--theme-radius-xs);background:var(--theme-status-neutral-subtle);color:var(--theme-text-secondary);font-size:.71875rem}.icon-btn{flex:none;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);cursor:pointer}.icon-btn:hover{background:var(--theme-bg-hover)}.icon-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.icon-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.close{margin-left:auto}.ctx{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:8px 14px;list-style:none;border-bottom:1px solid var(--theme-border-subtle)}.ctx-chip{display:inline-flex;align-items:center;gap:6px;max-width:100%;height:22px;padding:0 4px 0 8px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);font-size:.75rem;color:var(--theme-text-secondary)}.ctx-chip button{display:inline-grid;flex:none;place-items:center;border:0;padding:0 2px;background:none;color:var(--theme-text-muted);cursor:pointer}.ctx-chip button:hover{color:var(--theme-text-primary)}.ctx-chip button:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.ctx-label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.thread{flex:1 1 auto;min-height:0}.unavailable{display:flex;align-items:center;gap:var(--theme-space-2);margin:0 14px var(--theme-space-2);padding:8px 10px;border:1px dashed var(--theme-border-default);border-radius:var(--theme-radius-sm);color:var(--theme-text-secondary)}.unavailable p{margin:0}@media(max-width:1180px){:host{width:340px}}@media(max-width:640px){:host{position:fixed;inset:48px 0 0;z-index:30;width:auto;border-left:0}}.head-actions{display:flex;flex:none;gap:2px;margin-left:auto}.head-actions+.close{margin-left:0}.text-btn{height:26px;padding:0 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);font:inherit;font-size:.75rem;cursor:pointer}.text-btn:hover:not(:disabled){background:var(--theme-bg-hover);color:var(--theme-text-primary)}.text-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.text-btn:disabled{color:var(--theme-text-muted);cursor:default}.text-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.text-btn.danger{color:var(--theme-status-error)}.sessions{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--theme-space-2);min-height:0;padding:10px 14px;overflow:auto}.sessions .back{align-self:flex-start}.session-list{display:grid;gap:2px;margin:0;padding:0;list-style:none}.session-row{display:flex;align-items:center;gap:4px;border-radius:var(--theme-radius-sm)}.session-row.active{background:var(--theme-accent-subtle)}.session-open{display:grid;flex:1 1 auto;min-width:0;padding:6px 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.session-open:hover:not(:disabled){background:var(--theme-bg-hover)}.session-open:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.session-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.session-date{color:var(--theme-text-muted);font-size:.71875rem}.session-confirm{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:4px;padding:4px 8px}.confirm-text{flex:1 1 100%;overflow-wrap:anywhere}.session-empty{padding:6px 8px;color:var(--theme-text-secondary)}.starters{display:grid;gap:var(--theme-space-2);padding:14px 14px 0}.starters-title{margin:0;color:var(--theme-text-secondary);font-size:.75rem;font-weight:600}.starter-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.starter{width:100%;padding:6px 10px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.starter:hover:not(:disabled){border-color:var(--theme-ai);background:var(--theme-bg-hover)}.starter:disabled{color:var(--theme-text-muted);cursor:default}.starter:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.resize-handle{position:absolute;top:0;bottom:0;left:-3px;z-index:1;width:6px;cursor:col-resize;touch-action:none}.resize-handle:after{content:\"\";position:absolute;top:0;bottom:0;left:2px;width:2px;background:transparent;transition:background-color .15s}.resize-handle:hover:after,.resize-handle:focus-visible:after{background:var(--theme-accent)}.resize-handle:focus-visible{outline:none}:host(.mm-assistant-resizing){-webkit-user-select:none;user-select:none;cursor:col-resize}:host(.mm-assistant-resizing) .resize-handle:after{background:var(--theme-accent)}@media(prefers-reduced-motion:reduce){.resize-handle:after{transition:none}}:host(.mm-assistant-overlay){position:fixed;top:var(--mm-assistant-overlay-top, 48px);right:0;bottom:0;z-index:var(--mm-assistant-overlay-z-index, 20);box-shadow:var(--theme-shadow-panel)}\n"], dependencies: [{ kind: "component", type: AssistantThreadComponent, selector: "mm-assistant-thread", inputs: ["items", "messages"], outputs: ["proposalDecision"] }, { kind: "component", type: AssistantComposerComponent, selector: "mm-assistant-composer", inputs: ["text", "canSend", "sending", "attachments", "files", "messages"], outputs: ["textChange", "filesChange", "send", "stop"] }, { kind: "component", type: SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
736
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AssistantPanelComponent, isStandalone: true, selector: "mm-assistant-panel", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-labelledby": "assistant-panel-title", "id": "assistant-panel" }, listeners: { "keydown.escape": "onEscape($event)", "keydown.tab": "onTab($event)", "keydown.shift.tab": "onTab($event)" }, properties: { "attr.role": "isPhone() ? \"dialog\" : \"complementary\"", "attr.aria-modal": "isPhone() ? \"true\" : null", "class.mm-assistant-overlay": "overlay()", "class.mm-assistant-resizing": "resizing()", "attr.data-mode": "effectiveMode()", "style.width.px": "isPhone() ? null : appliedWidth()" } }, viewQueries: [{ propertyName: "composer", first: true, predicate: AssistantComposerComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (canResize()) {\n <div class=\"resize-handle\" role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\" aria-controls=\"assistant-panel\"\n [attr.aria-label]=\"m().resizePanel\" [title]=\"m().resizePanel\"\n [attr.aria-valuenow]=\"currentWidth()\" [attr.aria-valuemin]=\"effectiveMin()\" [attr.aria-valuemax]=\"effectiveMax()\"\n (pointerdown)=\"startResize($event)\" (keydown)=\"onResizeKey($event)\" (dblclick)=\"resetWidth()\"></div>\n}\n\n<header class=\"head\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <h2 class=\"title\" id=\"assistant-panel-title\">{{ m().title }}</h2>\n @if (connected()) {\n <span class=\"chip-neutral\" [title]=\"m().readsWithYourPermissions\">{{ m().readsWithYourPermissions }}</span>\n }\n @if (assistant.sessionsSupported) {\n <div class=\"head-actions\">\n <button type=\"button\" class=\"icon-btn new-chat\" [attr.aria-label]=\"m().newChat\" [title]=\"m().newChat\" (click)=\"newChat()\">\n <kendo-svg-icon [icon]=\"plusIcon\"></kendo-svg-icon>\n </button>\n <button type=\"button\" class=\"icon-btn sessions-toggle\" aria-controls=\"assistant-sessions\"\n [attr.aria-label]=\"m().sessions\" [title]=\"m().sessions\"\n [attr.aria-expanded]=\"view() === 'sessions'\"\n (click)=\"view() === 'sessions' ? backToChat() : showSessions()\">\n <kendo-svg-icon [icon]=\"historyIcon\"></kendo-svg-icon>\n </button>\n </div>\n }\n <button type=\"button\" class=\"icon-btn close\" [attr.aria-label]=\"m().closeAssistant\" [title]=\"m().closeAssistant\" (click)=\"assistant.close()\">\n <kendo-svg-icon [icon]=\"xIcon\"></kendo-svg-icon>\n </button>\n</header>\n\n@if (assistant.contextChips().length) {\n <ul class=\"ctx\" [attr.aria-label]=\"m().contextLabel\">\n @for (chip of assistant.contextChips(); track chip.id; let i = $index) {\n <li class=\"ctx-chip\" [attr.data-kind]=\"chip.kind\" [title]=\"chip.value\">\n <span class=\"ctx-label\">{{ chip.label }}</span>\n <button type=\"button\" [attr.aria-label]=\"format(m().removeContext, { label: chip.label })\" [title]=\"format(m().removeContext, { label: chip.label })\" (click)=\"removeChip(chip.id, i)\"><kendo-svg-icon [icon]=\"xIcon\" size=\"small\"></kendo-svg-icon></button>\n </li>\n }\n </ul>\n}\n\n@if (view() === 'sessions') {\n <section class=\"sessions\" id=\"assistant-sessions\" [attr.aria-label]=\"m().sessionsLabel\">\n <button type=\"button\" class=\"text-btn back\" (click)=\"backToChat()\">\u2190 {{ m().backToChat }}</button>\n <ul class=\"session-list\">\n @for (session of assistant.sessions(); track session.id) {\n <li class=\"session-row\" [attr.data-session-id]=\"session.id\"\n [class.active]=\"session.id === assistant.activeSessionId()\">\n @if (confirmingDelete() === session.id) {\n <div class=\"session-confirm\" role=\"group\" [attr.aria-label]=\"format(m().deleteSessionConfirm, { title: session.title })\">\n <span class=\"confirm-text\">{{ format(m().deleteSessionConfirm, { title: session.title }) }}</span>\n <button type=\"button\" class=\"text-btn danger confirm-delete\" [disabled]=\"busySession() === session.id\"\n (click)=\"confirmDelete(session)\">{{ m().delete }}</button>\n <button type=\"button\" class=\"text-btn cancel-delete\" (click)=\"cancelDelete()\">{{ m().cancel }}</button>\n </div>\n } @else {\n <button type=\"button\" class=\"session-open\" [title]=\"session.title\"\n [attr.aria-current]=\"session.id === assistant.activeSessionId() ? 'true' : null\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"openSession(session)\">\n <span class=\"session-title\">{{ session.title }}</span>\n @if (sessionDate(session); as date) {\n <span class=\"session-date\">{{ date }}</span>\n }\n </button>\n @if (assistant.sessionDeleteSupported) {\n <button type=\"button\" class=\"icon-btn session-delete\"\n [attr.aria-label]=\"format(m().deleteSession, { title: session.title })\"\n [title]=\"format(m().deleteSession, { title: session.title })\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"askDelete(session)\">\n <kendo-svg-icon [icon]=\"trashIcon\" size=\"small\"></kendo-svg-icon>\n </button>\n }\n }\n </li>\n } @empty {\n <li class=\"session-empty\">{{ m().noSessions }}</li>\n }\n </ul>\n </section>\n} @else {\n @if (showGreeting()) {\n <div class=\"greeting\" data-testid=\"assistant-greeting\">\n <mm-octobot animation=\"wave\" size=\"md\" playOnce />\n <p class=\"greeting-text\">{{ m().greeting }}</p>\n </div>\n }\n @if (showStarters()) {\n <section class=\"starters\" aria-labelledby=\"assistant-starters-title\">\n <h3 class=\"starters-title\" id=\"assistant-starters-title\">{{ m().startersTitle }}</h3>\n <ul class=\"starter-list\">\n @for (question of assistant.starterQuestions(); track $index) {\n <li><button type=\"button\" class=\"starter\" [disabled]=\"!assistant.canSend()\" (click)=\"sendStarter(question)\">{{ question }}</button></li>\n }\n </ul>\n </section>\n }\n\n <mm-assistant-thread class=\"thread\" [items]=\"assistant.thread()\" [messages]=\"messages()\" (proposalDecision)=\"onDecision($event)\"></mm-assistant-thread>\n\n @if (!connected() || assistant.transportStatus() === 'error') {\n <div class=\"unavailable\" role=\"status\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <p>{{ assistant.transportMessage() ?? m().notAvailable }}</p>\n </div>\n }\n\n <mm-assistant-composer\n [messages]=\"messages()\"\n [text]=\"assistant.draft()\"\n (textChange)=\"assistant.setDraft($event)\"\n [attachments]=\"assistant.attachments\"\n [files]=\"assistant.draftFiles()\"\n (filesChange)=\"assistant.setDraftFiles($event)\"\n [canSend]=\"assistant.canSend()\"\n [sending]=\"assistant.sending()\"\n (send)=\"assistant.send($event)\"\n (stop)=\"assistant.stop()\">\n </mm-assistant-composer>\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;width:400px;min-height:0;border-left:1px solid var(--theme-border-subtle);background:var(--theme-bg-surface);color:var(--theme-text-primary)}.head{display:flex;align-items:center;gap:var(--theme-space-2);padding:10px 14px;border-bottom:1px solid var(--theme-border-subtle)}.title{flex:none;margin:0;white-space:nowrap;font-family:var(--theme-font-display);font-size:.8125rem;font-weight:600}.sparkle{color:var(--theme-ai)}.chip-neutral{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:6px;padding:0 7px;border-radius:var(--theme-radius-xs);background:var(--theme-status-neutral-subtle);color:var(--theme-text-secondary);font-size:.71875rem}.icon-btn{flex:none;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);cursor:pointer}.icon-btn:hover{background:var(--theme-bg-hover)}.icon-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.icon-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.close{margin-left:auto}.ctx{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:8px 14px;list-style:none;border-bottom:1px solid var(--theme-border-subtle)}.ctx-chip{display:inline-flex;align-items:center;gap:6px;max-width:100%;height:22px;padding:0 4px 0 8px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);font-size:.75rem;color:var(--theme-text-secondary)}.ctx-chip button{display:inline-grid;flex:none;place-items:center;border:0;padding:0 2px;background:none;color:var(--theme-text-muted);cursor:pointer}.ctx-chip button:hover{color:var(--theme-text-primary)}.ctx-chip button:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.ctx-label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.thread{flex:1 1 auto;min-height:0}.unavailable{display:flex;align-items:center;gap:var(--theme-space-2);margin:0 14px var(--theme-space-2);padding:8px 10px;border:1px dashed var(--theme-border-default);border-radius:var(--theme-radius-sm);color:var(--theme-text-secondary)}.unavailable p{margin:0}@media(max-width:1180px){:host{width:340px}}@media(max-width:640px){:host{position:fixed;inset:48px 0 0;z-index:30;width:auto;border-left:0}}.head-actions{display:flex;flex:none;gap:2px;margin-left:auto}.head-actions+.close{margin-left:0}.text-btn{height:26px;padding:0 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);font:inherit;font-size:.75rem;cursor:pointer}.text-btn:hover:not(:disabled){background:var(--theme-bg-hover);color:var(--theme-text-primary)}.text-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.text-btn:disabled{color:var(--theme-text-muted);cursor:default}.text-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.text-btn.danger{color:var(--theme-status-error)}.sessions{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--theme-space-2);min-height:0;padding:10px 14px;overflow:auto}.sessions .back{align-self:flex-start}.session-list{display:grid;gap:2px;margin:0;padding:0;list-style:none}.session-row{display:flex;align-items:center;gap:4px;border-radius:var(--theme-radius-sm)}.session-row.active{background:var(--theme-accent-subtle)}.session-open{display:grid;flex:1 1 auto;min-width:0;padding:6px 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.session-open:hover:not(:disabled){background:var(--theme-bg-hover)}.session-open:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.session-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.session-date{color:var(--theme-text-muted);font-size:.71875rem}.session-confirm{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:4px;padding:4px 8px}.confirm-text{flex:1 1 100%;overflow-wrap:anywhere}.session-empty{padding:6px 8px;color:var(--theme-text-secondary)}.greeting{display:grid;justify-items:center;gap:var(--theme-space-2);padding:20px 14px 0;text-align:center}.greeting-text{margin:0;color:var(--theme-text-primary);font-weight:600}.starters{display:grid;gap:var(--theme-space-2);padding:14px 14px 0}.starters-title{margin:0;color:var(--theme-text-secondary);font-size:.75rem;font-weight:600}.starter-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.starter{width:100%;padding:6px 10px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.starter:hover:not(:disabled){border-color:var(--theme-ai);background:var(--theme-bg-hover)}.starter:disabled{color:var(--theme-text-muted);cursor:default}.starter:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.resize-handle{--mm-resize-line: transparent;--mm-resize-grip: var(--theme-border-default, var(--theme-border-subtle, rgba(128, 128, 128, .5)));position:absolute;top:0;bottom:0;left:-4px;z-index:1;width:8px;cursor:col-resize;touch-action:none}.resize-handle:after{content:\"\";position:absolute;top:0;bottom:0;left:3px;width:2px;background:var(--mm-resize-line);transition:background-color .15s}.resize-handle:before{content:\"\";position:absolute;top:50%;left:2px;z-index:1;width:4px;height:32px;margin-top:-16px;border-radius:2px;background:var(--mm-resize-grip);transition:background-color .15s}.resize-handle:hover,.resize-handle:focus-visible{--mm-resize-line: var(--theme-accent);--mm-resize-grip: var(--theme-accent)}.resize-handle:focus-visible{outline:none}:host(.mm-assistant-resizing){-webkit-user-select:none;user-select:none;cursor:col-resize}:host(.mm-assistant-resizing) .resize-handle{--mm-resize-line: var(--theme-accent);--mm-resize-grip: var(--theme-accent)}@media(prefers-reduced-motion:reduce){.resize-handle:after,.resize-handle:before{transition:none}}:host(.mm-assistant-overlay){position:fixed;top:var(--mm-assistant-overlay-top, 48px);right:0;bottom:0;z-index:var(--mm-assistant-overlay-z-index, 20);box-shadow:var(--theme-shadow-panel)}\n"], dependencies: [{ kind: "component", type: AssistantThreadComponent, selector: "mm-assistant-thread", inputs: ["items", "messages"], outputs: ["proposalDecision"] }, { kind: "component", type: AssistantComposerComponent, selector: "mm-assistant-composer", inputs: ["text", "canSend", "sending", "attachments", "files", "messages"], outputs: ["textChange", "filesChange", "send", "stop"] }, { kind: "component", type: SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: OctoBotComponent, selector: "mm-octobot", inputs: ["animation", "size", "label", "loading", "still", "playOnce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
714
737
|
}
|
|
715
738
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AssistantPanelComponent, decorators: [{
|
|
716
739
|
type: Component,
|
|
717
|
-
args: [{ selector: 'mm-assistant-panel', imports: [AssistantThreadComponent, AssistantComposerComponent, SVGIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
740
|
+
args: [{ selector: 'mm-assistant-panel', imports: [AssistantThreadComponent, AssistantComposerComponent, SVGIconComponent, OctoBotComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
718
741
|
'[attr.role]': 'isPhone() ? "dialog" : "complementary"',
|
|
719
742
|
'[attr.aria-modal]': 'isPhone() ? "true" : null',
|
|
720
743
|
'aria-labelledby': 'assistant-panel-title',
|
|
@@ -726,7 +749,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
726
749
|
'(keydown.escape)': 'onEscape($event)',
|
|
727
750
|
'(keydown.tab)': 'onTab($event)',
|
|
728
751
|
'(keydown.shift.tab)': 'onTab($event)'
|
|
729
|
-
}, template: "@if (canResize()) {\n <div class=\"resize-handle\" role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\" aria-controls=\"assistant-panel\"\n [attr.aria-label]=\"m().resizePanel\" [title]=\"m().resizePanel\"\n [attr.aria-valuenow]=\"currentWidth()\" [attr.aria-valuemin]=\"effectiveMin()\" [attr.aria-valuemax]=\"effectiveMax()\"\n (pointerdown)=\"startResize($event)\" (keydown)=\"onResizeKey($event)\" (dblclick)=\"resetWidth()\"></div>\n}\n\n<header class=\"head\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <h2 class=\"title\" id=\"assistant-panel-title\">{{ m().title }}</h2>\n @if (connected()) {\n <span class=\"chip-neutral\" [title]=\"m().readsWithYourPermissions\">{{ m().readsWithYourPermissions }}</span>\n }\n @if (assistant.sessionsSupported) {\n <div class=\"head-actions\">\n <button type=\"button\" class=\"icon-btn new-chat\" [attr.aria-label]=\"m().newChat\" [title]=\"m().newChat\" (click)=\"newChat()\">\n <kendo-svg-icon [icon]=\"plusIcon\"></kendo-svg-icon>\n </button>\n <button type=\"button\" class=\"icon-btn sessions-toggle\" aria-controls=\"assistant-sessions\"\n [attr.aria-label]=\"m().sessions\" [title]=\"m().sessions\"\n [attr.aria-expanded]=\"view() === 'sessions'\"\n (click)=\"view() === 'sessions' ? backToChat() : showSessions()\">\n <kendo-svg-icon [icon]=\"historyIcon\"></kendo-svg-icon>\n </button>\n </div>\n }\n <button type=\"button\" class=\"icon-btn close\" [attr.aria-label]=\"m().closeAssistant\" [title]=\"m().closeAssistant\" (click)=\"assistant.close()\">\n <kendo-svg-icon [icon]=\"xIcon\"></kendo-svg-icon>\n </button>\n</header>\n\n@if (assistant.contextChips().length) {\n <ul class=\"ctx\" [attr.aria-label]=\"m().contextLabel\">\n @for (chip of assistant.contextChips(); track chip.id; let i = $index) {\n <li class=\"ctx-chip\" [attr.data-kind]=\"chip.kind\" [title]=\"chip.value\">\n <span class=\"ctx-label\">{{ chip.label }}</span>\n <button type=\"button\" [attr.aria-label]=\"format(m().removeContext, { label: chip.label })\" [title]=\"format(m().removeContext, { label: chip.label })\" (click)=\"removeChip(chip.id, i)\"><kendo-svg-icon [icon]=\"xIcon\" size=\"small\"></kendo-svg-icon></button>\n </li>\n }\n </ul>\n}\n\n@if (view() === 'sessions') {\n <section class=\"sessions\" id=\"assistant-sessions\" [attr.aria-label]=\"m().sessionsLabel\">\n <button type=\"button\" class=\"text-btn back\" (click)=\"backToChat()\">\u2190 {{ m().backToChat }}</button>\n <ul class=\"session-list\">\n @for (session of assistant.sessions(); track session.id) {\n <li class=\"session-row\" [attr.data-session-id]=\"session.id\"\n [class.active]=\"session.id === assistant.activeSessionId()\">\n @if (confirmingDelete() === session.id) {\n <div class=\"session-confirm\" role=\"group\" [attr.aria-label]=\"format(m().deleteSessionConfirm, { title: session.title })\">\n <span class=\"confirm-text\">{{ format(m().deleteSessionConfirm, { title: session.title }) }}</span>\n <button type=\"button\" class=\"text-btn danger confirm-delete\" [disabled]=\"busySession() === session.id\"\n (click)=\"confirmDelete(session)\">{{ m().delete }}</button>\n <button type=\"button\" class=\"text-btn cancel-delete\" (click)=\"cancelDelete()\">{{ m().cancel }}</button>\n </div>\n } @else {\n <button type=\"button\" class=\"session-open\" [title]=\"session.title\"\n [attr.aria-current]=\"session.id === assistant.activeSessionId() ? 'true' : null\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"openSession(session)\">\n <span class=\"session-title\">{{ session.title }}</span>\n @if (sessionDate(session); as date) {\n <span class=\"session-date\">{{ date }}</span>\n }\n </button>\n @if (assistant.sessionDeleteSupported) {\n <button type=\"button\" class=\"icon-btn session-delete\"\n [attr.aria-label]=\"format(m().deleteSession, { title: session.title })\"\n [title]=\"format(m().deleteSession, { title: session.title })\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"askDelete(session)\">\n <kendo-svg-icon [icon]=\"trashIcon\" size=\"small\"></kendo-svg-icon>\n </button>\n }\n }\n </li>\n } @empty {\n <li class=\"session-empty\">{{ m().noSessions }}</li>\n }\n </ul>\n </section>\n} @else {\n @if (showStarters()) {\n <section class=\"starters\" aria-labelledby=\"assistant-starters-title\">\n <h3 class=\"starters-title\" id=\"assistant-starters-title\">{{ m().startersTitle }}</h3>\n <ul class=\"starter-list\">\n @for (question of assistant.starterQuestions(); track $index) {\n <li><button type=\"button\" class=\"starter\" [disabled]=\"!assistant.canSend()\" (click)=\"sendStarter(question)\">{{ question }}</button></li>\n }\n </ul>\n </section>\n }\n\n <mm-assistant-thread class=\"thread\" [items]=\"assistant.thread()\" [messages]=\"messages()\" (proposalDecision)=\"onDecision($event)\"></mm-assistant-thread>\n\n @if (!connected() || assistant.transportStatus() === 'error') {\n <div class=\"unavailable\" role=\"status\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <p>{{ assistant.transportMessage() ?? m().notAvailable }}</p>\n </div>\n }\n\n <mm-assistant-composer\n [messages]=\"messages()\"\n [text]=\"assistant.draft()\"\n (textChange)=\"assistant.setDraft($event)\"\n [attachments]=\"assistant.attachments\"\n [files]=\"assistant.draftFiles()\"\n (filesChange)=\"assistant.setDraftFiles($event)\"\n [canSend]=\"assistant.canSend()\"\n [sending]=\"assistant.sending()\"\n (send)=\"assistant.send($event)\"\n (stop)=\"assistant.stop()\">\n </mm-assistant-composer>\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;width:400px;min-height:0;border-left:1px solid var(--theme-border-subtle);background:var(--theme-bg-surface);color:var(--theme-text-primary)}.head{display:flex;align-items:center;gap:var(--theme-space-2);padding:10px 14px;border-bottom:1px solid var(--theme-border-subtle)}.title{flex:none;margin:0;white-space:nowrap;font-family:var(--theme-font-display);font-size:.8125rem;font-weight:600}.sparkle{color:var(--theme-ai)}.chip-neutral{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:6px;padding:0 7px;border-radius:var(--theme-radius-xs);background:var(--theme-status-neutral-subtle);color:var(--theme-text-secondary);font-size:.71875rem}.icon-btn{flex:none;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);cursor:pointer}.icon-btn:hover{background:var(--theme-bg-hover)}.icon-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.icon-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.close{margin-left:auto}.ctx{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:8px 14px;list-style:none;border-bottom:1px solid var(--theme-border-subtle)}.ctx-chip{display:inline-flex;align-items:center;gap:6px;max-width:100%;height:22px;padding:0 4px 0 8px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);font-size:.75rem;color:var(--theme-text-secondary)}.ctx-chip button{display:inline-grid;flex:none;place-items:center;border:0;padding:0 2px;background:none;color:var(--theme-text-muted);cursor:pointer}.ctx-chip button:hover{color:var(--theme-text-primary)}.ctx-chip button:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.ctx-label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.thread{flex:1 1 auto;min-height:0}.unavailable{display:flex;align-items:center;gap:var(--theme-space-2);margin:0 14px var(--theme-space-2);padding:8px 10px;border:1px dashed var(--theme-border-default);border-radius:var(--theme-radius-sm);color:var(--theme-text-secondary)}.unavailable p{margin:0}@media(max-width:1180px){:host{width:340px}}@media(max-width:640px){:host{position:fixed;inset:48px 0 0;z-index:30;width:auto;border-left:0}}.head-actions{display:flex;flex:none;gap:2px;margin-left:auto}.head-actions+.close{margin-left:0}.text-btn{height:26px;padding:0 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);font:inherit;font-size:.75rem;cursor:pointer}.text-btn:hover:not(:disabled){background:var(--theme-bg-hover);color:var(--theme-text-primary)}.text-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.text-btn:disabled{color:var(--theme-text-muted);cursor:default}.text-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.text-btn.danger{color:var(--theme-status-error)}.sessions{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--theme-space-2);min-height:0;padding:10px 14px;overflow:auto}.sessions .back{align-self:flex-start}.session-list{display:grid;gap:2px;margin:0;padding:0;list-style:none}.session-row{display:flex;align-items:center;gap:4px;border-radius:var(--theme-radius-sm)}.session-row.active{background:var(--theme-accent-subtle)}.session-open{display:grid;flex:1 1 auto;min-width:0;padding:6px 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.session-open:hover:not(:disabled){background:var(--theme-bg-hover)}.session-open:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.session-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.session-date{color:var(--theme-text-muted);font-size:.71875rem}.session-confirm{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:4px;padding:4px 8px}.confirm-text{flex:1 1 100%;overflow-wrap:anywhere}.session-empty{padding:6px 8px;color:var(--theme-text-secondary)}.starters{display:grid;gap:var(--theme-space-2);padding:14px 14px 0}.starters-title{margin:0;color:var(--theme-text-secondary);font-size:.75rem;font-weight:600}.starter-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.starter{width:100%;padding:6px 10px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.starter:hover:not(:disabled){border-color:var(--theme-ai);background:var(--theme-bg-hover)}.starter:disabled{color:var(--theme-text-muted);cursor:default}.starter:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.resize-handle{position:absolute;top:0;bottom:0;left:-3px;z-index:1;width:6px;cursor:col-resize;touch-action:none}.resize-handle:after{content:\"\";position:absolute;top:0;bottom:0;left:2px;width:2px;background:transparent;transition:background-color .15s}.resize-handle:hover:after,.resize-handle:focus-visible:after{background:var(--theme-accent)}.resize-handle:focus-visible{outline:none}:host(.mm-assistant-resizing){-webkit-user-select:none;user-select:none;cursor:col-resize}:host(.mm-assistant-resizing) .resize-handle:after{background:var(--theme-accent)}@media(prefers-reduced-motion:reduce){.resize-handle:after{transition:none}}:host(.mm-assistant-overlay){position:fixed;top:var(--mm-assistant-overlay-top, 48px);right:0;bottom:0;z-index:var(--mm-assistant-overlay-z-index, 20);box-shadow:var(--theme-shadow-panel)}\n"] }]
|
|
752
|
+
}, template: "@if (canResize()) {\n <div class=\"resize-handle\" role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\" aria-controls=\"assistant-panel\"\n [attr.aria-label]=\"m().resizePanel\" [title]=\"m().resizePanel\"\n [attr.aria-valuenow]=\"currentWidth()\" [attr.aria-valuemin]=\"effectiveMin()\" [attr.aria-valuemax]=\"effectiveMax()\"\n (pointerdown)=\"startResize($event)\" (keydown)=\"onResizeKey($event)\" (dblclick)=\"resetWidth()\"></div>\n}\n\n<header class=\"head\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <h2 class=\"title\" id=\"assistant-panel-title\">{{ m().title }}</h2>\n @if (connected()) {\n <span class=\"chip-neutral\" [title]=\"m().readsWithYourPermissions\">{{ m().readsWithYourPermissions }}</span>\n }\n @if (assistant.sessionsSupported) {\n <div class=\"head-actions\">\n <button type=\"button\" class=\"icon-btn new-chat\" [attr.aria-label]=\"m().newChat\" [title]=\"m().newChat\" (click)=\"newChat()\">\n <kendo-svg-icon [icon]=\"plusIcon\"></kendo-svg-icon>\n </button>\n <button type=\"button\" class=\"icon-btn sessions-toggle\" aria-controls=\"assistant-sessions\"\n [attr.aria-label]=\"m().sessions\" [title]=\"m().sessions\"\n [attr.aria-expanded]=\"view() === 'sessions'\"\n (click)=\"view() === 'sessions' ? backToChat() : showSessions()\">\n <kendo-svg-icon [icon]=\"historyIcon\"></kendo-svg-icon>\n </button>\n </div>\n }\n <button type=\"button\" class=\"icon-btn close\" [attr.aria-label]=\"m().closeAssistant\" [title]=\"m().closeAssistant\" (click)=\"assistant.close()\">\n <kendo-svg-icon [icon]=\"xIcon\"></kendo-svg-icon>\n </button>\n</header>\n\n@if (assistant.contextChips().length) {\n <ul class=\"ctx\" [attr.aria-label]=\"m().contextLabel\">\n @for (chip of assistant.contextChips(); track chip.id; let i = $index) {\n <li class=\"ctx-chip\" [attr.data-kind]=\"chip.kind\" [title]=\"chip.value\">\n <span class=\"ctx-label\">{{ chip.label }}</span>\n <button type=\"button\" [attr.aria-label]=\"format(m().removeContext, { label: chip.label })\" [title]=\"format(m().removeContext, { label: chip.label })\" (click)=\"removeChip(chip.id, i)\"><kendo-svg-icon [icon]=\"xIcon\" size=\"small\"></kendo-svg-icon></button>\n </li>\n }\n </ul>\n}\n\n@if (view() === 'sessions') {\n <section class=\"sessions\" id=\"assistant-sessions\" [attr.aria-label]=\"m().sessionsLabel\">\n <button type=\"button\" class=\"text-btn back\" (click)=\"backToChat()\">\u2190 {{ m().backToChat }}</button>\n <ul class=\"session-list\">\n @for (session of assistant.sessions(); track session.id) {\n <li class=\"session-row\" [attr.data-session-id]=\"session.id\"\n [class.active]=\"session.id === assistant.activeSessionId()\">\n @if (confirmingDelete() === session.id) {\n <div class=\"session-confirm\" role=\"group\" [attr.aria-label]=\"format(m().deleteSessionConfirm, { title: session.title })\">\n <span class=\"confirm-text\">{{ format(m().deleteSessionConfirm, { title: session.title }) }}</span>\n <button type=\"button\" class=\"text-btn danger confirm-delete\" [disabled]=\"busySession() === session.id\"\n (click)=\"confirmDelete(session)\">{{ m().delete }}</button>\n <button type=\"button\" class=\"text-btn cancel-delete\" (click)=\"cancelDelete()\">{{ m().cancel }}</button>\n </div>\n } @else {\n <button type=\"button\" class=\"session-open\" [title]=\"session.title\"\n [attr.aria-current]=\"session.id === assistant.activeSessionId() ? 'true' : null\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"openSession(session)\">\n <span class=\"session-title\">{{ session.title }}</span>\n @if (sessionDate(session); as date) {\n <span class=\"session-date\">{{ date }}</span>\n }\n </button>\n @if (assistant.sessionDeleteSupported) {\n <button type=\"button\" class=\"icon-btn session-delete\"\n [attr.aria-label]=\"format(m().deleteSession, { title: session.title })\"\n [title]=\"format(m().deleteSession, { title: session.title })\"\n [disabled]=\"busySession() === session.id\"\n (click)=\"askDelete(session)\">\n <kendo-svg-icon [icon]=\"trashIcon\" size=\"small\"></kendo-svg-icon>\n </button>\n }\n }\n </li>\n } @empty {\n <li class=\"session-empty\">{{ m().noSessions }}</li>\n }\n </ul>\n </section>\n} @else {\n @if (showGreeting()) {\n <div class=\"greeting\" data-testid=\"assistant-greeting\">\n <mm-octobot animation=\"wave\" size=\"md\" playOnce />\n <p class=\"greeting-text\">{{ m().greeting }}</p>\n </div>\n }\n @if (showStarters()) {\n <section class=\"starters\" aria-labelledby=\"assistant-starters-title\">\n <h3 class=\"starters-title\" id=\"assistant-starters-title\">{{ m().startersTitle }}</h3>\n <ul class=\"starter-list\">\n @for (question of assistant.starterQuestions(); track $index) {\n <li><button type=\"button\" class=\"starter\" [disabled]=\"!assistant.canSend()\" (click)=\"sendStarter(question)\">{{ question }}</button></li>\n }\n </ul>\n </section>\n }\n\n <mm-assistant-thread class=\"thread\" [items]=\"assistant.thread()\" [messages]=\"messages()\" (proposalDecision)=\"onDecision($event)\"></mm-assistant-thread>\n\n @if (!connected() || assistant.transportStatus() === 'error') {\n <div class=\"unavailable\" role=\"status\">\n <span class=\"sparkle\" aria-hidden=\"true\">\u2726</span>\n <p>{{ assistant.transportMessage() ?? m().notAvailable }}</p>\n </div>\n }\n\n <mm-assistant-composer\n [messages]=\"messages()\"\n [text]=\"assistant.draft()\"\n (textChange)=\"assistant.setDraft($event)\"\n [attachments]=\"assistant.attachments\"\n [files]=\"assistant.draftFiles()\"\n (filesChange)=\"assistant.setDraftFiles($event)\"\n [canSend]=\"assistant.canSend()\"\n [sending]=\"assistant.sending()\"\n (send)=\"assistant.send($event)\"\n (stop)=\"assistant.stop()\">\n </mm-assistant-composer>\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;width:400px;min-height:0;border-left:1px solid var(--theme-border-subtle);background:var(--theme-bg-surface);color:var(--theme-text-primary)}.head{display:flex;align-items:center;gap:var(--theme-space-2);padding:10px 14px;border-bottom:1px solid var(--theme-border-subtle)}.title{flex:none;margin:0;white-space:nowrap;font-family:var(--theme-font-display);font-size:.8125rem;font-weight:600}.sparkle{color:var(--theme-ai)}.chip-neutral{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:6px;padding:0 7px;border-radius:var(--theme-radius-xs);background:var(--theme-status-neutral-subtle);color:var(--theme-text-secondary);font-size:.71875rem}.icon-btn{flex:none;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);cursor:pointer}.icon-btn:hover{background:var(--theme-bg-hover)}.icon-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.icon-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.close{margin-left:auto}.ctx{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:8px 14px;list-style:none;border-bottom:1px solid var(--theme-border-subtle)}.ctx-chip{display:inline-flex;align-items:center;gap:6px;max-width:100%;height:22px;padding:0 4px 0 8px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-xs);font-size:.75rem;color:var(--theme-text-secondary)}.ctx-chip button{display:inline-grid;flex:none;place-items:center;border:0;padding:0 2px;background:none;color:var(--theme-text-muted);cursor:pointer}.ctx-chip button:hover{color:var(--theme-text-primary)}.ctx-chip button:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.ctx-label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.thread{flex:1 1 auto;min-height:0}.unavailable{display:flex;align-items:center;gap:var(--theme-space-2);margin:0 14px var(--theme-space-2);padding:8px 10px;border:1px dashed var(--theme-border-default);border-radius:var(--theme-radius-sm);color:var(--theme-text-secondary)}.unavailable p{margin:0}@media(max-width:1180px){:host{width:340px}}@media(max-width:640px){:host{position:fixed;inset:48px 0 0;z-index:30;width:auto;border-left:0}}.head-actions{display:flex;flex:none;gap:2px;margin-left:auto}.head-actions+.close{margin-left:0}.text-btn{height:26px;padding:0 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-secondary);font:inherit;font-size:.75rem;cursor:pointer}.text-btn:hover:not(:disabled){background:var(--theme-bg-hover);color:var(--theme-text-primary)}.text-btn[aria-expanded=true]{background:var(--theme-accent-subtle);color:var(--theme-text-primary)}.text-btn:disabled{color:var(--theme-text-muted);cursor:default}.text-btn:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.text-btn.danger{color:var(--theme-status-error)}.sessions{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--theme-space-2);min-height:0;padding:10px 14px;overflow:auto}.sessions .back{align-self:flex-start}.session-list{display:grid;gap:2px;margin:0;padding:0;list-style:none}.session-row{display:flex;align-items:center;gap:4px;border-radius:var(--theme-radius-sm)}.session-row.active{background:var(--theme-accent-subtle)}.session-open{display:grid;flex:1 1 auto;min-width:0;padding:6px 8px;border:0;border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.session-open:hover:not(:disabled){background:var(--theme-bg-hover)}.session-open:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.session-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.session-date{color:var(--theme-text-muted);font-size:.71875rem}.session-confirm{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:4px;padding:4px 8px}.confirm-text{flex:1 1 100%;overflow-wrap:anywhere}.session-empty{padding:6px 8px;color:var(--theme-text-secondary)}.greeting{display:grid;justify-items:center;gap:var(--theme-space-2);padding:20px 14px 0;text-align:center}.greeting-text{margin:0;color:var(--theme-text-primary);font-weight:600}.starters{display:grid;gap:var(--theme-space-2);padding:14px 14px 0}.starters-title{margin:0;color:var(--theme-text-secondary);font-size:.75rem;font-weight:600}.starter-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.starter{width:100%;padding:6px 10px;border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-sm);background:none;color:var(--theme-text-primary);font:inherit;text-align:left;cursor:pointer}.starter:hover:not(:disabled){border-color:var(--theme-ai);background:var(--theme-bg-hover)}.starter:disabled{color:var(--theme-text-muted);cursor:default}.starter:focus-visible{outline:none;box-shadow:var(--theme-focus-ring)}.resize-handle{--mm-resize-line: transparent;--mm-resize-grip: var(--theme-border-default, var(--theme-border-subtle, rgba(128, 128, 128, .5)));position:absolute;top:0;bottom:0;left:-4px;z-index:1;width:8px;cursor:col-resize;touch-action:none}.resize-handle:after{content:\"\";position:absolute;top:0;bottom:0;left:3px;width:2px;background:var(--mm-resize-line);transition:background-color .15s}.resize-handle:before{content:\"\";position:absolute;top:50%;left:2px;z-index:1;width:4px;height:32px;margin-top:-16px;border-radius:2px;background:var(--mm-resize-grip);transition:background-color .15s}.resize-handle:hover,.resize-handle:focus-visible{--mm-resize-line: var(--theme-accent);--mm-resize-grip: var(--theme-accent)}.resize-handle:focus-visible{outline:none}:host(.mm-assistant-resizing){-webkit-user-select:none;user-select:none;cursor:col-resize}:host(.mm-assistant-resizing) .resize-handle{--mm-resize-line: var(--theme-accent);--mm-resize-grip: var(--theme-accent)}@media(prefers-reduced-motion:reduce){.resize-handle:after,.resize-handle:before{transition:none}}:host(.mm-assistant-overlay){position:fixed;top:var(--mm-assistant-overlay-top, 48px);right:0;bottom:0;z-index:var(--mm-assistant-overlay-z-index, 20);box-shadow:var(--theme-shadow-panel)}\n"] }]
|
|
730
753
|
}], ctorParameters: () => [], propDecorators: { composer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AssistantComposerComponent), { isSignal: true }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }] } });
|
|
731
754
|
|
|
732
755
|
/*
|