@newheap/platform-ai-chat 0.13.0 → 0.14.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 +5 -0
- package/admin/index.d.ts +164 -4
- package/fesm2022/newheap-platform-ai-chat-admin.mjs +468 -15
- package/fesm2022/newheap-platform-ai-chat-admin.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat-testing.mjs +564 -2
- package/fesm2022/newheap-platform-ai-chat-testing.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat.mjs +514 -28
- package/fesm2022/newheap-platform-ai-chat.mjs.map +1 -1
- package/i18n/en.json +189 -3
- package/i18n/nl.json +189 -3
- package/index.d.ts +336 -6
- package/package.json +1 -1
- package/testing/index.d.ts +13 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"newheap-platform-ai-chat-admin.mjs","sources":["../../../projects/nh-ai-chat/admin/src/context/nh-assistant-admin-context.component.ts","../../../projects/nh-ai-chat/admin/src/context/nh-assistant-admin-context.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agent-editor.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agent-editor.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-evaluation.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-evaluation.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-feedback-report.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-feedback-report.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agents.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agents.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-server-editor.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-server-editor.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-tools.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-tools.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-servers.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-servers.component.html","../../../projects/nh-ai-chat/admin/src/nh-assistant-admin.component.ts","../../../projects/nh-ai-chat/admin/src/nh-assistant-admin.component.html","../../../projects/nh-ai-chat/admin/src/public-api.ts","../../../projects/nh-ai-chat/admin/src/newheap-platform-ai-chat-admin.ts"],"sourcesContent":["import { DatePipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription, forkJoin } from 'rxjs';\nimport {\n ApplicationContext,\n ApplicationContextVersion,\n NhAssistantAdminApiService,\n NhAssistantClientErrorCodes,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Maximum length of the application context and of agent instructions. */\nexport const NH_ASSISTANT_MAX_INSTRUCTIONS = 20_000;\n\nlet nextId = 0;\n\n/**\n * Editor of the application context: the current version with its hash, optimistic\n * concurrency through `expectedVersion`, and the version history.\n */\n@Component({\n selector: 'nh-assistant-admin-context',\n standalone: true,\n imports: [DatePipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-context.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminContextComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n readonly id = `nh-assistant-admin-context-${nextId++}`;\n readonly max = NH_ASSISTANT_MAX_INSTRUCTIONS;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly saving = signal(false);\n readonly saved = signal(false);\n readonly conflict = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n readonly context = signal<ApplicationContext | null>(null);\n readonly versions = signal<ApplicationContextVersion[]>([]);\n readonly text = signal('');\n\n readonly tooLong = computed(() => this.text().length > this.max);\n readonly dirty = computed(() => this.text() !== (this.context()?.text ?? ''));\n readonly canSave = computed(() => !this.saving() && !this.tooLong() && this.dirty() && this.context() !== null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly history = computed(() => this.versions().filter(version => version.version !== this.context()?.version));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n this.load(false);\n }\n\n /** Loads the latest version; with `keepDraft` the user's unsaved text stays in the editor. */\n load(keepDraft: boolean): void {\n this.loading.set(!keepDraft);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = forkJoin([this.admin.getContext(), this.admin.getContextVersions()]).subscribe({\n next: ([context, versions]) => {\n const draft = this.text();\n this.context.set(context);\n this.versions.set(versions);\n this.text.set(keepDraft ? draft : context.text);\n this.conflict.set(false);\n this.error.set(null);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n onInput(event: Event): void {\n this.text.set((event.target as HTMLTextAreaElement).value);\n this.saved.set(false);\n }\n\n save(): void {\n const context = this.context();\n if (!context || !this.canSave()) {\n return;\n }\n\n this.saving.set(true);\n this.saved.set(false);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.updateContext({ text: this.text(), expectedVersion: context.version }).subscribe({\n next: updated => {\n this.context.set(updated);\n this.versions.update(versions => [\n { version: updated.version, hash: updated.hash, updatedAt: updated.updatedAt, updatedBy: updated.updatedBy },\n ...versions\n ]);\n this.text.set(updated.text);\n this.saving.set(false);\n this.saved.set(true);\n },\n error: (error: unknown) => {\n const failure = toNhAssistantError(error);\n this.saving.set(false);\n this.conflict.set(failure.code === NhAssistantClientErrorCodes.versionConflict);\n this.error.set(this.conflict() ? null : failure);\n }\n });\n }\n}\n","<section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading() || saving()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.context.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.context.description' | translate }}</p>\n </div>\n </header>\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load(false)\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (context(); as current) {\n <form class=\"stack\" (submit)=\"$event.preventDefault(); save()\">\n <div class=\"meta\">\n <span class=\"badge\">{{ 'nh-assistant.admin.context.version' | translate: { version: current.version } }}</span>\n <span>\n @if (current.updatedBy) {\n {{ 'nh-assistant.admin.context.updated' | translate: { date: (current.updatedAt | date: 'medium'), user: current.updatedBy } }}\n } @else {\n {{ 'nh-assistant.admin.context.updated-unknown' | translate: { date: (current.updatedAt | date: 'medium') } }}\n }\n </span>\n <span class=\"mono\" [attr.title]=\"current.hash\">{{ 'nh-assistant.admin.context.hash' | translate }} {{ current.hash.slice(0, 18) }}</span>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-text'\">{{ 'nh-assistant.admin.context.label' | translate }}</label>\n <textarea\n class=\"large\"\n rows=\"14\"\n [id]=\"id + '-text'\"\n [value]=\"text()\"\n [attr.aria-describedby]=\"id + '-hint'\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"></textarea>\n <p class=\"hint\" [id]=\"id + '-hint'\">\n <span [class.error-text]=\"tooLong()\">{{ tooLong() ? ('nh-assistant.admin.too-long' | translate) : '' }}</span>\n <span class=\"counter\" [class.error-text]=\"tooLong()\">{{ 'nh-assistant.admin.characters' | translate: { count: text().length, max: max } }}</span>\n </p>\n </div>\n\n @if (conflict()) {\n <div class=\"message warning\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <span class=\"grow\">{{ 'nh-assistant.admin.context.conflict' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"load(true)\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.context.reload' | translate }}\n </button>\n </div>\n }\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (saved()) {\n <p class=\"message success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.saved' | translate }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"primary\" type=\"submit\" [disabled]=\"!canSave()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n </form>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-history'\">\n <h4 [id]=\"id + '-history'\">{{ 'nh-assistant.admin.context.history' | translate }}</h4>\n @if (history().length === 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.context.history-empty' | translate }}</p>\n } @else {\n <ol class=\"history\">\n @for (version of history(); track version.version) {\n <li>\n <span class=\"badge\">{{ 'nh-assistant.admin.context.version' | translate: { version: version.version } }}</span>\n <span>{{ version.updatedAt | date: 'medium' }}</span>\n @if (version.updatedBy) {\n <span>{{ version.updatedBy }}</span>\n }\n <span class=\"mono muted\" [attr.title]=\"version.hash\">{{ version.hash.slice(0, 18) }}</span>\n </li>\n }\n </ol>\n }\n </section>\n }\n</section>\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AdminAgent,\n AdminAgentInput,\n AssistantAutonomy,\n McpServer,\n ɵNH_ASSISTANT_DASH_CASE as NH_ASSISTANT_DASH_CASE,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError,\n ToolCatalogEntry\n} from '@newheap/platform-ai-chat';\nimport { NH_ASSISTANT_MAX_INSTRUCTIONS } from '../context/nh-assistant-admin-context.component';\n\n/** True when a tool id matches a selector glob (`*` matches any characters). */\nexport function nhAssistantSelectorMatches(toolId: string, selector: string): boolean {\n const pattern = selector.split('*').map(part => part.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('.*');\n return new RegExp(`^${pattern}$`).test(toolId);\n}\n\nconst selectorPattern = /^[a-z0-9*][a-z0-9.*_-]*$/i;\n\nlet nextId = 0;\n\n/**\n * Creates or edits one agent: texts, autonomy, policy, tool selectors chosen from the tool\n * catalog or typed as patterns, and assigned MCP servers.\n */\n@Component({\n selector: 'nh-assistant-admin-agent-editor',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-agent-editor.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminAgentEditorComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n /** The agent to edit, or null for a new agent. */\n readonly agent = input<AdminAgent | null>(null);\n readonly tools = input<readonly ToolCatalogEntry[]>([]);\n readonly servers = input<readonly McpServer[]>([]);\n readonly saved = output<AdminAgent>();\n readonly cancelled = output<void>();\n\n readonly id = `nh-assistant-agent-editor-${nextId++}`;\n readonly max = NH_ASSISTANT_MAX_INSTRUCTIONS;\n readonly autonomyLevels: readonly AssistantAutonomy[] = ['observe', 'explain', 'propose', 'simulate', 'execute'];\n\n readonly agentId = signal('');\n readonly displayName = signal('');\n readonly description = signal('');\n readonly instructions = signal('');\n readonly autonomy = signal<AssistantAutonomy>('explain');\n readonly requiredPolicy = signal('');\n readonly toolSelectors = signal<string[]>([]);\n readonly mcpServerIds = signal<string[]>([]);\n readonly newSelector = signal('');\n readonly catalogFilter = signal('');\n readonly submitted = signal(false);\n readonly saving = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n\n readonly isNew = computed(() => this.agent() === null);\n readonly idInvalid = computed(() => this.isNew() && !NH_ASSISTANT_DASH_CASE.test(this.agentId()));\n readonly nameMissing = computed(() => this.displayName().trim().length === 0);\n readonly tooLong = computed(() => this.instructions().length > this.max);\n readonly selectorInvalid = computed(() => this.newSelector().trim().length > 0 && !selectorPattern.test(this.newSelector().trim()));\n readonly valid = computed(() => !this.idInvalid() && !this.nameMissing() && !this.tooLong());\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly filteredTools = computed(() => {\n const filter = this.catalogFilter().trim().toLowerCase();\n return this.tools().filter(tool => !filter ||\n tool.id.toLowerCase().includes(filter) || tool.description.toLowerCase().includes(filter));\n });\n readonly matchCount = computed(() => this.tools()\n .filter(tool => this.toolSelectors().some(selector => nhAssistantSelectorMatches(tool.id, selector))).length);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n\n effect(() => {\n const agent = this.agent();\n untracked(() => this.reset(agent));\n });\n }\n\n isSelected(toolId: string): boolean {\n return this.toolSelectors().includes(toolId);\n }\n\n isCovered(toolId: string): boolean {\n return this.toolSelectors().some(selector => selector !== toolId && nhAssistantSelectorMatches(toolId, selector));\n }\n\n toggleTool(toolId: string, checked: boolean): void {\n this.toolSelectors.update(selectors => checked\n ? [...selectors.filter(selector => selector !== toolId), toolId]\n : selectors.filter(selector => selector !== toolId));\n }\n\n addSelector(): void {\n const selector = this.newSelector().trim();\n if (selector.length === 0 || this.selectorInvalid()) {\n return;\n }\n\n this.toolSelectors.update(selectors => selectors.includes(selector) ? selectors : [...selectors, selector]);\n this.newSelector.set('');\n }\n\n onSelectorKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.addSelector();\n }\n }\n\n removeSelector(selector: string): void {\n this.toolSelectors.update(selectors => selectors.filter(item => item !== selector));\n }\n\n toggleServer(serverId: string, checked: boolean): void {\n this.mcpServerIds.update(ids => checked ? [...ids.filter(id => id !== serverId), serverId] : ids.filter(id => id !== serverId));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n save(): void {\n this.submitted.set(true);\n if (!this.valid() || this.saving()) {\n return;\n }\n\n const policy = this.requiredPolicy().trim();\n const input: AdminAgentInput = {\n id: this.isNew() ? this.agentId() : this.agent()!.id,\n displayName: this.displayName().trim(),\n description: this.description().trim(),\n instructions: this.instructions(),\n toolSelectors: this.toolSelectors(),\n mcpServerIds: this.mcpServerIds(),\n requiredPolicy: policy.length > 0 ? policy : null,\n autonomy: this.autonomy()\n };\n\n const existing = this.agent();\n const request = existing\n ? this.admin.updateAgent(existing.id, { ...input, expectedVersion: existing.version })\n : this.admin.createAgent(input);\n\n this.saving.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = request.subscribe({\n next: agent => {\n this.saving.set(false);\n this.saved.emit(agent);\n },\n error: (error: unknown) => {\n this.saving.set(false);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private reset(agent: AdminAgent | null): void {\n this.agentId.set(agent?.id ?? '');\n this.displayName.set(agent?.displayName ?? '');\n this.description.set(agent?.description ?? '');\n this.instructions.set(agent?.instructions ?? '');\n this.autonomy.set(agent?.autonomy ?? 'explain');\n this.requiredPolicy.set(agent?.requiredPolicy ?? '');\n this.toolSelectors.set([...(agent?.toolSelectors ?? [])]);\n this.mcpServerIds.set([...(agent?.mcpServerIds ?? [])]);\n this.submitted.set(false);\n this.error.set(null);\n }\n}\n","<form class=\"section card\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"saving()\" (submit)=\"$event.preventDefault(); save()\">\n <h3 [id]=\"id + '-title'\">\n @if (agent(); as current) {\n {{ 'nh-assistant.admin.agent-editor.edit-title' | translate: { name: current.displayName } }}\n } @else {\n {{ 'nh-assistant.admin.agent-editor.new-title' | translate }}\n }\n </h3>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-id'\">{{ 'nh-assistant.admin.agent-editor.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [id]=\"id + '-id'\"\n [value]=\"agentId()\"\n [disabled]=\"!isNew()\"\n [attr.aria-describedby]=\"id + '-id-hint'\"\n [attr.aria-invalid]=\"submitted() && idInvalid() ? true : null\"\n (input)=\"agentId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-id-hint'\">\n <span [class.error-text]=\"submitted() && idInvalid()\">\n {{ (submitted() && idInvalid() ? 'nh-assistant.admin.invalid-id' : 'nh-assistant.admin.agent-editor.id-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-name'\">{{ 'nh-assistant.admin.agent-editor.display-name' | translate }}</label>\n <input\n type=\"text\"\n [id]=\"id + '-name'\"\n [value]=\"displayName()\"\n [attr.aria-invalid]=\"submitted() && nameMissing() ? true : null\"\n [attr.aria-describedby]=\"id + '-name-hint'\"\n (input)=\"displayName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-name-hint'\">\n @if (submitted() && nameMissing()) {\n <span class=\"error-text\">{{ 'nh-assistant.admin.required' | translate }}</span>\n }\n </p>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-description'\">{{ 'nh-assistant.admin.agent-editor.description' | translate }}</label>\n <input type=\"text\" [id]=\"id + '-description'\" [value]=\"description()\" (input)=\"description.set(value($event))\" />\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-instructions'\">{{ 'nh-assistant.admin.agent-editor.instructions' | translate }}</label>\n <textarea\n rows=\"8\"\n [id]=\"id + '-instructions'\"\n [value]=\"instructions()\"\n [attr.aria-describedby]=\"id + '-instructions-hint'\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"instructions.set(value($event))\"></textarea>\n <p class=\"hint\" [id]=\"id + '-instructions-hint'\">\n <span [class.error-text]=\"tooLong()\">\n {{ (tooLong() ? 'nh-assistant.admin.too-long' : 'nh-assistant.admin.agent-editor.instructions-hint') | translate }}\n </span>\n <span class=\"counter\" [class.error-text]=\"tooLong()\">{{ 'nh-assistant.admin.characters' | translate: { count: instructions().length, max: max } }}</span>\n </p>\n </div>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-autonomy'\">{{ 'nh-assistant.admin.agent-editor.autonomy' | translate }}</label>\n <select [id]=\"id + '-autonomy'\" [attr.aria-describedby]=\"id + '-autonomy-hint'\" (change)=\"autonomy.set($any(value($event)))\">\n @for (level of autonomyLevels; track level) {\n <option [value]=\"level\" [selected]=\"autonomy() === level\">{{ 'nh-assistant.admin.agents.autonomy.' + level | translate }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-autonomy-hint'\">{{ 'nh-assistant.admin.agent-editor.autonomy-hint' | translate }}</p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-policy'\">{{ 'nh-assistant.admin.agent-editor.required-policy' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [id]=\"id + '-policy'\"\n [value]=\"requiredPolicy()\"\n [attr.aria-describedby]=\"id + '-policy-hint'\"\n (input)=\"requiredPolicy.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-policy-hint'\">{{ 'nh-assistant.admin.agent-editor.required-policy-hint' | translate }}</p>\n </div>\n </div>\n\n <p class=\"hint\">{{ 'nh-assistant.admin.agent-editor.state-hint' | translate }}</p>\n\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.agent-editor.tool-selectors' | translate }}</legend>\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.tool-selectors-hint' | translate }}</p>\n\n @if (toolSelectors().length === 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.no-selectors' | translate }}</p>\n } @else {\n <ul class=\"chips\">\n @for (selector of toolSelectors(); track selector) {\n <li class=\"chip\">\n <span>{{ selector }}</span>\n <button\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.admin.agent-editor.remove-selector' | translate: { selector: selector }\"\n [attr.title]=\"'nh-assistant.admin.agent-editor.remove-selector' | translate: { selector: selector }\"\n (click)=\"removeSelector(selector)\">\n <nh-assistant-icon name=\"x\" />\n </button>\n </li>\n }\n </ul>\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.admin.agent-editor.matches' | translate: { count: matchCount() } }}</p>\n }\n\n <div class=\"inline\">\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [attr.aria-label]=\"'nh-assistant.admin.agent-editor.add-selector' | translate\"\n [attr.placeholder]=\"'nh-assistant.admin.agent-editor.selector-placeholder' | translate\"\n [attr.aria-invalid]=\"selectorInvalid() ? true : null\"\n [value]=\"newSelector()\"\n (input)=\"newSelector.set(value($event))\"\n (keydown)=\"onSelectorKeydown($event)\" />\n <button class=\"secondary\" type=\"button\" [disabled]=\"newSelector().trim().length === 0 || selectorInvalid()\" (click)=\"addSelector()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.agent-editor.add-selector' | translate }}\n </button>\n </div>\n\n <div class=\"field\">\n <label class=\"label\" [for]=\"id + '-catalog-filter'\">{{ 'nh-assistant.admin.agent-editor.catalog' | translate }}</label>\n <input\n type=\"search\"\n [id]=\"id + '-catalog-filter'\"\n [attr.placeholder]=\"'nh-assistant.admin.agent-editor.catalog-filter' | translate\"\n [value]=\"catalogFilter()\"\n (input)=\"catalogFilter.set(value($event))\" />\n <ul class=\"catalog\" [attr.aria-label]=\"'nh-assistant.admin.agent-editor.catalog' | translate\">\n @for (tool of filteredTools(); track tool.id) {\n <li>\n <label>\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(tool.id) || isCovered(tool.id)\"\n [disabled]=\"isCovered(tool.id)\"\n (change)=\"toggleTool(tool.id, checked($event))\" />\n <span class=\"tool-id\">{{ tool.id }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.source.' + tool.source | translate }}</span>\n <span class=\"badge\" [class.warning]=\"tool.effect !== 'read-only'\">{{ 'nh-assistant.admin.effect.' + tool.effect | translate }}</span>\n <span class=\"muted\">{{ tool.description }}</span>\n </label>\n </li>\n } @empty {\n <li class=\"muted\">{{ 'nh-assistant.admin.agent-editor.catalog-empty' | translate }}</li>\n }\n </ul>\n </div>\n </fieldset>\n\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.agent-editor.mcp-servers' | translate }}</legend>\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.mcp-servers-hint' | translate }}</p>\n @for (server of servers(); track server.id) {\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"mcpServerIds().includes(server.id)\" (change)=\"toggleServer(server.id, checked($event))\" />\n <span>{{ server.displayName }} <span class=\"mono muted\">{{ server.id }}</span></span>\n </label>\n } @empty {\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.mcp-servers-empty' | translate }}</p>\n }\n </fieldset>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancelled.emit()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"saving() || tooLong()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n</form>\n","import { DatePipe, DecimalPipe, DOCUMENT } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AgentEvaluation,\n AgentEvaluationCost,\n AgentReplay,\n NhAssistantAdminApiService,\n NhAssistantError,\n NhAssistantPanelService,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Periods the evaluation offers, in days before now; the server allows at most 92. */\nexport type NhAssistantEvaluationPeriod = 7 | 30 | 90;\n\n/** One row of the cost comparison: a measure of the live agent next to the variant's. */\ninterface NhAssistantCostRow {\n key: 'runs' | 'model-calls' | 'tokens' | 'tool-calls';\n live: AgentEvaluationCost;\n variant: AgentEvaluationCost;\n}\n\nconst dayMs = 24 * 60 * 60 * 1000;\nconst defaultReplayRuns = 100;\nconst maxReplayRuns = 500;\n\nlet nextId = 0;\n\n/**\n * Compares a shadow variant of an agent with the live agent, for the agent's administrators: the\n * runs that handled the same events, per tool the proposals both made, only one made and what\n * people decided about the live ones, what each cost and how each routed, with links to the threads\n * of the differences. Small numbers mislead, so counts stand next to every share. Administrators\n * replay the recorded runs of the period into the variant and export the comparison as JSON Lines.\n * The report holds no messages or arguments.\n */\n@Component({\n selector: 'nh-assistant-agent-evaluation',\n standalone: true,\n imports: [DatePipe, DecimalPipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-agent-evaluation.component.html',\n styleUrls: ['../nh-assistant-admin-shared.scss', './nh-assistant-agent-feedback-report.component.scss']\n})\nexport class NhAssistantAgentEvaluationComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly panel = inject(NhAssistantPanelService, { optional: true });\n private readonly document = inject(DOCUMENT);\n private subscription?: Subscription;\n private replaySubscription?: Subscription;\n\n /** The live agent. */\n readonly agentId = input.required<string>();\n /** Its shadow variants; the first is compared until another is chosen. */\n readonly variants = input.required<readonly string[]>();\n\n readonly id = `nh-assistant-agent-evaluation-${nextId++}`;\n readonly periods: readonly NhAssistantEvaluationPeriod[] = [7, 30, 90];\n readonly maxReplayRuns = maxReplayRuns;\n readonly canOpenThreads = this.panel !== null;\n\n readonly variant = signal('');\n readonly period = signal<NhAssistantEvaluationPeriod>(7);\n readonly loading = signal(true);\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly evaluation = signal<AgentEvaluation | null>(null);\n\n readonly exporting = signal(false);\n readonly exportError = signal<NhAssistantError | null>(null);\n readonly exportErrorKeys = computed(() => nhAssistantErrorKeys(this.exportError()));\n readonly canExport = computed(() => !this.exporting() && !this.loading() && (this.evaluation()?.runs.paired ?? 0) > 0);\n\n readonly replays = signal<AgentReplay[]>([]);\n readonly replayRuns = signal(defaultReplayRuns);\n readonly replaying = signal(false);\n readonly replayError = signal<NhAssistantError | null>(null);\n readonly replayErrorKeys = computed(() => nhAssistantErrorKeys(this.replayError()));\n readonly replayRunning = computed(() => this.replays().some(replay => replay.status === 'running'));\n\n readonly costRows = computed<NhAssistantCostRow[]>(() => {\n const evaluation = this.evaluation();\n return evaluation\n ? (['runs', 'model-calls', 'tokens', 'tool-calls'] as const).map(key => ({ key, live: evaluation.liveCost, variant: evaluation.variantCost }))\n : [];\n });\n /** Routing matters only when one of the two worked in a skill. */\n readonly showRouting = computed(() => (this.evaluation()?.routing ?? []).some(row => row.liveSkill !== null || row.variantSkill !== null));\n\n /** The period the last load asked for, so the report, the export and a replay agree. */\n private range = periodRange(7);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.replaySubscription?.unsubscribe();\n });\n effect(() => {\n const variants = this.variants();\n this.agentId();\n untracked(() => {\n if (!variants.includes(this.variant())) {\n this.variant.set(variants[0] ?? '');\n }\n this.load();\n });\n });\n }\n\n /** Reloads the comparison and the variant's replays for the chosen period. */\n load(): void {\n this.range = periodRange(this.period());\n this.error.set(null);\n this.exportError.set(null);\n this.subscription?.unsubscribe();\n if (!this.variant()) {\n this.loading.set(false);\n this.evaluation.set(null);\n return;\n }\n\n this.loading.set(true);\n this.subscription = this.admin.getAgentEvaluation(this.agentId(), { variant: this.variant(), ...this.range }).subscribe({\n next: evaluation => {\n this.evaluation.set(evaluation);\n this.loading.set(false);\n },\n error: (failure: unknown) => {\n this.evaluation.set(null);\n this.loading.set(false);\n this.error.set(toNhAssistantError(failure));\n }\n });\n this.loadReplays();\n }\n\n loadReplays(): void {\n this.replaySubscription?.unsubscribe();\n this.replaySubscription = this.admin.getAgentReplays(this.variant()).subscribe({\n next: list => this.replays.set(list.items),\n error: () => this.replays.set([])\n });\n }\n\n onVariant(event: Event): void {\n this.variant.set((event.target as HTMLSelectElement).value);\n this.load();\n }\n\n onPeriod(event: Event): void {\n this.period.set(Number((event.target as HTMLSelectElement).value) as NhAssistantEvaluationPeriod);\n this.load();\n }\n\n onReplayRuns(event: Event): void {\n const value = Math.round(Number((event.target as HTMLInputElement).value));\n this.replayRuns.set(Number.isFinite(value) ? Math.min(Math.max(value, 1), maxReplayRuns) : defaultReplayRuns);\n }\n\n /** Replays the live agent's recorded runs of the period into the variant. */\n replay(): void {\n if (this.replaying() || this.replayRunning() || !this.variant()) {\n return;\n }\n\n this.replaying.set(true);\n this.replayError.set(null);\n this.admin\n .startAgentReplay(this.variant(), { sourceAgentId: this.agentId(), ...this.range, maxRuns: this.replayRuns() })\n .subscribe({\n next: replay => {\n this.replaying.set(false);\n this.replays.update(items => [replay, ...items.filter(item => item.id !== replay.id)]);\n },\n error: (failure: unknown) => {\n this.replaying.set(false);\n this.replayError.set(toNhAssistantError(failure));\n }\n });\n }\n\n /** Downloads the paired runs of the comparison as a JSON Lines file. */\n async export(): Promise<void> {\n if (!this.canExport()) {\n return;\n }\n\n this.exporting.set(true);\n this.exportError.set(null);\n try {\n const blob = await this.admin.exportAgentEvaluation(this.agentId(), { variant: this.variant(), ...this.range });\n const url = URL.createObjectURL(blob);\n const link = this.document.createElement('a');\n link.href = url;\n link.download = `agent-evaluation-${this.agentId()}-${this.variant()}.jsonl`;\n link.click();\n URL.revokeObjectURL(url);\n } catch (failure) {\n this.exportError.set(toNhAssistantError(failure));\n } finally {\n this.exporting.set(false);\n }\n }\n\n /** Opens a thread of the comparison in the assistant panel, when the host has one. */\n openThread(conversationId: string): void {\n this.panel?.open(conversationId);\n }\n\n /** The share of a count in a total, or `null` without a total. */\n share(count: number, total: number): number | null {\n return total > 0 ? count / total : null;\n }\n\n total(row: AgentEvaluation['tools'][number]): number {\n return row.agreed + row.liveOnly;\n }\n\n categories(row: AgentEvaluation['tools'][number]): { category: string; count: number }[] {\n return Object.entries(row.liveDecisions.rejectionCategories)\n .map(([category, count]) => ({ category, count }))\n .sort((left, right) => right.count - left.count);\n }\n}\n\nfunction periodRange(days: number): { from: string; to: string } {\n const to = Date.now();\n return { from: new Date(to - days * dayMs).toISOString(), to: new Date(to).toISOString() };\n}\n","<section class=\"section report\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.evaluation.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.description' | translate }}</p>\n <p class=\"muted export-hint\" [id]=\"id + '-export-hint'\">{{ 'nh-assistant.admin.evaluation.export-hint' | translate }}</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.evaluation.refresh' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"!canExport()\" [attr.aria-describedby]=\"id + '-export-hint'\" (click)=\"export()\">\n <nh-assistant-icon name=\"page\" />{{ (exporting() ? 'nh-assistant.admin.evaluation.exporting' : 'nh-assistant.admin.evaluation.export') | translate }}\n </button>\n </div>\n </header>\n\n <div class=\"filters\">\n <div class=\"field\">\n <label [for]=\"id + '-variant'\">{{ 'nh-assistant.admin.evaluation.variant' | translate }}</label>\n <select [id]=\"id + '-variant'\" (change)=\"onVariant($event)\">\n @for (option of variants(); track option) {\n <option [value]=\"option\" [selected]=\"variant() === option\">\n {{ ['nh-assistant.agents.' + option + '.name'] | nhAssistantTranslate: option }}\n </option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-period'\">{{ 'nh-assistant.admin.evaluation.period' | translate }}</label>\n <select [id]=\"id + '-period'\" (change)=\"onPeriod($event)\">\n @for (days of periods; track days) {\n <option [value]=\"days\" [selected]=\"period() === days\">{{ 'nh-assistant.admin.feedback.periods.last-' + days + '-days' | translate }}</option>\n }\n </select>\n </div>\n </div>\n\n @if (exportError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ exportErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading() && evaluation() === null) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (error(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (evaluation(); as report) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-runs-title'\">\n <h4 [id]=\"id + '-runs-title'\">{{ 'nh-assistant.admin.evaluation.runs-title' | translate }}</h4>\n <dl class=\"meta\" data-evaluation-runs>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.live' | translate }}</dt><dd>{{ report.runs.live }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.variant' | translate }}</dt><dd>{{ report.runs.variant }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.paired' | translate }}</dt><dd data-paired>{{ report.runs.paired }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.replayed' | translate }}</dt><dd>{{ report.runs.replayed }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.live-unpaired' | translate }}</dt><dd>{{ report.runs.liveUnpaired }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.variant-unpaired' | translate }}</dt><dd>{{ report.runs.variantUnpaired }}</dd></div>\n </dl>\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.small-numbers' | translate }}</p>\n @if (report.runs.replayed > 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.replayed-hint' | translate }}</p>\n }\n @if (report.runs.truncated) {\n <p class=\"message\" role=\"status\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.evaluation.truncated' | translate }}</p>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-tools-title'\">\n <h4 [id]=\"id + '-tools-title'\">{{ 'nh-assistant.admin.evaluation.tools-title' | translate }}</h4>\n @if (report.tools.length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.evaluation.tools-empty' | translate }}</p>\n } @else {\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-tools-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.tool' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.agreed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.live-only' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.variant-only' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.rejected-not-proposed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.rejected-also-proposed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.approved-missed' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.live-decisions' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of report.tools; track row.toolId) {\n <tr [attr.data-evaluation-tool]=\"row.toolId\">\n <th scope=\"row\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.tool' | translate\"><span class=\"mono\">{{ row.toolId }}</span></th>\n <td class=\"number\" data-agreed [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.agreed' | translate\">\n {{ row.agreed }}\n @if (share(row.agreed, total(row)); as fraction) {\n <span class=\"muted\">({{ fraction * 100 | number: '1.0-0' }}%)</span>\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-only' | translate\">{{ row.liveOnly }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.variant-only' | translate\">{{ row.variantOnly }}</td>\n <td class=\"number\" data-rejected-not-proposed [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.rejected-not-proposed' | translate\">{{ row.rejectedLiveNotProposed }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.rejected-also-proposed' | translate\">{{ row.rejectedLiveAlsoProposed }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.approved-missed' | translate\">{{ row.approvedLiveMissed }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-decisions' | translate\">\n {{ 'nh-assistant.admin.evaluation.decisions' | translate: row.liveDecisions }}\n @if (categories(row).length > 0) {\n <ul class=\"badges\">\n @for (item of categories(row); track item.category) {\n <li>\n <span class=\"badge\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-cost-title'\">\n <h4 [id]=\"id + '-cost-title'\">{{ 'nh-assistant.admin.evaluation.cost-title' | translate }}</h4>\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-cost-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.measure' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.live' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.variant' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of costRows(); track row.key) {\n <tr [attr.data-cost]=\"row.key\">\n <th scope=\"row\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.measure' | translate\">{{ 'nh-assistant.admin.evaluation.cost.' + row.key | translate }}</th>\n @for (side of [row.live, row.variant]; track $index) {\n <td class=\"number\" [attr.data-label]=\"($index === 0 ? 'nh-assistant.admin.evaluation.columns.live' : 'nh-assistant.admin.evaluation.columns.variant') | translate\">\n @switch (row.key) {\n @case ('runs') { {{ side.runs }} }\n @case ('model-calls') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageModelCalls | number: '1.0-2'), p95: side.p95ModelCalls, total: side.modelCalls } }}\n }\n @case ('tokens') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageTokens | number: '1.0-0'), p95: side.p95Tokens, total: side.tokens } }}\n }\n @case ('tool-calls') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageToolCalls | number: '1.0-2'), p95: side.p95ToolCalls, total: side.toolCalls } }}\n }\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n\n @if (showRouting()) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-routing-title'\">\n <h4 [id]=\"id + '-routing-title'\">{{ 'nh-assistant.admin.evaluation.routing-title' | translate }}</h4>\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-routing-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.live-skill' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.variant-skill' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.runs' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of report.routing; track $index) {\n <tr>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-skill' | translate\">{{ row.liveSkill ?? ('nh-assistant.admin.evaluation.no-skill' | translate) }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.variant-skill' | translate\">{{ row.variantSkill ?? ('nh-assistant.admin.evaluation.no-skill' | translate) }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.runs' | translate\">{{ row.runs }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n }\n\n @if (report.differences.length > 0) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-differences-title'\">\n <h4 [id]=\"id + '-differences-title'\">{{ 'nh-assistant.admin.evaluation.differences-title' | translate }}</h4>\n <ul class=\"cards\">\n @for (difference of report.differences; track difference.liveRunId + difference.variantRunId + $index) {\n <li class=\"card\" [attr.data-difference]=\"difference.kind\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ difference.toolId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.kind.' + difference.kind | translate }}</span>\n @if (difference.liveStatus; as status) {\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.live-status' | translate: { status } }}</span>\n }\n @if (difference.replayed) {\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.replayed' | translate }}</span>\n }\n </div>\n @if (canOpenThreads) {\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"openThread(difference.liveConversationId)\">\n {{ 'nh-assistant.admin.evaluation.open-live' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"openThread(difference.variantConversationId)\">\n {{ 'nh-assistant.admin.evaluation.open-variant' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n </section>\n }\n }\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-replay-title'\">\n <h4 [id]=\"id + '-replay-title'\">{{ 'nh-assistant.admin.evaluation.replay-title' | translate }}</h4>\n <p class=\"muted\" [id]=\"id + '-replay-hint'\">{{ 'nh-assistant.admin.evaluation.replay-hint' | translate: { max: maxReplayRuns } }}</p>\n <div class=\"inline\">\n <div class=\"field\">\n <label [for]=\"id + '-replay-runs'\">{{ 'nh-assistant.admin.evaluation.replay-runs' | translate }}</label>\n <input\n [id]=\"id + '-replay-runs'\"\n type=\"number\"\n min=\"1\"\n [max]=\"maxReplayRuns\"\n [value]=\"replayRuns()\"\n [attr.aria-describedby]=\"id + '-replay-hint'\"\n (change)=\"onReplayRuns($event)\" />\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"replaying() || replayRunning() || !variant()\" (click)=\"replay()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.evaluation.replay' | translate }}\n </button>\n </div>\n @if (replayError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ replayErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (replays().length > 0) {\n <ul class=\"cards\" data-replays>\n @for (item of replays(); track item.id) {\n <li class=\"card\" [attr.data-replay]=\"item.status\">\n <div class=\"card-header\">\n <strong>{{ item.createdAt | date: 'short' }}</strong>\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.replay-status.' + item.status | translate }}</span>\n </div>\n <p class=\"muted\">\n {{ 'nh-assistant.admin.evaluation.replay-progress' | translate: { replayed: item.runsReplayed, skipped: item.runsSkipped, max: item.maxRuns } }}\n </p>\n @if (item.stopReason; as code) {\n <p class=\"muted\">{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</p>\n }\n </li>\n }\n </ul>\n }\n </section>\n</section>\n","import { DatePipe, DOCUMENT, PercentPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AgentFeedbackCategoryCount,\n AgentFeedbackItem,\n AgentFeedbackSummaryRow,\n AgentProposalFeedbackCategory,\n AgentProposalFeedbackGroup,\n NH_ASSISTANT_FEEDBACK_CATEGORIES,\n StaleKind,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Periods the report offers, in days before now. */\nexport type NhAssistantFeedbackPeriod = 7 | 30 | 90;\n\n/** A summary row with its most frequent feedback categories and why open proposals closed. */\ninterface NhAssistantFeedbackSummaryView extends AgentFeedbackSummaryRow {\n topCategories: AgentFeedbackCategoryCount[];\n /** Open proposals closed before a decision, per kind, most frequent first. */\n invalidatedKinds: { kind: StaleKind; count: number; reasons: string }[];\n}\n\nconst dayMs = 24 * 60 * 60 * 1000;\nconst topCategoryCount = 3;\n\nlet nextId = 0;\n\n/**\n * What people said when they rejected an agent's proposals, for the agent's administrators: per\n * tool and agent version the decisions, the rejection rate, the share of rejections with feedback,\n * the number of different people and the most frequent categories, followed by the feedback itself\n * and a JSON Lines export. Comparing agent versions shows whether a change to the prompt, tools or\n * policy helped. The server requires the assistant admin policy and reports only the caller's scopes.\n */\n@Component({\n selector: 'nh-assistant-agent-feedback-report',\n standalone: true,\n imports: [DatePipe, PercentPipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-agent-feedback-report.component.html',\n styleUrls: ['../nh-assistant-admin-shared.scss', './nh-assistant-agent-feedback-report.component.scss']\n})\nexport class NhAssistantAgentFeedbackReportComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly document = inject(DOCUMENT);\n private summarySubscription?: Subscription;\n private listSubscription?: Subscription;\n\n readonly agentId = input.required<string>();\n /** Feedback per page; the server allows at most 100. */\n readonly itemsPerPage = input(20);\n\n readonly id = `nh-assistant-agent-feedback-${nextId++}`;\n readonly periods: readonly NhAssistantFeedbackPeriod[] = [7, 30, 90];\n readonly categories = NH_ASSISTANT_FEEDBACK_CATEGORIES;\n\n readonly period = signal<NhAssistantFeedbackPeriod>(30);\n readonly toolId = signal('');\n readonly category = signal<AgentProposalFeedbackCategory | ''>('');\n readonly page = signal(1);\n\n readonly summaryLoading = signal(true);\n readonly summaryError = signal<NhAssistantError | null>(null);\n readonly summaryErrorKeys = computed(() => nhAssistantErrorKeys(this.summaryError()));\n readonly rows = signal<AgentFeedbackSummaryRow[]>([]);\n\n readonly listLoading = signal(true);\n readonly listError = signal<NhAssistantError | null>(null);\n readonly listErrorKeys = computed(() => nhAssistantErrorKeys(this.listError()));\n readonly items = signal<AgentFeedbackItem[]>([]);\n readonly total = signal(0);\n readonly pages = computed(() => Math.max(1, Math.ceil(this.total() / this.itemsPerPage())));\n\n readonly exporting = signal(false);\n readonly exportError = signal<NhAssistantError | null>(null);\n readonly exportErrorKeys = computed(() => nhAssistantErrorKeys(this.exportError()));\n readonly canExport = computed(() => !this.exporting() && !this.listLoading() && this.listError() === null && this.total() > 0);\n\n /** Tools with proposals in the period, plus the chosen tool when the period has none of it. */\n readonly tools = computed(() => {\n const tools = new Set(this.rows().map(row => row.toolId));\n if (this.toolId()) {\n tools.add(this.toolId());\n }\n return [...tools].sort();\n });\n readonly visibleRows = computed<NhAssistantFeedbackSummaryView[]>(() => this.rows()\n .filter(row => !this.toolId() || row.toolId === this.toolId())\n .map(row => ({\n ...row,\n topCategories: [...row.categories].sort((left, right) => right.count - left.count).slice(0, topCategoryCount),\n invalidatedKinds: invalidatedKinds(row)\n })));\n readonly filtered = computed(() => this.toolId() !== '' || this.category() !== '');\n\n /** The period the last load asked for, so the list, summary and export agree. */\n private range = periodRange(30);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.summarySubscription?.unsubscribe();\n this.listSubscription?.unsubscribe();\n });\n effect(() => {\n this.agentId();\n untracked(() => {\n this.toolId.set('');\n this.category.set('');\n this.load();\n });\n });\n }\n\n /** Reloads the summary and the first page of feedback for the chosen period. */\n load(): void {\n this.range = periodRange(this.period());\n this.page.set(1);\n this.loadSummary();\n this.loadList();\n }\n\n onPeriod(event: Event): void {\n this.period.set(Number((event.target as HTMLSelectElement).value) as NhAssistantFeedbackPeriod);\n this.load();\n }\n\n onTool(event: Event): void {\n this.toolId.set((event.target as HTMLSelectElement).value);\n this.page.set(1);\n this.loadList();\n }\n\n onCategory(event: Event): void {\n this.category.set((event.target as HTMLSelectElement).value as AgentProposalFeedbackCategory | '');\n this.page.set(1);\n this.loadList();\n }\n\n goTo(page: number): void {\n this.page.set(Math.min(Math.max(1, page), this.pages()));\n this.loadList();\n }\n\n loadSummary(): void {\n this.summaryLoading.set(true);\n this.summaryError.set(null);\n this.summarySubscription?.unsubscribe();\n this.summarySubscription = this.admin.getAgentFeedbackSummary(this.agentId(), this.range).subscribe({\n next: summary => {\n this.rows.set(summary.rows);\n this.summaryLoading.set(false);\n },\n error: (failure: unknown) => {\n this.rows.set([]);\n this.summaryLoading.set(false);\n this.summaryError.set(toNhAssistantError(failure));\n }\n });\n }\n\n loadList(): void {\n this.listLoading.set(true);\n this.listError.set(null);\n this.exportError.set(null);\n this.listSubscription?.unsubscribe();\n this.listSubscription = this.admin\n .getAgentFeedback(this.agentId(), {\n ...this.range,\n toolId: this.toolId() || undefined,\n category: this.category() || undefined,\n page: this.page(),\n itemsPerPage: this.itemsPerPage()\n })\n .subscribe({\n next: list => {\n this.items.set(list.items);\n this.total.set(list.total);\n this.listLoading.set(false);\n },\n error: (failure: unknown) => {\n this.items.set([]);\n this.total.set(0);\n this.listLoading.set(false);\n this.listError.set(toNhAssistantError(failure));\n }\n });\n }\n\n /** Downloads the feedback of the period and filters as a JSON Lines file. */\n async export(): Promise<void> {\n if (!this.canExport()) {\n return;\n }\n\n this.exporting.set(true);\n this.exportError.set(null);\n try {\n const blob = await this.admin.exportAgentFeedback(this.agentId(), {\n ...this.range,\n toolId: this.toolId() || undefined,\n category: this.category() || undefined\n });\n const url = URL.createObjectURL(blob);\n const link = this.document.createElement('a');\n link.href = url;\n link.download = `agent-feedback-${this.agentId()}.jsonl`;\n link.click();\n URL.revokeObjectURL(url);\n } catch (failure) {\n this.exportError.set(toNhAssistantError(failure));\n } finally {\n this.exporting.set(false);\n }\n }\n\n /** Badge color of a feedback group: wrong and not allowed are failures, not now is a warning. */\n groupClass(group: AgentProposalFeedbackGroup): string {\n switch (group) {\n case 'wrong':\n case 'not-allowed':\n return 'danger';\n case 'right-but-not-now':\n return 'warning';\n default:\n return '';\n }\n }\n}\n\nfunction periodRange(days: number): { from: string; to: string } {\n const to = Date.now();\n return { from: new Date(to - days * dayMs).toISOString(), to: new Date(to).toISOString() };\n}\n\n/**\n * The open proposals of a row that closed before a decision, per kind, with their reason codes for\n * the tooltip. Proposals that closed after their approval are part of the approved count.\n */\nfunction invalidatedKinds(row: AgentFeedbackSummaryRow): { kind: StaleKind; count: number; reasons: string }[] {\n const kinds = new Map<StaleKind, { count: number; reasons: string[] }>();\n for (const item of row.invalidations ?? []) {\n if (item.afterApproval) {\n continue;\n }\n\n const entry = kinds.get(item.kind) ?? { count: 0, reasons: [] };\n entry.count += item.count;\n entry.reasons.push(`${item.reasonCode} (${item.count})`);\n kinds.set(item.kind, entry);\n }\n\n return [...kinds.entries()]\n .map(([kind, entry]) => ({ kind, count: entry.count, reasons: entry.reasons.join(', ') }))\n .sort((left, right) => right.count - left.count);\n}\n","<section class=\"section report\" [attr.aria-labelledby]=\"id + '-title'\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.feedback.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.description' | translate }}</p>\n <p class=\"muted export-hint\" [id]=\"id + '-export-hint'\">{{ 'nh-assistant.admin.feedback.export-hint' | translate }}</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"summaryLoading() || listLoading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.feedback.refresh' | translate }}\n </button>\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"!canExport()\"\n [attr.aria-describedby]=\"id + '-export-hint'\"\n (click)=\"export()\">\n <nh-assistant-icon name=\"page\" />{{ (exporting() ? 'nh-assistant.admin.feedback.exporting' : 'nh-assistant.admin.feedback.export') | translate }}\n </button>\n </div>\n </header>\n\n <div class=\"filters\">\n <div class=\"field\">\n <label [for]=\"id + '-period'\">{{ 'nh-assistant.admin.feedback.period' | translate }}</label>\n <select [id]=\"id + '-period'\" (change)=\"onPeriod($event)\">\n @for (days of periods; track days) {\n <option [value]=\"days\" [selected]=\"period() === days\">{{ 'nh-assistant.admin.feedback.periods.last-' + days + '-days' | translate }}</option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-tool'\">{{ 'nh-assistant.admin.feedback.tool' | translate }}</label>\n <select [id]=\"id + '-tool'\" [disabled]=\"summaryLoading() && tools().length === 0\" (change)=\"onTool($event)\">\n <option value=\"\" [selected]=\"toolId() === ''\">{{ 'nh-assistant.admin.feedback.all-tools' | translate }}</option>\n @for (tool of tools(); track tool) {\n <option [value]=\"tool\" [selected]=\"toolId() === tool\">{{ tool }}</option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-category'\">{{ 'nh-assistant.admin.feedback.category' | translate }}</label>\n <select [id]=\"id + '-category'\" [attr.aria-describedby]=\"id + '-category-hint'\" (change)=\"onCategory($event)\">\n <option value=\"\" [selected]=\"category() === ''\">{{ 'nh-assistant.admin.feedback.all-categories' | translate }}</option>\n @for (option of categories; track option) {\n <option [value]=\"option\" [selected]=\"category() === option\">{{ 'nh-assistant.proposal-feedback.categories.' + option | translate }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-category-hint'\"><span>{{ 'nh-assistant.admin.feedback.category-hint' | translate }}</span></p>\n </div>\n </div>\n\n @if (exportError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ exportErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-summary-title'\" [attr.aria-busy]=\"summaryLoading()\">\n <h4 [id]=\"id + '-summary-title'\">{{ 'nh-assistant.admin.feedback.summary-title' | translate }}</h4>\n @if (summaryLoading() && rows().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (summaryError(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ summaryErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"loadSummary()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (visibleRows().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.feedback.summary-empty' | translate }}</p>\n } @else {\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-summary-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.tool' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.version' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.approved' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.rejected' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.expired' | translate }}</th>\n <th scope=\"col\" class=\"number\" [attr.title]=\"'nh-assistant.admin.feedback.invalidated-hint' | translate\">\n {{ 'nh-assistant.admin.feedback.columns.invalidated' | translate }}\n </th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.rejection-rate' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.with-feedback' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.people' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.categories' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of visibleRows(); track row.toolId + '|' + row.agentVersion) {\n <tr>\n <th scope=\"row\" class=\"tool\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.tool' | translate\">\n <span class=\"mono\">{{ row.toolId }}</span>\n </th>\n <td [attr.data-label]=\"'nh-assistant.admin.feedback.columns.version' | translate\">\n @if (row.agentVersion === null) {\n {{ 'nh-assistant.admin.feedback.consultations' | translate }}\n } @else {\n {{ 'nh-assistant.admin.feedback.version' | translate: { version: row.agentVersion } }}\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.approved' | translate\">{{ row.approved }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.rejected' | translate\">{{ row.rejected }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.expired' | translate\">{{ row.expired }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.invalidated' | translate\">\n {{ row.invalidated ?? 0 }}\n @if (row.invalidatedKinds.length > 0) {\n <ul class=\"badges\">\n @for (item of row.invalidatedKinds; track item.kind) {\n <li>\n <span class=\"badge\" [attr.title]=\"item.reasons\">\n {{ 'nh-assistant.approval.stale-kind.' + item.kind | translate }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.rejection-rate' | translate\">\n @if (row.rejectionRate === null) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.no-decisions' | translate }}</span>\n } @else {\n {{ row.rejectionRate | percent: '1.0-0' }}\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.with-feedback' | translate\">{{ row.rejectedWithFeedback }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.people' | translate\">{{ row.feedbackAuthors }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.feedback.columns.categories' | translate\">\n @if (row.topCategories.length === 0) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.no-categories' | translate }}</span>\n } @else {\n <ul class=\"badges\">\n @for (item of row.topCategories; track item.category) {\n <li>\n <span [class]=\"'badge ' + groupClass(item.group)\" [attr.title]=\"'nh-assistant.proposal-feedback.groups.' + item.group | translate\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-list-title'\" [attr.aria-busy]=\"listLoading()\">\n <div class=\"list-header\">\n <h4 [id]=\"id + '-list-title'\">{{ 'nh-assistant.admin.feedback.list-title' | translate }}</h4>\n @if (!listLoading() && listError() === null) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.list-count' | translate: { count: total() } }}</span>\n }\n </div>\n @if (listLoading() && items().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (listError(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ listErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"loadList()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (items().length === 0) {\n <p class=\"state\">{{ (filtered() ? 'nh-assistant.admin.feedback.list-empty-filtered' : 'nh-assistant.admin.feedback.list-empty') | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (item of items(); track item.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ item.subjectDisplayName ?? item.subjectId }}</strong>\n <span class=\"muted\">{{ item.presentation?.toolDisplayName ?? item.toolId }}</span>\n @if (item.agentVersion !== null) {\n <span class=\"badge\">{{ 'nh-assistant.admin.feedback.version' | translate: { version: item.agentVersion } }}</span>\n }\n <span [class]=\"'badge ' + groupClass(item.group)\" [attr.title]=\"'nh-assistant.proposal-feedback.groups.' + item.group | translate\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n </span>\n @if (item.bulk) {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.admin.feedback.bulk-hint' | translate\">{{ 'nh-assistant.admin.feedback.bulk' | translate }}</span>\n }\n </div>\n @if (item.text) {\n <blockquote class=\"feedback-text\">{{ item.text }}</blockquote>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.no-text' | translate }}</p>\n }\n <p class=\"proposal\">\n <span class=\"proposal-label\">{{ 'nh-assistant.admin.feedback.proposal' | translate }}</span>\n {{ item.presentation?.summary ?? item.summary }}\n </p>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.proposal.status.' + item.approvalStatus | nhAssistantTranslate: item.approvalStatus }}</span>\n <span>{{ 'nh-assistant.admin.feedback.author' | translate: { actor: item.authorDisplayName || item.authorActorId } }}</span>\n <span>{{ item.updatedAt | date: 'short' }}</span>\n </div>\n </li>\n }\n </ul>\n @if (pages() > 1) {\n <nav class=\"pager\" [attr.aria-label]=\"'nh-assistant.admin.feedback.pages' | translate\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() <= 1 || listLoading()\" (click)=\"goTo(page() - 1)\">\n {{ 'nh-assistant.admin.feedback.previous' | translate }}\n </button>\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.page' | translate: { page: page(), pages: pages() } }}</span>\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() >= pages() || listLoading()\" (click)=\"goTo(page() + 1)\">\n {{ 'nh-assistant.admin.feedback.next' | translate }}\n </button>\n </nav>\n }\n }\n </section>\n</section>\n","import { DatePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n afterNextRender,\n computed,\n inject,\n signal,\n viewChild\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Observable, Subscription, forkJoin } from 'rxjs';\nimport {\n AdminAgent,\n AgentShadowMode,\n AgentShadowState,\n AgentSkillState,\n AgentState,\n McpServer,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n NhAssistantStore,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError,\n SetAgentStateRequest,\n ToolCatalogEntry\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminAgentEditorComponent } from './nh-assistant-admin-agent-editor.component';\nimport { NhAssistantAgentEvaluationComponent } from './nh-assistant-agent-evaluation.component';\nimport { NhAssistantAgentFeedbackReportComponent } from './nh-assistant-agent-feedback-report.component';\n\nlet nextId = 0;\n\ntype AgentStateAction = SetAgentStateRequest['state'];\n\n/** The longest reason the server stores with a state change. */\nconst maxStateReason = 500;\n\n/**\n * Agent administration: code agents (override, reset) and agents created here (edit, delete),\n * and for every agent its run state with pause, stop and resume, its shadow mode and that of each\n * skill, and the technical account of an agent that answers to one, each with an optional reason.\n * Editing opens `nh-assistant-admin-agent-editor`; the feedback action opens\n * `nh-assistant-agent-feedback-report` for the agent, and the evaluation action of an agent with\n * shadow variants opens `nh-assistant-agent-evaluation`.\n */\n@Component({\n selector: 'nh-assistant-admin-agents',\n standalone: true,\n imports: [\n DatePipe,\n TranslatePipe,\n NhAssistantTranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminAgentEditorComponent,\n NhAssistantAgentEvaluationComponent,\n NhAssistantAgentFeedbackReportComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-agents.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminAgentsComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly store = inject(NhAssistantStore);\n private readonly injector = inject(Injector);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly backButton = viewChild<ElementRef<HTMLButtonElement>>('back');\n private readonly reasonInput = viewChild<ElementRef<HTMLInputElement>>('reasonInput');\n private subscription?: Subscription;\n private actionSubscription?: Subscription;\n\n readonly id = `nh-assistant-admin-agents-${nextId++}`;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly agents = signal<AdminAgent[]>([]);\n readonly tools = signal<ToolCatalogEntry[]>([]);\n readonly servers = signal<McpServer[]>([]);\n /** `undefined`: list; `null`: new agent; an agent: editing that agent. */\n readonly editing = signal<AdminAgent | null | undefined>(undefined);\n /** The agent whose feedback report is shown instead of the list. */\n readonly reporting = signal<AdminAgent | null>(null);\n /** The agent whose comparison with its shadow variants is shown instead of the list. */\n readonly evaluating = signal<AdminAgent | null>(null);\n readonly confirming = signal<{ agentId: string; action: 'delete' | 'reset' } | null>(null);\n readonly busyAgentId = signal<string | null>(null);\n /** The state change whose reason is being entered, of the agent or one of its skills. */\n readonly changingState = signal<{ agentId: string; skillId?: string; state: AgentStateAction } | null>(null);\n /** The shadow mode change whose reason is being entered, of the agent or one of its skills. */\n readonly changingShadow = signal<{ agentId: string; skillId?: string; mode: AgentShadowMode } | null>(null);\n /** The change of the technical account being entered: a new account, or the one in code. */\n readonly changingAccount = signal<{ agentId: string; mode: 'set' | 'code' } | null>(null);\n readonly accountId = signal('');\n readonly stateReason = signal('');\n readonly maxReason = maxStateReason;\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.actionSubscription?.unsubscribe();\n });\n this.load();\n }\n\n load(): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = forkJoin([this.admin.getAgents(), this.admin.getTools(), this.admin.getMcpServers()]).subscribe({\n next: ([agents, tools, servers]) => {\n this.agents.set(agents);\n this.tools.set(tools);\n this.servers.set(servers);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n create(): void {\n this.error.set(null);\n this.editing.set(null);\n }\n\n edit(agent: AdminAgent): void {\n this.error.set(null);\n this.editing.set(agent);\n }\n\n /** Shows what people said when they rejected the agent's proposals. */\n openReport(agent: AdminAgent): void {\n this.error.set(null);\n this.confirming.set(null);\n this.reporting.set(agent);\n afterNextRender(() => this.backButton()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /** The shadow variants of an agent, by id. */\n variantsOf(agent: AdminAgent): string[] {\n return this.agents()\n .filter(item => item.shadowOf === agent.id)\n .map(item => item.id);\n }\n\n /** Compares the agent with its shadow variants. */\n openEvaluation(agent: AdminAgent): void {\n this.error.set(null);\n this.confirming.set(null);\n this.evaluating.set(agent);\n afterNextRender(() => this.backButton()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /** Returns to the list and to the evaluation action of the agent whose comparison was open. */\n closeEvaluation(): void {\n const agentId = this.evaluating()?.id;\n this.evaluating.set(null);\n if (agentId !== undefined) {\n afterNextRender(() => {\n const action = Array.from(this.host.nativeElement.querySelectorAll<HTMLButtonElement>('[data-evaluation-agent]'))\n .find(item => item.dataset['evaluationAgent'] === agentId);\n action?.focus();\n }, { injector: this.injector });\n }\n }\n\n /** Returns to the list and to the feedback action of the agent whose report was open. */\n closeReport(): void {\n const agentId = this.reporting()?.id;\n this.reporting.set(null);\n if (agentId !== undefined) {\n afterNextRender(() => {\n const host = this.host.nativeElement;\n const action = Array.from(host.querySelectorAll<HTMLButtonElement>('[data-feedback-agent]'))\n .find(item => item.dataset['feedbackAgent'] === agentId);\n action?.focus();\n }, { injector: this.injector });\n }\n }\n\n onSaved(agent: AdminAgent): void {\n this.agents.update(agents => agents.some(item => item.id === agent.id)\n ? agents.map(item => item.id === agent.id ? agent : item)\n : [...agents, agent]);\n this.editing.set(undefined);\n this.refreshChat();\n }\n\n /** The state changes the agent allows: none for an agent that is disabled in code. */\n stateActions(agent: AdminAgent): AgentStateAction[] {\n switch (agent.runState) {\n case 'active':\n return ['paused', 'stopped'];\n case 'paused':\n return ['active', 'stopped'];\n case 'stopped':\n return ['active'];\n default:\n return [];\n }\n }\n\n /** The state changes a skill allows. */\n skillActions(skill: AgentSkillState): AgentStateAction[] {\n switch (skill.runState) {\n case 'active':\n return ['paused', 'stopped'];\n case 'paused':\n return ['active', 'stopped'];\n default:\n return ['active'];\n }\n }\n\n /** Opens the reason form of a state change of the agent or, with a skill, of that skill. */\n askState(agent: AdminAgent, state: AgentStateAction, skill?: AgentSkillState): void {\n this.closeForms();\n this.changingState.set({ agentId: agent.id, skillId: skill?.skillId, state });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /**\n * The shadow modes an agent or skill can change to: the opposite of its own mode, and the mode\n * in code once an administrator overrode it. A shadow variant, and an agent without runs that\n * only chats, offer none.\n */\n shadowActions(shadow: AgentShadowState | null | undefined): AgentShadowMode[] {\n if (!shadow || shadow.locked) {\n return [];\n }\n const own = shadow.override ?? shadow.configured;\n const actions: AgentShadowMode[] = [own ? 'live' : 'shadow'];\n return shadow.override === null ? actions : [...actions, 'code'];\n }\n\n /** Opens the reason form of a shadow mode change of the agent or, with a skill, of that skill. */\n askShadow(agent: AdminAgent, mode: AgentShadowMode, skill?: AgentSkillState): void {\n this.closeForms();\n this.changingShadow.set({ agentId: agent.id, skillId: skill?.skillId, mode });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n isChangingShadow(agentId: string, mode: AgentShadowMode, skillId?: string): boolean {\n const change = this.changingShadow();\n return change?.agentId === agentId && change.mode === mode && change.skillId === skillId;\n }\n\n applyShadow(agent: AdminAgent): void {\n const change = this.changingShadow();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const reason = this.stateReason().trim();\n const request = { mode: change.mode, reason: reason.length > 0 ? reason : null };\n if (change.skillId !== undefined) {\n this.run(\n agent.id,\n this.admin.setSkillShadow(agent.id, change.skillId, request),\n skill => this.replace(withSkill(agent, skill)));\n return;\n }\n\n this.run(\n agent.id,\n this.admin.setAgentShadow(agent.id, request),\n state => this.replace(withState(agent, state)));\n }\n\n /** Opens the form that changes the technical account, or returns to the one in code. */\n askAccount(agent: AdminAgent, mode: 'set' | 'code'): void {\n this.closeForms();\n this.changingAccount.set({ agentId: agent.id, mode });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n isChangingAccount(agentId: string, mode: 'set' | 'code'): boolean {\n const change = this.changingAccount();\n return change?.agentId === agentId && change.mode === mode;\n }\n\n applyAccount(agent: AdminAgent): void {\n const change = this.changingAccount();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const actorId = change.mode === 'set' ? this.accountId().trim() : null;\n if (actorId === '') {\n return;\n }\n const reason = this.stateReason().trim();\n this.run(\n agent.id,\n this.admin.setServiceAccount(agent.id, { actorId, reason: reason.length > 0 ? reason : null }),\n state => this.replace(withState(agent, state)));\n }\n\n isChangingState(agentId: string, state: AgentStateAction, skillId?: string): boolean {\n const change = this.changingState();\n return change?.agentId === agentId && change.state === state && change.skillId === skillId;\n }\n\n applyState(agent: AdminAgent): void {\n const change = this.changingState();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const reason = this.stateReason().trim();\n const request = { state: change.state, reason: reason.length > 0 ? reason : null };\n if (change.skillId !== undefined) {\n this.run(\n agent.id,\n this.admin.setSkillState(agent.id, change.skillId, request),\n skill => this.replace(withSkill(agent, skill)));\n return;\n }\n\n this.run(\n agent.id,\n this.admin.setAgentState(agent.id, request),\n state => this.replace(withState(agent, state)));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n\n confirm(agentId: string, action: 'delete' | 'reset'): void {\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n this.confirming.set({ agentId, action });\n }\n\n isConfirming(agentId: string, action: 'delete' | 'reset'): boolean {\n const confirming = this.confirming();\n return confirming?.agentId === agentId && confirming.action === action;\n }\n\n reset(agent: AdminAgent): void {\n this.run(agent.id, this.admin.resetAgent(agent.id), updated => this.replace(updated));\n }\n\n remove(agent: AdminAgent): void {\n this.run<void>(agent.id, this.admin.deleteAgent(agent.id), () => {\n this.agents.update(agents => agents.filter(item => item.id !== agent.id));\n });\n }\n\n private run<T>(agentId: string, request: Observable<T>, done: (result: T) => void): void {\n this.busyAgentId.set(agentId);\n this.confirming.set(null);\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n this.error.set(null);\n this.actionSubscription?.unsubscribe();\n this.actionSubscription = request.subscribe({\n next: result => done(result),\n complete: () => {\n this.busyAgentId.set(null);\n this.refreshChat();\n },\n error: (error: unknown) => {\n this.busyAgentId.set(null);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n /** Closes the open confirmation and change forms before another opens; one is open at a time. */\n private closeForms(): void {\n this.confirming.set(null);\n this.error.set(null);\n this.stateReason.set('');\n this.accountId.set('');\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n }\n\n private replace(agent: AdminAgent): void {\n this.agents.update(agents => agents.map(item => item.id === agent.id ? agent : item));\n }\n\n /** Agent changes affect the agent picker of the panel. */\n private refreshChat(): void {\n void this.store.reloadStatus();\n }\n}\n\nfunction withState(agent: AdminAgent, state: AgentState): AdminAgent {\n return {\n ...agent,\n isEnabled: state.runState !== 'stopped',\n runState: state.runState,\n stateChangedAt: state.changedAt,\n stateChangedBy: state.changedBy,\n stateReason: state.reason,\n waitingInputs: state.waitingInputs,\n skills: state.skills ?? agent.skills,\n shadow: state.shadow ?? agent.shadow,\n serviceAccount: state.serviceAccount === undefined ? agent.serviceAccount : state.serviceAccount\n };\n}\n\nfunction withSkill(agent: AdminAgent, skill: AgentSkillState): AdminAgent {\n return {\n ...agent,\n skills: (agent.skills ?? []).map(item => item.skillId === skill.skillId ? skill : item)\n };\n}\n","@if (editing() !== undefined) {\n <nh-assistant-admin-agent-editor\n [agent]=\"editing() ?? null\"\n [tools]=\"tools()\"\n [servers]=\"servers()\"\n (saved)=\"onSaved($event)\"\n (cancelled)=\"editing.set(undefined)\" />\n} @else if (reporting(); as agent) {\n <div class=\"stack\">\n <div>\n <button #back class=\"secondary\" type=\"button\" (click)=\"closeReport()\">\n {{ 'nh-assistant.admin.feedback.back' | translate }}\n </button>\n </div>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.agent' | translate: { name: agent.displayName, id: agent.id } }}</p>\n <nh-assistant-agent-feedback-report [agentId]=\"agent.id\" />\n </div>\n} @else if (evaluating(); as agent) {\n <div class=\"stack\">\n <div>\n <button #back class=\"secondary\" type=\"button\" (click)=\"closeEvaluation()\">\n {{ 'nh-assistant.admin.evaluation.back' | translate }}\n </button>\n </div>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.agent' | translate: { name: agent.displayName, id: agent.id } }}</p>\n <nh-assistant-agent-evaluation [agentId]=\"agent.id\" [variants]=\"variantsOf(agent)\" />\n </div>\n} @else {\n <section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.agents.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.description' | translate }}</p>\n </div>\n <button class=\"primary\" type=\"button\" [disabled]=\"loading() || loadFailed()\" (click)=\"create()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.agents.new' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (agents().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.agents.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (agent of agents(); track agent.id) {\n <li class=\"card\" [class.inactive]=\"agent.runState !== 'active'\" [attr.aria-busy]=\"busyAgentId() === agent.id\">\n <div class=\"card-header\">\n <strong>{{ agent.displayName }}</strong>\n <span class=\"mono muted\">{{ agent.id }}</span>\n <span class=\"badge\">{{ (agent.source === 'code' ? 'nh-assistant.admin.agents.source-code' : 'nh-assistant.admin.agents.source-admin') | translate }}</span>\n @if (agent.isOverridden) {\n <span class=\"badge warning\">{{ 'nh-assistant.admin.agents.overridden' | translate }}</span>\n }\n <span\n class=\"badge\"\n [class.success]=\"agent.runState === 'active'\"\n [class.warning]=\"agent.runState === 'paused'\"\n [class.danger]=\"agent.runState === 'stopped'\">{{ 'nh-assistant.admin.agents.state.' + agent.runState | translate }}</span>\n @if (agent.shadow?.shadow) {\n <span class=\"badge warning\" data-shadow-badge>{{ 'nh-assistant.admin.agents.shadow.badge' | translate }}</span>\n }\n </div>\n @if (agent.description) {\n <p class=\"muted\">{{ agent.description }}</p>\n }\n @if (agent.runState === 'configured-off') {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.configured-off-hint' | translate }}</p>\n } @else if (agent.runState !== 'active') {\n <p class=\"muted\">\n @if (agent.stateChangedAt) {\n {{ 'nh-assistant.admin.agents.state.changed' | translate: { user: agent.stateChangedBy, date: (agent.stateChangedAt | date: 'medium') } }}\n }\n @if (agent.stateReason) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: agent.stateReason } }}\n }\n </p>\n @if (agent.runState === 'paused') {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.waiting' | translate: { count: agent.waitingInputs } }}</p>\n }\n }\n @if (agent.shadow; as shadow) {\n @if (shadow.shadow) {\n <p class=\"muted\">\n {{ (shadow.locked ? 'nh-assistant.admin.agents.shadow.locked' : 'nh-assistant.admin.agents.shadow.hint') | translate }}\n @if (shadow.changedAt && shadow.override !== null) {\n {{ 'nh-assistant.admin.agents.shadow.changed' | translate: { user: shadow.changedBy, date: (shadow.changedAt | date: 'medium') } }}\n }\n @if (shadow.reason && shadow.override !== null) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: shadow.reason } }}\n }\n </p>\n }\n }\n @if (agent.serviceAccount; as account) {\n <p class=\"muted\" data-service-account>\n <span class=\"mono\">{{ 'nh-assistant.admin.agents.service-account.label' | translate: { account: account.actorId } }}</span>\n @if (account.overridden) {\n {{ 'nh-assistant.admin.agents.service-account.configured' | translate: { account: account.configuredActorId } }}\n @if (account.reason) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: account.reason } }}\n }\n }\n </p>\n }\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.agents.autonomy.' + agent.autonomy | translate }}</span>\n <span>{{ 'nh-assistant.admin.agents.tool-count' | translate: { count: agent.toolSelectors.length } }}</span>\n <span>{{ 'nh-assistant.admin.agents.server-count' | translate: { count: agent.mcpServerIds.length } }}</span>\n <span>{{ 'nh-assistant.admin.agents.version' | translate: { version: agent.version } }}</span>\n @if (agent.requiredPolicy) {\n <span class=\"mono\">{{ agent.requiredPolicy }}</span>\n }\n </div>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"edit(agent)\">\n <nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}\n </button>\n @for (action of stateActions(agent); track action) {\n <button\n type=\"button\"\n [class.secondary]=\"action !== 'stopped'\"\n [class.danger]=\"action === 'stopped'\"\n [attr.aria-expanded]=\"isChangingState(agent.id, action)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askState(agent, action)\">\n {{ 'nh-assistant.admin.agents.state.action.' + action | translate }}\n </button>\n }\n @if (agent.runState !== 'configured-off') {\n @for (mode of shadowActions(agent.shadow); track mode) {\n <button\n class=\"secondary\"\n type=\"button\"\n [attr.data-shadow-action]=\"mode\"\n [attr.aria-expanded]=\"isChangingShadow(agent.id, mode)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askShadow(agent, mode)\">\n {{ 'nh-assistant.admin.agents.shadow.action.' + mode | translate }}\n </button>\n }\n }\n @if (agent.serviceAccount; as account) {\n <button\n class=\"secondary\"\n type=\"button\"\n data-account-action=\"set\"\n [attr.aria-expanded]=\"isChangingAccount(agent.id, 'set')\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askAccount(agent, 'set')\">\n {{ 'nh-assistant.admin.agents.service-account.action.set' | translate }}\n </button>\n @if (account.overridden) {\n <button\n class=\"secondary\"\n type=\"button\"\n data-account-action=\"code\"\n [attr.aria-expanded]=\"isChangingAccount(agent.id, 'code')\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askAccount(agent, 'code')\">\n {{ 'nh-assistant.admin.agents.service-account.action.code' | translate }}\n </button>\n }\n }\n <button class=\"secondary\" type=\"button\" [attr.data-feedback-agent]=\"agent.id\" (click)=\"openReport(agent)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.agents.feedback' | translate }}\n </button>\n @if (variantsOf(agent).length > 0) {\n <button class=\"secondary\" type=\"button\" [attr.data-evaluation-agent]=\"agent.id\" (click)=\"openEvaluation(agent)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.agents.evaluation' | translate }}\n </button>\n }\n @if (agent.source === 'code' && agent.isOverridden) {\n @if (isConfirming(agent.id, 'reset')) {\n <span class=\"muted\">{{ 'nh-assistant.admin.agents.reset-keeps-state' | translate }}</span>\n <button class=\"danger\" type=\"button\" (click)=\"reset(agent)\">{{ 'nh-assistant.admin.agents.confirm-reset' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"confirm(agent.id, 'reset')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.agents.reset' | translate }}\n </button>\n }\n }\n @if (agent.source === 'admin') {\n @if (isConfirming(agent.id, 'delete')) {\n <button class=\"danger\" type=\"button\" (click)=\"remove(agent)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"confirm(agent.id, 'delete')\">\n <nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}\n </button>\n }\n }\n </div>\n @if (agent.skills?.length) {\n <ul class=\"skills\" [attr.aria-label]=\"'nh-assistant.admin.agents.skills.title' | translate\">\n @for (skill of agent.skills; track skill.skillId) {\n <li class=\"skill\" [attr.data-skill]=\"skill.skillId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ skill.skillId }}</span>\n <span\n class=\"badge\"\n [class.success]=\"skill.runState === 'active'\"\n [class.warning]=\"skill.runState === 'paused'\"\n [class.danger]=\"skill.runState === 'stopped'\">{{ 'nh-assistant.admin.agents.state.' + skill.runState | translate }}</span>\n @if (skill.shadow?.shadow) {\n <span class=\"badge warning\" data-shadow-badge>{{ 'nh-assistant.admin.agents.shadow.badge' | translate }}</span>\n }\n </div>\n <p class=\"muted\">{{ skill.description }}</p>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.agents.skills.usage' | translate: { calls: skill.toolCallsToday, tokens: skill.tokensToday } }}</span>\n @if (skill.dailyToolCalls !== null) {\n <span>{{ 'nh-assistant.admin.agents.skills.budget' | translate: { calls: skill.dailyToolCalls, tokens: skill.dailyTokens } }}</span>\n }\n @if (skill.runState === 'paused') {\n <span>{{ 'nh-assistant.admin.agents.state.waiting' | translate: { count: skill.waitingInputs } }}</span>\n }\n @if (skill.reason) {\n <span>{{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: skill.reason } }}</span>\n }\n </div>\n @if (agent.runState !== 'configured-off') {\n <div class=\"card-actions\">\n @for (action of skillActions(skill); track action) {\n <button\n type=\"button\"\n [class.secondary]=\"action !== 'stopped'\"\n [class.danger]=\"action === 'stopped'\"\n [attr.aria-label]=\"('nh-assistant.admin.agents.state.action.' + action | translate) + ' ' + skill.skillId\"\n [attr.aria-expanded]=\"isChangingState(agent.id, action, skill.skillId)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askState(agent, action, skill)\">\n {{ 'nh-assistant.admin.agents.state.action.' + action | translate }}\n </button>\n }\n @for (mode of shadowActions(skill.shadow); track mode) {\n <button\n class=\"secondary\"\n type=\"button\"\n [attr.data-shadow-action]=\"mode\"\n [attr.aria-label]=\"('nh-assistant.admin.agents.shadow.action.' + mode | translate) + ' ' + skill.skillId\"\n [attr.aria-expanded]=\"isChangingShadow(agent.id, mode, skill.skillId)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askShadow(agent, mode, skill)\">\n {{ 'nh-assistant.admin.agents.shadow.action.' + mode | translate }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n @if (changingState(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" (submit)=\"$event.preventDefault(); applyState(agent)\">\n @if (change.skillId) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.skills.explain.' + change.state | translate: { skill: change.skillId } }}</p>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.explain.' + change.state | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" [class.primary]=\"change.state !== 'stopped'\" [class.danger]=\"change.state === 'stopped'\" [disabled]=\"busyAgentId() !== null\">\n {{ 'nh-assistant.admin.agents.state.confirm.' + change.state | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingState.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n @if (changingShadow(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" data-shadow-form (submit)=\"$event.preventDefault(); applyShadow(agent)\">\n @if (change.skillId) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.shadow.skill-explain.' + change.mode | translate: { skill: change.skillId } }}</p>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.shadow.explain.' + change.mode | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-shadow-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-shadow-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" class=\"primary\" [disabled]=\"busyAgentId() !== null\">\n {{ 'nh-assistant.admin.agents.shadow.confirm.' + change.mode | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingShadow.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n @if (changingAccount(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" data-account-form (submit)=\"$event.preventDefault(); applyAccount(agent)\">\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.service-account.explain.' + change.mode | translate: { account: agent.serviceAccount?.configuredActorId } }}</p>\n @if (change.mode === 'set') {\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-account'\">{{ 'nh-assistant.admin.agents.service-account.input-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n required\n [id]=\"id + '-' + agent.id + '-account'\"\n maxLength=\"256\"\n [value]=\"accountId()\"\n (input)=\"accountId.set(value($event))\" />\n </div>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-account-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-account-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" class=\"primary\" [disabled]=\"busyAgentId() !== null || (change.mode === 'set' && accountId().trim() === '')\">\n {{ 'nh-assistant.admin.agents.service-account.confirm.' + change.mode | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingAccount.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n </li>\n }\n </ul>\n }\n </section>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpAuthMode,\n McpServer,\n McpServerInput,\n ɵNH_ASSISTANT_DASH_CASE as NH_ASSISTANT_DASH_CASE,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/**\n * What happens to the stored secret on save. `keep` omits `secret`, `replace` sends the\n * new value and `clear` sends `\"\"`. The stored value is never shown.\n */\nexport type NhAssistantSecretAction = 'keep' | 'replace' | 'clear';\n\nlet nextId = 0;\n\n/** Creates or edits one MCP server with a write-only secret. */\n@Component({\n selector: 'nh-assistant-admin-mcp-server-editor',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-server-editor.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpServerEditorComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n /** The server to edit, or null for a new server. */\n readonly server = input<McpServer | null>(null);\n readonly saved = output<McpServer>();\n readonly cancelled = output<void>();\n\n readonly id = `nh-assistant-server-editor-${nextId++}`;\n readonly authModes: readonly McpAuthMode[] = ['none', 'bearer', 'api-key', 'forward-user-token'];\n\n readonly serverId = signal('');\n readonly displayName = signal('');\n readonly url = signal('');\n readonly authMode = signal<McpAuthMode>('none');\n readonly headerName = signal('');\n readonly requiredPolicy = signal('');\n readonly isEnabled = signal(true);\n readonly secretAction = signal<NhAssistantSecretAction>('keep');\n /** The new secret while typing. Never filled from the server. */\n readonly secret = signal('');\n readonly submitted = signal(false);\n readonly saving = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n\n readonly isNew = computed(() => this.server() === null);\n readonly hasSecret = computed(() => this.server()?.hasSecret === true);\n readonly usesSecret = computed(() => this.authMode() === 'bearer' || this.authMode() === 'api-key');\n readonly showSecretInput = computed(() => this.usesSecret() && (!this.hasSecret() || this.secretAction() === 'replace'));\n readonly idInvalid = computed(() => this.isNew() && (this.serverId().length > 40 || !NH_ASSISTANT_DASH_CASE.test(this.serverId())));\n readonly nameMissing = computed(() => this.displayName().trim().length === 0);\n readonly urlInvalid = computed(() => !isAllowedUrl(this.url().trim()));\n readonly valid = computed(() => !this.idInvalid() && !this.nameMissing() && !this.urlInvalid());\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n\n effect(() => {\n const server = this.server();\n untracked(() => this.reset(server));\n });\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n setSecretAction(action: NhAssistantSecretAction): void {\n this.secretAction.set(action);\n this.secret.set('');\n }\n\n onSecretInput(event: Event): void {\n this.secret.set(this.value(event));\n if (!this.hasSecret()) {\n this.secretAction.set(this.secret().length > 0 ? 'replace' : 'keep');\n }\n }\n\n save(): void {\n this.submitted.set(true);\n if (!this.valid() || this.saving()) {\n return;\n }\n\n const authMode = this.authMode();\n const policy = this.requiredPolicy().trim();\n const header = this.headerName().trim();\n const input: McpServerInput = {\n id: this.isNew() ? this.serverId() : this.server()!.id,\n displayName: this.displayName().trim(),\n url: this.url().trim(),\n authMode,\n headerName: authMode === 'api-key' && header.length > 0 ? header : null,\n requiredPolicy: policy.length > 0 ? policy : null,\n isEnabled: this.isEnabled()\n };\n\n // Write-only secret: omitted keeps the stored value, \"\" clears it.\n const action = this.secretAction();\n if (!this.usesSecret() && this.hasSecret()) {\n input.secret = '';\n } else if (action === 'clear') {\n input.secret = '';\n } else if (action === 'replace' && this.secret().length > 0) {\n input.secret = this.secret();\n }\n\n const existing = this.server();\n const request = existing ? this.admin.updateMcpServer(existing.id, input) : this.admin.createMcpServer(input);\n\n this.saving.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = request.subscribe({\n next: server => {\n this.saving.set(false);\n this.secret.set('');\n this.saved.emit(server);\n },\n error: (error: unknown) => {\n this.saving.set(false);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private reset(server: McpServer | null): void {\n this.serverId.set(server?.id ?? '');\n this.displayName.set(server?.displayName ?? '');\n this.url.set(server?.url ?? 'https://');\n this.authMode.set(server?.authMode ?? 'none');\n this.headerName.set(server?.headerName ?? '');\n this.requiredPolicy.set(server?.requiredPolicy ?? '');\n this.isEnabled.set(server?.isEnabled ?? true);\n this.secretAction.set('keep');\n this.secret.set('');\n this.submitted.set(false);\n this.error.set(null);\n }\n}\n\nfunction isAllowedUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || (url.protocol === 'http:' && url.hostname === 'localhost');\n } catch {\n return false;\n }\n}\n","<form class=\"section card\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"saving()\" autocomplete=\"off\" (submit)=\"$event.preventDefault(); save()\">\n <h3 [id]=\"id + '-title'\">\n @if (server(); as current) {\n {{ 'nh-assistant.admin.server-editor.edit-title' | translate: { name: current.displayName } }}\n } @else {\n {{ 'nh-assistant.admin.server-editor.new-title' | translate }}\n }\n </h3>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-id'\">{{ 'nh-assistant.admin.server-editor.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n [id]=\"id + '-id'\"\n [value]=\"serverId()\"\n [disabled]=\"!isNew()\"\n [attr.aria-describedby]=\"id + '-id-hint'\"\n [attr.aria-invalid]=\"submitted() && idInvalid() ? true : null\"\n (input)=\"serverId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-id-hint'\">\n <span [class.error-text]=\"submitted() && idInvalid()\">\n {{ (submitted() && idInvalid() ? 'nh-assistant.admin.invalid-id' : 'nh-assistant.admin.server-editor.id-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-name'\">{{ 'nh-assistant.admin.server-editor.display-name' | translate }}</label>\n <input\n type=\"text\"\n [id]=\"id + '-name'\"\n [value]=\"displayName()\"\n [attr.aria-invalid]=\"submitted() && nameMissing() ? true : null\"\n [attr.aria-describedby]=\"id + '-name-hint'\"\n (input)=\"displayName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-name-hint'\">\n @if (submitted() && nameMissing()) {\n <span class=\"error-text\">{{ 'nh-assistant.admin.required' | translate }}</span>\n }\n </p>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-url'\">{{ 'nh-assistant.admin.server-editor.url' | translate }}</label>\n <input\n type=\"url\"\n class=\"mono\"\n inputmode=\"url\"\n [id]=\"id + '-url'\"\n [value]=\"url()\"\n [attr.aria-describedby]=\"id + '-url-hint'\"\n [attr.aria-invalid]=\"submitted() && urlInvalid() ? true : null\"\n (input)=\"url.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-url-hint'\">\n <span [class.error-text]=\"submitted() && urlInvalid()\">\n {{ (submitted() && urlInvalid() ? 'nh-assistant.admin.server-editor.url-invalid' : 'nh-assistant.admin.server-editor.url-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-auth'\">{{ 'nh-assistant.admin.server-editor.auth-mode' | translate }}</label>\n <select [id]=\"id + '-auth'\" (change)=\"authMode.set($any(value($event)))\">\n @for (mode of authModes; track mode) {\n <option [value]=\"mode\" [selected]=\"authMode() === mode\">{{ 'nh-assistant.admin.mcp.auth.' + mode | translate }}</option>\n }\n </select>\n </div>\n\n @if (authMode() === 'api-key') {\n <div class=\"field\">\n <label [for]=\"id + '-header'\">{{ 'nh-assistant.admin.server-editor.header-name' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n placeholder=\"X-Api-Key\"\n [id]=\"id + '-header'\"\n [value]=\"headerName()\"\n [attr.aria-describedby]=\"id + '-header-hint'\"\n (input)=\"headerName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-header-hint'\">{{ 'nh-assistant.admin.server-editor.header-name-hint' | translate }}</p>\n </div>\n }\n </div>\n\n @if (authMode() === 'forward-user-token') {\n <p class=\"message warning\" role=\"note\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.server-editor.forward-warning' | translate }}</p>\n }\n\n @if (usesSecret()) {\n <fieldset class=\"field\">\n <legend>{{ 'nh-assistant.admin.server-editor.secret' | translate }}</legend>\n @if (hasSecret()) {\n <div class=\"meta secret-state\">\n @switch (secretAction()) {\n @case ('clear') {\n <span class=\"badge warning\">{{ 'nh-assistant.admin.server-editor.secret-will-clear' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('keep')\">{{ 'nh-assistant.admin.server-editor.secret-undo' | translate }}</button>\n }\n @case ('replace') {\n <span class=\"badge\">{{ 'nh-assistant.admin.server-editor.secret-set' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('keep')\">{{ 'nh-assistant.admin.server-editor.secret-undo' | translate }}</button>\n }\n @default {\n <span class=\"badge success\">{{ 'nh-assistant.admin.server-editor.secret-set' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('replace')\">{{ 'nh-assistant.admin.server-editor.secret-replace' | translate }}</button>\n <button class=\"danger\" type=\"button\" (click)=\"setSecretAction('clear')\">{{ 'nh-assistant.admin.server-editor.secret-clear' | translate }}</button>\n }\n }\n </div>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.server-editor.secret-none' | translate }}</p>\n }\n @if (showSecretInput()) {\n <label class=\"visually-hidden\" [for]=\"id + '-secret'\">{{ 'nh-assistant.admin.server-editor.secret-new' | translate }}</label>\n <input\n type=\"password\"\n class=\"mono\"\n autocomplete=\"new-password\"\n spellcheck=\"false\"\n [id]=\"id + '-secret'\"\n [attr.placeholder]=\"'nh-assistant.admin.server-editor.secret-new' | translate\"\n [attr.aria-describedby]=\"id + '-secret-hint'\"\n [value]=\"secret()\"\n (input)=\"onSecretInput($event)\" />\n }\n <p class=\"hint\" [id]=\"id + '-secret-hint'\">{{ 'nh-assistant.admin.server-editor.secret-hint' | translate }}</p>\n </fieldset>\n }\n\n <div class=\"field\">\n <label [for]=\"id + '-policy'\">{{ 'nh-assistant.admin.server-editor.required-policy' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n [id]=\"id + '-policy'\"\n [value]=\"requiredPolicy()\"\n [attr.aria-describedby]=\"id + '-policy-hint'\"\n (input)=\"requiredPolicy.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-policy-hint'\">{{ 'nh-assistant.admin.server-editor.required-policy-hint' | translate }}</p>\n </div>\n\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"isEnabled()\" (change)=\"isEnabled.set(checked($event))\" />\n <span>{{ 'nh-assistant.admin.server-editor.enabled' | translate }}</span>\n </label>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancelled.emit()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"saving()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n</form>\n","import { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, output, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpServer,\n McpTool,\n McpToolEffect,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Unsaved changes of one tool row. */\ninterface ToolDraft {\n isEnabled: boolean;\n effect: McpToolEffect;\n descriptionOverride: string;\n}\n\nlet nextId = 0;\n\n/**\n * The tools of one MCP server. Every tool starts disabled as a change that needs approval;\n * the administrator enables it and chooses the effect. Remote annotations appear as hints\n * only, and a changed remote input schema is shown as a warning.\n */\n@Component({\n selector: 'nh-assistant-admin-mcp-tools',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-tools.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpToolsComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n private rowSubscription?: Subscription;\n\n readonly server = input.required<McpServer>();\n readonly closed = output<void>();\n /** Emitted after a sync so the host can refresh the server's sync status. */\n readonly synced = output<void>();\n\n readonly id = `nh-assistant-mcp-tools-${nextId++}`;\n readonly effects: readonly McpToolEffect[] = ['mutation', 'read-only'];\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly syncing = signal(false);\n readonly savingTool = signal<string | null>(null);\n readonly savedTool = signal<string | null>(null);\n readonly tools = signal<McpTool[]>([]);\n readonly drafts = signal<Record<string, ToolDraft>>({});\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.rowSubscription?.unsubscribe();\n });\n\n effect(() => {\n const server = this.server();\n untracked(() => this.load(server.id));\n });\n }\n\n load(serverId = this.server().id): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.getMcpTools(serverId).subscribe({\n next: tools => {\n this.setTools(tools);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n sync(): void {\n this.syncing.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.syncMcpServer(this.server().id).subscribe({\n next: tools => {\n this.setTools(tools);\n this.syncing.set(false);\n this.synced.emit();\n },\n error: (error: unknown) => {\n this.syncing.set(false);\n this.error.set(toNhAssistantError(error));\n this.synced.emit();\n }\n });\n }\n\n draft(tool: McpTool): ToolDraft {\n return this.drafts()[tool.remoteName] ?? toDraft(tool);\n }\n\n isDirty(tool: McpTool): boolean {\n const draft = this.draft(tool);\n return draft.isEnabled !== tool.isEnabled || draft.effect !== tool.effect ||\n draft.descriptionOverride !== (tool.descriptionOverride ?? '');\n }\n\n change(tool: McpTool, patch: Partial<ToolDraft>): void {\n this.savedTool.set(null);\n this.drafts.update(drafts => ({ ...drafts, [tool.remoteName]: { ...this.draft(tool), ...patch } }));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n save(tool: McpTool): void {\n const draft = this.draft(tool);\n const override = draft.descriptionOverride.trim();\n\n this.savingTool.set(tool.remoteName);\n this.savedTool.set(null);\n this.error.set(null);\n this.rowSubscription?.unsubscribe();\n this.rowSubscription = this.admin.updateMcpTool(this.server().id, tool.remoteName, {\n isEnabled: draft.isEnabled,\n effect: draft.effect,\n descriptionOverride: override.length > 0 ? override : null\n }).subscribe({\n next: updated => {\n this.tools.update(tools => tools.map(item => item.remoteName === updated.remoteName ? updated : item));\n this.drafts.update(drafts => {\n const { [updated.remoteName]: removed, ...rest } = drafts;\n return rest;\n });\n this.savingTool.set(null);\n this.savedTool.set(updated.remoteName);\n },\n error: (error: unknown) => {\n this.savingTool.set(null);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private setTools(tools: McpTool[]): void {\n this.tools.set(tools);\n this.drafts.set({});\n this.savedTool.set(null);\n }\n}\n\nfunction toDraft(tool: McpTool): ToolDraft {\n return { isEnabled: tool.isEnabled, effect: tool.effect, descriptionOverride: tool.descriptionOverride ?? '' };\n}\n","<section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading() || syncing()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.tools.title' | translate: { name: server().displayName } }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.tools.description' | translate }}</p>\n </div>\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"closed.emit()\">{{ 'nh-assistant.admin.tools.back' | translate }}</button>\n <button class=\"primary\" type=\"button\" [disabled]=\"syncing()\" (click)=\"sync()\">\n <nh-assistant-icon name=\"refresh\" />{{ (syncing() ? 'nh-assistant.admin.mcp.syncing' : 'nh-assistant.admin.mcp.sync') | translate }}\n </button>\n </div>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (tools().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.tools.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (tool of tools(); track tool.remoteName) {\n <li class=\"card\" [class.inactive]=\"!tool.isEnabled\" [attr.data-status]=\"tool.status\" [attr.aria-busy]=\"savingTool() === tool.remoteName\">\n <div class=\"card-header\">\n <strong class=\"mono\">{{ tool.remoteName }}</strong>\n <span class=\"badge\"\n [class.warning]=\"tool.status === 'schema-changed'\"\n [class.danger]=\"tool.status === 'missing'\">{{ 'nh-assistant.admin.tools.status.' + tool.status | translate }}</span>\n <span class=\"badge\" [class.success]=\"tool.isEnabled\">{{ (tool.isEnabled ? 'nh-assistant.admin.enabled' : 'nh-assistant.admin.disabled') | translate }}</span>\n @if (tool.readOnlyHint !== null) {\n <span class=\"badge hint\" [attr.title]=\"'nh-assistant.admin.tools.description' | translate\">\n {{ (tool.readOnlyHint ? 'nh-assistant.admin.tools.hint-read-only' : 'nh-assistant.admin.tools.hint-mutation') | translate }}\n </span>\n }\n </div>\n <span class=\"mono muted\">{{ tool.localId }}</span>\n\n @if (tool.status === 'schema-changed') {\n <p class=\"message warning\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.tools.schema-changed-warning' | translate }}</p>\n }\n @if (tool.status === 'missing') {\n <p class=\"message error\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.tools.missing-warning' | translate }}</p>\n }\n\n <p class=\"muted\"><span class=\"label\">{{ 'nh-assistant.admin.tools.remote-description' | translate }}</span>{{ tool.description }}</p>\n\n <div class=\"grid\">\n <label class=\"check\">\n <input\n type=\"checkbox\"\n [checked]=\"draft(tool).isEnabled\"\n [disabled]=\"tool.status === 'missing'\"\n (change)=\"change(tool, { isEnabled: checked($event) })\" />\n <span>{{ 'nh-assistant.admin.tools.enabled' | translate }}</span>\n </label>\n <div class=\"field\">\n <label [for]=\"id + '-effect-' + $index\">{{ 'nh-assistant.admin.tools.effect' | translate }}</label>\n <select [id]=\"id + '-effect-' + $index\" (change)=\"change(tool, { effect: $any(value($event)) })\">\n @for (effect of effects; track effect) {\n <option [value]=\"effect\" [selected]=\"draft(tool).effect === effect\">{{ 'nh-assistant.admin.effect.' + effect | translate }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-override-' + $index\">{{ 'nh-assistant.admin.tools.description-override' | translate }}</label>\n <input\n type=\"text\"\n maxlength=\"1000\"\n [id]=\"id + '-override-' + $index\"\n [value]=\"draft(tool).descriptionOverride\"\n [attr.aria-describedby]=\"id + '-override-hint-' + $index\"\n (input)=\"change(tool, { descriptionOverride: value($event) })\" />\n <p class=\"hint\" [id]=\"id + '-override-hint-' + $index\">{{ 'nh-assistant.admin.tools.description-override-hint' | translate }}</p>\n </div>\n\n <div class=\"card-actions\">\n <button class=\"primary\" type=\"button\" [disabled]=\"!isDirty(tool) || savingTool() !== null\" (click)=\"save(tool)\">\n {{ (savingTool() === tool.remoteName ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.tools.save') | translate }}\n </button>\n @if (savedTool() === tool.remoteName) {\n <span class=\"badge success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.saved' | translate }}</span>\n }\n </div>\n </li>\n }\n </ul>\n }\n</section>\n","import { DatePipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpServer,\n McpServerTestResult,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n nhAssistantErrorMessageKey,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminMcpServerEditorComponent } from './nh-assistant-admin-mcp-server-editor.component';\nimport { NhAssistantAdminMcpToolsComponent } from './nh-assistant-admin-mcp-tools.component';\n\n/** Result of the latest connection test per server. */\ninterface TestState {\n running: boolean;\n result: McpServerTestResult | null;\n}\n\nlet nextId = 0;\n\n/**\n * MCP server administration: list, connection test, tool sync, the server editor and the\n * tool table of one server.\n */\n@Component({\n selector: 'nh-assistant-admin-mcp-servers',\n standalone: true,\n imports: [\n DatePipe,\n TranslatePipe,\n NhAssistantTranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminMcpServerEditorComponent,\n NhAssistantAdminMcpToolsComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-servers.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpServersComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n private readonly actions = new Subscription();\n\n readonly id = `nh-assistant-admin-mcp-${nextId++}`;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly servers = signal<McpServer[]>([]);\n /** `undefined`: list; `null`: new server; a server: editing that server. */\n readonly editing = signal<McpServer | null | undefined>(undefined);\n readonly toolsOf = signal<McpServer | null>(null);\n readonly tests = signal<Record<string, TestState>>({});\n readonly confirmingDelete = signal<string | null>(null);\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.actions.unsubscribe();\n });\n this.load();\n }\n\n load(): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.getMcpServers().subscribe({\n next: servers => {\n this.servers.set(servers);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n /** Reloads the list silently, for example after a sync changed the sync status. */\n refresh(): void {\n this.actions.add(this.admin.getMcpServers().subscribe({ next: servers => this.servers.set(servers), error: () => undefined }));\n }\n\n create(): void {\n this.error.set(null);\n this.editing.set(null);\n }\n\n edit(server: McpServer): void {\n this.error.set(null);\n this.editing.set(server);\n }\n\n onSaved(server: McpServer): void {\n this.servers.update(servers => servers.some(item => item.id === server.id)\n ? servers.map(item => item.id === server.id ? server : item)\n : [...servers, server]);\n this.editing.set(undefined);\n }\n\n test(server: McpServer): void {\n this.setTest(server.id, { running: true, result: null });\n this.actions.add(this.admin.testMcpServer(server.id).subscribe({\n next: result => this.setTest(server.id, { running: false, result }),\n error: (error: unknown) => {\n const failure = toNhAssistantError(error);\n this.setTest(server.id, { running: false, result: { ok: false, code: failure.code, toolCount: null } });\n }\n }));\n }\n\n testState(serverId: string): TestState | null {\n return this.tests()[serverId] ?? null;\n }\n\n testErrorKeys(code: string | null): string[] {\n return code ? [nhAssistantErrorMessageKey(code), 'nh-assistant.errors.generic'] : ['nh-assistant.errors.generic'];\n }\n\n remove(server: McpServer): void {\n this.confirmingDelete.set(null);\n this.error.set(null);\n this.actions.add(this.admin.deleteMcpServer(server.id).subscribe({\n complete: () => this.servers.update(servers => servers.filter(item => item.id !== server.id)),\n error: (error: unknown) => this.error.set(toNhAssistantError(error))\n }));\n }\n\n private setTest(serverId: string, state: TestState): void {\n this.tests.update(tests => ({ ...tests, [serverId]: state }));\n }\n}\n","@if (editing() !== undefined) {\n <nh-assistant-admin-mcp-server-editor [server]=\"editing() ?? null\" (saved)=\"onSaved($event)\" (cancelled)=\"editing.set(undefined)\" />\n} @else if (toolsOf(); as server) {\n <nh-assistant-admin-mcp-tools [server]=\"server\" (closed)=\"toolsOf.set(null); refresh()\" (synced)=\"refresh()\" />\n} @else {\n <section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.mcp.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.mcp.description' | translate }}</p>\n </div>\n <button class=\"primary\" type=\"button\" [disabled]=\"loading() || loadFailed()\" (click)=\"create()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.mcp.new' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (servers().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.mcp.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (server of servers(); track server.id) {\n <li class=\"card\" [class.inactive]=\"!server.isEnabled\">\n <div class=\"card-header\">\n <strong>{{ server.displayName }}</strong>\n <span class=\"mono muted\">{{ server.id }}</span>\n <span class=\"badge\" [class.success]=\"server.isEnabled\">{{ (server.isEnabled ? 'nh-assistant.admin.enabled' : 'nh-assistant.admin.disabled') | translate }}</span>\n @if (server.lastSyncStatus) {\n <span class=\"badge\" [class.success]=\"server.lastSyncStatus === 'ok'\" [class.danger]=\"server.lastSyncStatus === 'failed'\">\n {{ (server.lastSyncStatus === 'ok' ? 'nh-assistant.admin.mcp.sync-ok' : 'nh-assistant.admin.mcp.sync-failed') | translate }}\n </span>\n }\n </div>\n <span class=\"mono muted url\">{{ server.url }}</span>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.mcp.auth.' + server.authMode | translate }}</span>\n @if (server.authMode === 'bearer' || server.authMode === 'api-key') {\n <span class=\"badge\" [class.success]=\"server.hasSecret\" [class.warning]=\"!server.hasSecret\">\n {{ (server.hasSecret ? 'nh-assistant.admin.mcp.secret-set' : 'nh-assistant.admin.mcp.no-secret') | translate }}\n </span>\n }\n <span>\n @if (server.lastSyncAt) {\n {{ 'nh-assistant.admin.mcp.last-sync' | translate: { date: (server.lastSyncAt | date: 'medium') } }}\n } @else {\n {{ 'nh-assistant.admin.mcp.never-synced' | translate }}\n }\n </span>\n <span>\n @if (server.assignedAgentIds.length > 0) {\n {{ 'nh-assistant.admin.mcp.assigned' | translate: { agents: server.assignedAgentIds.join(', ') } }}\n } @else {\n {{ 'nh-assistant.admin.mcp.unassigned' | translate }}\n }\n </span>\n </div>\n\n @if (testState(server.id); as state) {\n @if (state.running) {\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.admin.mcp.testing' | translate }}</p>\n } @else if (state.result?.ok) {\n <p class=\"message success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.mcp.test-ok' | translate: { count: state.result?.toolCount ?? 0 } }}</p>\n } @else {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ testErrorKeys(state.result?.code ?? null) | nhAssistantTranslate: (state.result?.code ?? '') }}</p>\n }\n }\n\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"edit(server)\"><nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}</button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"testState(server.id)?.running\" (click)=\"test(server)\">\n <nh-assistant-icon name=\"link\" />{{ 'nh-assistant.admin.mcp.test' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"toolsOf.set(server)\"><nh-assistant-icon name=\"tool\" />{{ 'nh-assistant.admin.mcp.tools' | translate }}</button>\n @if (confirmingDelete() === server.id) {\n <button class=\"danger\" type=\"button\" (click)=\"remove(server)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirmingDelete.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" (click)=\"confirmingDelete.set(server.id)\"><nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}</button>\n }\n </div>\n </li>\n }\n </ul>\n }\n </section>\n}\n","import { ChangeDetectionStrategy, Component, ElementRef, afterNextRender, inject, input, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport {\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n NhAssistantStore\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminAgentsComponent } from './agents/nh-assistant-admin-agents.component';\nimport { NhAssistantAdminContextComponent } from './context/nh-assistant-admin-context.component';\nimport { NhAssistantAdminMcpServersComponent } from './mcp/nh-assistant-admin-mcp-servers.component';\n\nexport type NhAssistantAdminTab = 'context' | 'agents' | 'mcp-servers';\n\nlet nextId = 0;\n\n/**\n * The assistant administration page with the tabs Context, Agents and MCP servers. The host\n * routes to it and guards the route with its admin permission; the component additionally\n * shows a no-access state unless the server reports `canAdminister`.\n */\n@Component({\n selector: 'nh-assistant-admin',\n standalone: true,\n imports: [\n TranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminContextComponent,\n NhAssistantAdminAgentsComponent,\n NhAssistantAdminMcpServersComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin.component.html',\n styleUrl: './nh-assistant-admin.component.scss'\n})\nexport class NhAssistantAdminComponent {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly store = inject(NhAssistantStore);\n\n /** Tab shown first. */\n readonly initialTab = input<NhAssistantAdminTab>('context');\n\n readonly id = `nh-assistant-admin-${nextId++}`;\n readonly tabs: readonly NhAssistantAdminTab[] = ['context', 'agents', 'mcp-servers'];\n readonly activeTab = signal<NhAssistantAdminTab | null>(null);\n readonly ready = signal(false);\n\n constructor() {\n afterNextRender(() => {\n void this.store.initialize().then(() => this.ready.set(true));\n });\n }\n\n selected(): NhAssistantAdminTab {\n return this.activeTab() ?? this.initialTab();\n }\n\n select(tab: NhAssistantAdminTab): void {\n this.activeTab.set(tab);\n }\n\n /** Arrow keys, Home and End move between tabs as the ARIA tabs pattern describes. */\n onTabKeydown(event: KeyboardEvent): void {\n const index = this.tabs.indexOf(this.selected());\n const last = this.tabs.length - 1;\n const targets: Record<string, number> = {\n ArrowRight: index === last ? 0 : index + 1,\n ArrowLeft: index === 0 ? last : index - 1,\n Home: 0,\n End: last\n };\n const next = targets[event.key];\n if (next === undefined) {\n return;\n }\n\n event.preventDefault();\n this.select(this.tabs[next]);\n this.host.nativeElement.querySelector<HTMLElement>(`#${this.id}-tab-${this.tabs[next]}`)?.focus();\n }\n}\n","<section class=\"admin\" [attr.aria-labelledby]=\"id + '-title'\">\n <header class=\"page-header\">\n <nh-assistant-icon class=\"page-icon\" name=\"admin\" />\n <div>\n <h2 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.title' | translate }}</h2>\n <p>{{ 'nh-assistant.admin.description' | translate }}</p>\n </div>\n </header>\n\n @if (!ready() || (store.statusLoading() && !store.enabled())) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else if (!store.canAdminister()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.admin.forbidden-title' | translate }}</p>\n <p>{{ 'nh-assistant.admin.forbidden-description' | translate }}</p>\n </div>\n } @else {\n <div class=\"tabs\" role=\"tablist\" [attr.aria-label]=\"'nh-assistant.admin.tabs-label' | translate\" (keydown)=\"onTabKeydown($event)\">\n @for (tab of tabs; track tab) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"tab\"\n [id]=\"id + '-tab-' + tab\"\n [attr.aria-selected]=\"selected() === tab\"\n [attr.aria-controls]=\"id + '-panel'\"\n [attr.tabindex]=\"selected() === tab ? 0 : -1\"\n (click)=\"select(tab)\">\n {{ 'nh-assistant.admin.tabs.' + tab | translate }}\n </button>\n }\n </div>\n\n <div class=\"panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"id + '-panel'\" [attr.aria-labelledby]=\"id + '-tab-' + selected()\">\n @switch (selected()) {\n @case ('context') {\n <nh-assistant-admin-context />\n }\n @case ('agents') {\n <nh-assistant-admin-agents />\n }\n @case ('mcp-servers') {\n <nh-assistant-admin-mcp-servers />\n }\n }\n </div>\n }\n</section>\n","/*\n * Public API surface of @newheap/platform-ai-chat/admin.\n *\n * The administration page is a separate entry point so hosts load it only on their lazy\n * admin route and the chat panel stays small.\n */\nexport * from './nh-assistant-admin.component';\nexport * from './context/nh-assistant-admin-context.component';\nexport * from './agents/nh-assistant-admin-agents.component';\nexport * from './agents/nh-assistant-admin-agent-editor.component';\nexport * from './agents/nh-assistant-agent-evaluation.component';\nexport * from './agents/nh-assistant-agent-feedback-report.component';\nexport * from './mcp/nh-assistant-admin-mcp-servers.component';\nexport * from './mcp/nh-assistant-admin-mcp-server-editor.component';\nexport * from './mcp/nh-assistant-admin-mcp-tools.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["nextId","nhAssistantErrorKeys","toNhAssistantError","NhAssistantIconComponent","NhAssistantTranslatePipe","NH_ASSISTANT_DASH_CASE","dayMs","periodRange"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"newheap-platform-ai-chat-admin.mjs","sources":["../../../projects/nh-ai-chat/admin/src/context/nh-assistant-admin-context.component.ts","../../../projects/nh-ai-chat/admin/src/context/nh-assistant-admin-context.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agent-editor.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agent-editor.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-evaluation.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-evaluation.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-feedback-report.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-feedback-report.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-run-configuration.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-agent-run-configuration.component.html","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agents.component.ts","../../../projects/nh-ai-chat/admin/src/agents/nh-assistant-admin-agents.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-server-editor.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-server-editor.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-tools.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-tools.component.html","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-servers.component.ts","../../../projects/nh-ai-chat/admin/src/mcp/nh-assistant-admin-mcp-servers.component.html","../../../projects/nh-ai-chat/admin/src/nh-assistant-admin.component.ts","../../../projects/nh-ai-chat/admin/src/nh-assistant-admin.component.html","../../../projects/nh-ai-chat/admin/src/public-api.ts","../../../projects/nh-ai-chat/admin/src/newheap-platform-ai-chat-admin.ts"],"sourcesContent":["import { DatePipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription, forkJoin } from 'rxjs';\nimport {\n ApplicationContext,\n ApplicationContextVersion,\n NhAssistantAdminApiService,\n NhAssistantClientErrorCodes,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Maximum length of the application context and of agent instructions. */\nexport const NH_ASSISTANT_MAX_INSTRUCTIONS = 20_000;\n\nlet nextId = 0;\n\n/**\n * Editor of the application context: the current version with its hash, optimistic\n * concurrency through `expectedVersion`, and the version history.\n */\n@Component({\n selector: 'nh-assistant-admin-context',\n standalone: true,\n imports: [DatePipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-context.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminContextComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n readonly id = `nh-assistant-admin-context-${nextId++}`;\n readonly max = NH_ASSISTANT_MAX_INSTRUCTIONS;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly saving = signal(false);\n readonly saved = signal(false);\n readonly conflict = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n readonly context = signal<ApplicationContext | null>(null);\n readonly versions = signal<ApplicationContextVersion[]>([]);\n readonly text = signal('');\n\n readonly tooLong = computed(() => this.text().length > this.max);\n readonly dirty = computed(() => this.text() !== (this.context()?.text ?? ''));\n readonly canSave = computed(() => !this.saving() && !this.tooLong() && this.dirty() && this.context() !== null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly history = computed(() => this.versions().filter(version => version.version !== this.context()?.version));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n this.load(false);\n }\n\n /** Loads the latest version; with `keepDraft` the user's unsaved text stays in the editor. */\n load(keepDraft: boolean): void {\n this.loading.set(!keepDraft);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = forkJoin([this.admin.getContext(), this.admin.getContextVersions()]).subscribe({\n next: ([context, versions]) => {\n const draft = this.text();\n this.context.set(context);\n this.versions.set(versions);\n this.text.set(keepDraft ? draft : context.text);\n this.conflict.set(false);\n this.error.set(null);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n onInput(event: Event): void {\n this.text.set((event.target as HTMLTextAreaElement).value);\n this.saved.set(false);\n }\n\n save(): void {\n const context = this.context();\n if (!context || !this.canSave()) {\n return;\n }\n\n this.saving.set(true);\n this.saved.set(false);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.updateContext({ text: this.text(), expectedVersion: context.version }).subscribe({\n next: updated => {\n this.context.set(updated);\n this.versions.update(versions => [\n { version: updated.version, hash: updated.hash, updatedAt: updated.updatedAt, updatedBy: updated.updatedBy },\n ...versions\n ]);\n this.text.set(updated.text);\n this.saving.set(false);\n this.saved.set(true);\n },\n error: (error: unknown) => {\n const failure = toNhAssistantError(error);\n this.saving.set(false);\n this.conflict.set(failure.code === NhAssistantClientErrorCodes.versionConflict);\n this.error.set(this.conflict() ? null : failure);\n }\n });\n }\n}\n","<section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading() || saving()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.context.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.context.description' | translate }}</p>\n </div>\n </header>\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load(false)\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (context(); as current) {\n <form class=\"stack\" (submit)=\"$event.preventDefault(); save()\">\n <div class=\"meta\">\n <span class=\"badge\">{{ 'nh-assistant.admin.context.version' | translate: { version: current.version } }}</span>\n <span>\n @if (current.updatedBy) {\n {{ 'nh-assistant.admin.context.updated' | translate: { date: (current.updatedAt | date: 'medium'), user: current.updatedBy } }}\n } @else {\n {{ 'nh-assistant.admin.context.updated-unknown' | translate: { date: (current.updatedAt | date: 'medium') } }}\n }\n </span>\n <span class=\"mono\" [attr.title]=\"current.hash\">{{ 'nh-assistant.admin.context.hash' | translate }} {{ current.hash.slice(0, 18) }}</span>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-text'\">{{ 'nh-assistant.admin.context.label' | translate }}</label>\n <textarea\n class=\"large\"\n rows=\"14\"\n [id]=\"id + '-text'\"\n [value]=\"text()\"\n [attr.aria-describedby]=\"id + '-hint'\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"onInput($event)\"></textarea>\n <p class=\"hint\" [id]=\"id + '-hint'\">\n <span [class.error-text]=\"tooLong()\">{{ tooLong() ? ('nh-assistant.admin.too-long' | translate) : '' }}</span>\n <span class=\"counter\" [class.error-text]=\"tooLong()\">{{ 'nh-assistant.admin.characters' | translate: { count: text().length, max: max } }}</span>\n </p>\n </div>\n\n @if (conflict()) {\n <div class=\"message warning\" role=\"alert\">\n <nh-assistant-icon name=\"warning\" />\n <span class=\"grow\">{{ 'nh-assistant.admin.context.conflict' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"load(true)\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.context.reload' | translate }}\n </button>\n </div>\n }\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (saved()) {\n <p class=\"message success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.saved' | translate }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"primary\" type=\"submit\" [disabled]=\"!canSave()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n </form>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-history'\">\n <h4 [id]=\"id + '-history'\">{{ 'nh-assistant.admin.context.history' | translate }}</h4>\n @if (history().length === 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.context.history-empty' | translate }}</p>\n } @else {\n <ol class=\"history\">\n @for (version of history(); track version.version) {\n <li>\n <span class=\"badge\">{{ 'nh-assistant.admin.context.version' | translate: { version: version.version } }}</span>\n <span>{{ version.updatedAt | date: 'medium' }}</span>\n @if (version.updatedBy) {\n <span>{{ version.updatedBy }}</span>\n }\n <span class=\"mono muted\" [attr.title]=\"version.hash\">{{ version.hash.slice(0, 18) }}</span>\n </li>\n }\n </ol>\n }\n </section>\n }\n</section>\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AdminAgent,\n AdminAgentInput,\n AssistantAutonomy,\n McpServer,\n ɵNH_ASSISTANT_DASH_CASE as NH_ASSISTANT_DASH_CASE,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError,\n ToolCatalogEntry\n} from '@newheap/platform-ai-chat';\nimport { NH_ASSISTANT_MAX_INSTRUCTIONS } from '../context/nh-assistant-admin-context.component';\n\n/** True when a tool id matches a selector glob (`*` matches any characters). */\nexport function nhAssistantSelectorMatches(toolId: string, selector: string): boolean {\n const pattern = selector.split('*').map(part => part.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('.*');\n return new RegExp(`^${pattern}$`).test(toolId);\n}\n\nconst selectorPattern = /^[a-z0-9*][a-z0-9.*_-]*$/i;\n\nlet nextId = 0;\n\n/**\n * Creates or edits one agent: texts, autonomy, policy, tool selectors chosen from the tool\n * catalog or typed as patterns, and assigned MCP servers.\n */\n@Component({\n selector: 'nh-assistant-admin-agent-editor',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-agent-editor.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminAgentEditorComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n /** The agent to edit, or null for a new agent. */\n readonly agent = input<AdminAgent | null>(null);\n readonly tools = input<readonly ToolCatalogEntry[]>([]);\n readonly servers = input<readonly McpServer[]>([]);\n readonly saved = output<AdminAgent>();\n readonly cancelled = output<void>();\n\n readonly id = `nh-assistant-agent-editor-${nextId++}`;\n readonly max = NH_ASSISTANT_MAX_INSTRUCTIONS;\n readonly autonomyLevels: readonly AssistantAutonomy[] = ['observe', 'explain', 'propose', 'simulate', 'execute'];\n\n readonly agentId = signal('');\n readonly displayName = signal('');\n readonly description = signal('');\n readonly instructions = signal('');\n readonly autonomy = signal<AssistantAutonomy>('explain');\n readonly requiredPolicy = signal('');\n readonly toolSelectors = signal<string[]>([]);\n readonly mcpServerIds = signal<string[]>([]);\n readonly newSelector = signal('');\n readonly catalogFilter = signal('');\n readonly submitted = signal(false);\n readonly saving = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n\n readonly isNew = computed(() => this.agent() === null);\n readonly idInvalid = computed(() => this.isNew() && !NH_ASSISTANT_DASH_CASE.test(this.agentId()));\n readonly nameMissing = computed(() => this.displayName().trim().length === 0);\n readonly tooLong = computed(() => this.instructions().length > this.max);\n readonly selectorInvalid = computed(() => this.newSelector().trim().length > 0 && !selectorPattern.test(this.newSelector().trim()));\n readonly valid = computed(() => !this.idInvalid() && !this.nameMissing() && !this.tooLong());\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly filteredTools = computed(() => {\n const filter = this.catalogFilter().trim().toLowerCase();\n return this.tools().filter(tool => !filter ||\n tool.id.toLowerCase().includes(filter) || tool.description.toLowerCase().includes(filter));\n });\n readonly matchCount = computed(() => this.tools()\n .filter(tool => this.toolSelectors().some(selector => nhAssistantSelectorMatches(tool.id, selector))).length);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n\n effect(() => {\n const agent = this.agent();\n untracked(() => this.reset(agent));\n });\n }\n\n isSelected(toolId: string): boolean {\n return this.toolSelectors().includes(toolId);\n }\n\n isCovered(toolId: string): boolean {\n return this.toolSelectors().some(selector => selector !== toolId && nhAssistantSelectorMatches(toolId, selector));\n }\n\n toggleTool(toolId: string, checked: boolean): void {\n this.toolSelectors.update(selectors => checked\n ? [...selectors.filter(selector => selector !== toolId), toolId]\n : selectors.filter(selector => selector !== toolId));\n }\n\n addSelector(): void {\n const selector = this.newSelector().trim();\n if (selector.length === 0 || this.selectorInvalid()) {\n return;\n }\n\n this.toolSelectors.update(selectors => selectors.includes(selector) ? selectors : [...selectors, selector]);\n this.newSelector.set('');\n }\n\n onSelectorKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.addSelector();\n }\n }\n\n removeSelector(selector: string): void {\n this.toolSelectors.update(selectors => selectors.filter(item => item !== selector));\n }\n\n toggleServer(serverId: string, checked: boolean): void {\n this.mcpServerIds.update(ids => checked ? [...ids.filter(id => id !== serverId), serverId] : ids.filter(id => id !== serverId));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n save(): void {\n this.submitted.set(true);\n if (!this.valid() || this.saving()) {\n return;\n }\n\n const policy = this.requiredPolicy().trim();\n const input: AdminAgentInput = {\n id: this.isNew() ? this.agentId() : this.agent()!.id,\n displayName: this.displayName().trim(),\n description: this.description().trim(),\n instructions: this.instructions(),\n toolSelectors: this.toolSelectors(),\n mcpServerIds: this.mcpServerIds(),\n requiredPolicy: policy.length > 0 ? policy : null,\n autonomy: this.autonomy()\n };\n\n const existing = this.agent();\n const request = existing\n ? this.admin.updateAgent(existing.id, { ...input, expectedVersion: existing.version })\n : this.admin.createAgent(input);\n\n this.saving.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = request.subscribe({\n next: agent => {\n this.saving.set(false);\n this.saved.emit(agent);\n },\n error: (error: unknown) => {\n this.saving.set(false);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private reset(agent: AdminAgent | null): void {\n this.agentId.set(agent?.id ?? '');\n this.displayName.set(agent?.displayName ?? '');\n this.description.set(agent?.description ?? '');\n this.instructions.set(agent?.instructions ?? '');\n this.autonomy.set(agent?.autonomy ?? 'explain');\n this.requiredPolicy.set(agent?.requiredPolicy ?? '');\n this.toolSelectors.set([...(agent?.toolSelectors ?? [])]);\n this.mcpServerIds.set([...(agent?.mcpServerIds ?? [])]);\n this.submitted.set(false);\n this.error.set(null);\n }\n}\n","<form class=\"section card\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"saving()\" (submit)=\"$event.preventDefault(); save()\">\n <h3 [id]=\"id + '-title'\">\n @if (agent(); as current) {\n {{ 'nh-assistant.admin.agent-editor.edit-title' | translate: { name: current.displayName } }}\n } @else {\n {{ 'nh-assistant.admin.agent-editor.new-title' | translate }}\n }\n </h3>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-id'\">{{ 'nh-assistant.admin.agent-editor.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [id]=\"id + '-id'\"\n [value]=\"agentId()\"\n [disabled]=\"!isNew()\"\n [attr.aria-describedby]=\"id + '-id-hint'\"\n [attr.aria-invalid]=\"submitted() && idInvalid() ? true : null\"\n (input)=\"agentId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-id-hint'\">\n <span [class.error-text]=\"submitted() && idInvalid()\">\n {{ (submitted() && idInvalid() ? 'nh-assistant.admin.invalid-id' : 'nh-assistant.admin.agent-editor.id-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-name'\">{{ 'nh-assistant.admin.agent-editor.display-name' | translate }}</label>\n <input\n type=\"text\"\n [id]=\"id + '-name'\"\n [value]=\"displayName()\"\n [attr.aria-invalid]=\"submitted() && nameMissing() ? true : null\"\n [attr.aria-describedby]=\"id + '-name-hint'\"\n (input)=\"displayName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-name-hint'\">\n @if (submitted() && nameMissing()) {\n <span class=\"error-text\">{{ 'nh-assistant.admin.required' | translate }}</span>\n }\n </p>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-description'\">{{ 'nh-assistant.admin.agent-editor.description' | translate }}</label>\n <input type=\"text\" [id]=\"id + '-description'\" [value]=\"description()\" (input)=\"description.set(value($event))\" />\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-instructions'\">{{ 'nh-assistant.admin.agent-editor.instructions' | translate }}</label>\n <textarea\n rows=\"8\"\n [id]=\"id + '-instructions'\"\n [value]=\"instructions()\"\n [attr.aria-describedby]=\"id + '-instructions-hint'\"\n [attr.aria-invalid]=\"tooLong() ? true : null\"\n (input)=\"instructions.set(value($event))\"></textarea>\n <p class=\"hint\" [id]=\"id + '-instructions-hint'\">\n <span [class.error-text]=\"tooLong()\">\n {{ (tooLong() ? 'nh-assistant.admin.too-long' : 'nh-assistant.admin.agent-editor.instructions-hint') | translate }}\n </span>\n <span class=\"counter\" [class.error-text]=\"tooLong()\">{{ 'nh-assistant.admin.characters' | translate: { count: instructions().length, max: max } }}</span>\n </p>\n </div>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-autonomy'\">{{ 'nh-assistant.admin.agent-editor.autonomy' | translate }}</label>\n <select [id]=\"id + '-autonomy'\" [attr.aria-describedby]=\"id + '-autonomy-hint'\" (change)=\"autonomy.set($any(value($event)))\">\n @for (level of autonomyLevels; track level) {\n <option [value]=\"level\" [selected]=\"autonomy() === level\">{{ 'nh-assistant.admin.agents.autonomy.' + level | translate }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-autonomy-hint'\">{{ 'nh-assistant.admin.agent-editor.autonomy-hint' | translate }}</p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-policy'\">{{ 'nh-assistant.admin.agent-editor.required-policy' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [id]=\"id + '-policy'\"\n [value]=\"requiredPolicy()\"\n [attr.aria-describedby]=\"id + '-policy-hint'\"\n (input)=\"requiredPolicy.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-policy-hint'\">{{ 'nh-assistant.admin.agent-editor.required-policy-hint' | translate }}</p>\n </div>\n </div>\n\n <p class=\"hint\">{{ 'nh-assistant.admin.agent-editor.state-hint' | translate }}</p>\n\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.agent-editor.tool-selectors' | translate }}</legend>\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.tool-selectors-hint' | translate }}</p>\n\n @if (toolSelectors().length === 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.no-selectors' | translate }}</p>\n } @else {\n <ul class=\"chips\">\n @for (selector of toolSelectors(); track selector) {\n <li class=\"chip\">\n <span>{{ selector }}</span>\n <button\n type=\"button\"\n [attr.aria-label]=\"'nh-assistant.admin.agent-editor.remove-selector' | translate: { selector: selector }\"\n [attr.title]=\"'nh-assistant.admin.agent-editor.remove-selector' | translate: { selector: selector }\"\n (click)=\"removeSelector(selector)\">\n <nh-assistant-icon name=\"x\" />\n </button>\n </li>\n }\n </ul>\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.admin.agent-editor.matches' | translate: { count: matchCount() } }}</p>\n }\n\n <div class=\"inline\">\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n [attr.aria-label]=\"'nh-assistant.admin.agent-editor.add-selector' | translate\"\n [attr.placeholder]=\"'nh-assistant.admin.agent-editor.selector-placeholder' | translate\"\n [attr.aria-invalid]=\"selectorInvalid() ? true : null\"\n [value]=\"newSelector()\"\n (input)=\"newSelector.set(value($event))\"\n (keydown)=\"onSelectorKeydown($event)\" />\n <button class=\"secondary\" type=\"button\" [disabled]=\"newSelector().trim().length === 0 || selectorInvalid()\" (click)=\"addSelector()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.agent-editor.add-selector' | translate }}\n </button>\n </div>\n\n <div class=\"field\">\n <label class=\"label\" [for]=\"id + '-catalog-filter'\">{{ 'nh-assistant.admin.agent-editor.catalog' | translate }}</label>\n <input\n type=\"search\"\n [id]=\"id + '-catalog-filter'\"\n [attr.placeholder]=\"'nh-assistant.admin.agent-editor.catalog-filter' | translate\"\n [value]=\"catalogFilter()\"\n (input)=\"catalogFilter.set(value($event))\" />\n <ul class=\"catalog\" [attr.aria-label]=\"'nh-assistant.admin.agent-editor.catalog' | translate\">\n @for (tool of filteredTools(); track tool.id) {\n <li>\n <label>\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(tool.id) || isCovered(tool.id)\"\n [disabled]=\"isCovered(tool.id)\"\n (change)=\"toggleTool(tool.id, checked($event))\" />\n <span class=\"tool-id\">{{ tool.id }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.source.' + tool.source | translate }}</span>\n <span class=\"badge\" [class.warning]=\"tool.effect !== 'read-only'\">{{ 'nh-assistant.admin.effect.' + tool.effect | translate }}</span>\n <span class=\"muted\">{{ tool.description }}</span>\n </label>\n </li>\n } @empty {\n <li class=\"muted\">{{ 'nh-assistant.admin.agent-editor.catalog-empty' | translate }}</li>\n }\n </ul>\n </div>\n </fieldset>\n\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.agent-editor.mcp-servers' | translate }}</legend>\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.mcp-servers-hint' | translate }}</p>\n @for (server of servers(); track server.id) {\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"mcpServerIds().includes(server.id)\" (change)=\"toggleServer(server.id, checked($event))\" />\n <span>{{ server.displayName }} <span class=\"mono muted\">{{ server.id }}</span></span>\n </label>\n } @empty {\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.mcp-servers-empty' | translate }}</p>\n }\n </fieldset>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancelled.emit()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"saving() || tooLong()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n</form>\n","import { DatePipe, DecimalPipe, DOCUMENT } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AgentEvaluation,\n AgentEvaluationCost,\n AgentReplay,\n NhAssistantAdminApiService,\n NhAssistantError,\n NhAssistantPanelService,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Periods the evaluation offers, in days before now; the server allows at most 92. */\nexport type NhAssistantEvaluationPeriod = 7 | 30 | 90;\n\n/** One row of the cost comparison: a measure of the live agent next to the variant's. */\ninterface NhAssistantCostRow {\n key: 'runs' | 'model-calls' | 'tokens' | 'tool-calls';\n live: AgentEvaluationCost;\n variant: AgentEvaluationCost;\n}\n\nconst dayMs = 24 * 60 * 60 * 1000;\nconst defaultReplayRuns = 100;\nconst maxReplayRuns = 500;\n\nlet nextId = 0;\n\n/**\n * Compares a shadow variant of an agent with the live agent, for the agent's administrators: the\n * runs that handled the same events, per tool the proposals both made, only one made and what\n * people decided about the live ones, what each cost and how each routed, with links to the threads\n * of the differences. Small numbers mislead, so counts stand next to every share. Administrators\n * replay the recorded runs of the period into the variant and export the comparison as JSON Lines.\n * The report holds no messages or arguments.\n */\n@Component({\n selector: 'nh-assistant-agent-evaluation',\n standalone: true,\n imports: [DatePipe, DecimalPipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-agent-evaluation.component.html',\n styleUrls: ['../nh-assistant-admin-shared.scss', './nh-assistant-agent-feedback-report.component.scss']\n})\nexport class NhAssistantAgentEvaluationComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly panel = inject(NhAssistantPanelService, { optional: true });\n private readonly document = inject(DOCUMENT);\n private subscription?: Subscription;\n private replaySubscription?: Subscription;\n\n /** The live agent. */\n readonly agentId = input.required<string>();\n /** Its shadow variants; the first is compared until another is chosen. */\n readonly variants = input.required<readonly string[]>();\n\n readonly id = `nh-assistant-agent-evaluation-${nextId++}`;\n readonly periods: readonly NhAssistantEvaluationPeriod[] = [7, 30, 90];\n readonly maxReplayRuns = maxReplayRuns;\n readonly canOpenThreads = this.panel !== null;\n\n readonly variant = signal('');\n readonly period = signal<NhAssistantEvaluationPeriod>(7);\n readonly loading = signal(true);\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly evaluation = signal<AgentEvaluation | null>(null);\n\n readonly exporting = signal(false);\n readonly exportError = signal<NhAssistantError | null>(null);\n readonly exportErrorKeys = computed(() => nhAssistantErrorKeys(this.exportError()));\n readonly canExport = computed(() => !this.exporting() && !this.loading() && (this.evaluation()?.runs.paired ?? 0) > 0);\n\n readonly replays = signal<AgentReplay[]>([]);\n readonly replayRuns = signal(defaultReplayRuns);\n readonly replaying = signal(false);\n readonly replayError = signal<NhAssistantError | null>(null);\n readonly replayErrorKeys = computed(() => nhAssistantErrorKeys(this.replayError()));\n readonly replayRunning = computed(() => this.replays().some(replay => replay.status === 'running'));\n\n readonly costRows = computed<NhAssistantCostRow[]>(() => {\n const evaluation = this.evaluation();\n return evaluation\n ? (['runs', 'model-calls', 'tokens', 'tool-calls'] as const).map(key => ({ key, live: evaluation.liveCost, variant: evaluation.variantCost }))\n : [];\n });\n /** Routing matters only when one of the two worked in a skill. */\n readonly showRouting = computed(() => (this.evaluation()?.routing ?? []).some(row => row.liveSkill !== null || row.variantSkill !== null));\n\n /** The period the last load asked for, so the report, the export and a replay agree. */\n private range = periodRange(7);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.replaySubscription?.unsubscribe();\n });\n effect(() => {\n const variants = this.variants();\n this.agentId();\n untracked(() => {\n if (!variants.includes(this.variant())) {\n this.variant.set(variants[0] ?? '');\n }\n this.load();\n });\n });\n }\n\n /** Reloads the comparison and the variant's replays for the chosen period. */\n load(): void {\n this.range = periodRange(this.period());\n this.error.set(null);\n this.exportError.set(null);\n this.subscription?.unsubscribe();\n if (!this.variant()) {\n this.loading.set(false);\n this.evaluation.set(null);\n return;\n }\n\n this.loading.set(true);\n this.subscription = this.admin.getAgentEvaluation(this.agentId(), { variant: this.variant(), ...this.range }).subscribe({\n next: evaluation => {\n this.evaluation.set(evaluation);\n this.loading.set(false);\n },\n error: (failure: unknown) => {\n this.evaluation.set(null);\n this.loading.set(false);\n this.error.set(toNhAssistantError(failure));\n }\n });\n this.loadReplays();\n }\n\n loadReplays(): void {\n this.replaySubscription?.unsubscribe();\n this.replaySubscription = this.admin.getAgentReplays(this.variant()).subscribe({\n next: list => this.replays.set(list.items),\n error: () => this.replays.set([])\n });\n }\n\n onVariant(event: Event): void {\n this.variant.set((event.target as HTMLSelectElement).value);\n this.load();\n }\n\n onPeriod(event: Event): void {\n this.period.set(Number((event.target as HTMLSelectElement).value) as NhAssistantEvaluationPeriod);\n this.load();\n }\n\n onReplayRuns(event: Event): void {\n const value = Math.round(Number((event.target as HTMLInputElement).value));\n this.replayRuns.set(Number.isFinite(value) ? Math.min(Math.max(value, 1), maxReplayRuns) : defaultReplayRuns);\n }\n\n /** Replays the live agent's recorded runs of the period into the variant. */\n replay(): void {\n if (this.replaying() || this.replayRunning() || !this.variant()) {\n return;\n }\n\n this.replaying.set(true);\n this.replayError.set(null);\n this.admin\n .startAgentReplay(this.variant(), { sourceAgentId: this.agentId(), ...this.range, maxRuns: this.replayRuns() })\n .subscribe({\n next: replay => {\n this.replaying.set(false);\n this.replays.update(items => [replay, ...items.filter(item => item.id !== replay.id)]);\n },\n error: (failure: unknown) => {\n this.replaying.set(false);\n this.replayError.set(toNhAssistantError(failure));\n }\n });\n }\n\n /** Downloads the paired runs of the comparison as a JSON Lines file. */\n async export(): Promise<void> {\n if (!this.canExport()) {\n return;\n }\n\n this.exporting.set(true);\n this.exportError.set(null);\n try {\n const blob = await this.admin.exportAgentEvaluation(this.agentId(), { variant: this.variant(), ...this.range });\n const url = URL.createObjectURL(blob);\n const link = this.document.createElement('a');\n link.href = url;\n link.download = `agent-evaluation-${this.agentId()}-${this.variant()}.jsonl`;\n link.click();\n URL.revokeObjectURL(url);\n } catch (failure) {\n this.exportError.set(toNhAssistantError(failure));\n } finally {\n this.exporting.set(false);\n }\n }\n\n /** Opens a thread of the comparison in the assistant panel, when the host has one. */\n openThread(conversationId: string): void {\n this.panel?.open(conversationId);\n }\n\n /** The share of a count in a total, or `null` without a total. */\n share(count: number, total: number): number | null {\n return total > 0 ? count / total : null;\n }\n\n total(row: AgentEvaluation['tools'][number]): number {\n return row.agreed + row.liveOnly;\n }\n\n categories(row: AgentEvaluation['tools'][number]): { category: string; count: number }[] {\n return Object.entries(row.liveDecisions.rejectionCategories)\n .map(([category, count]) => ({ category, count }))\n .sort((left, right) => right.count - left.count);\n }\n}\n\nfunction periodRange(days: number): { from: string; to: string } {\n const to = Date.now();\n return { from: new Date(to - days * dayMs).toISOString(), to: new Date(to).toISOString() };\n}\n","<section class=\"section report\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.evaluation.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.description' | translate }}</p>\n <p class=\"muted export-hint\" [id]=\"id + '-export-hint'\">{{ 'nh-assistant.admin.evaluation.export-hint' | translate }}</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"loading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.evaluation.refresh' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"!canExport()\" [attr.aria-describedby]=\"id + '-export-hint'\" (click)=\"export()\">\n <nh-assistant-icon name=\"page\" />{{ (exporting() ? 'nh-assistant.admin.evaluation.exporting' : 'nh-assistant.admin.evaluation.export') | translate }}\n </button>\n </div>\n </header>\n\n <div class=\"filters\">\n <div class=\"field\">\n <label [for]=\"id + '-variant'\">{{ 'nh-assistant.admin.evaluation.variant' | translate }}</label>\n <select [id]=\"id + '-variant'\" (change)=\"onVariant($event)\">\n @for (option of variants(); track option) {\n <option [value]=\"option\" [selected]=\"variant() === option\">\n {{ ['nh-assistant.agents.' + option + '.name'] | nhAssistantTranslate: option }}\n </option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-period'\">{{ 'nh-assistant.admin.evaluation.period' | translate }}</label>\n <select [id]=\"id + '-period'\" (change)=\"onPeriod($event)\">\n @for (days of periods; track days) {\n <option [value]=\"days\" [selected]=\"period() === days\">{{ 'nh-assistant.admin.feedback.periods.last-' + days + '-days' | translate }}</option>\n }\n </select>\n </div>\n </div>\n\n @if (exportError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ exportErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading() && evaluation() === null) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (error(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (evaluation(); as report) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-runs-title'\">\n <h4 [id]=\"id + '-runs-title'\">{{ 'nh-assistant.admin.evaluation.runs-title' | translate }}</h4>\n <dl class=\"meta\" data-evaluation-runs>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.live' | translate }}</dt><dd>{{ report.runs.live }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.variant' | translate }}</dt><dd>{{ report.runs.variant }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.paired' | translate }}</dt><dd data-paired>{{ report.runs.paired }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.replayed' | translate }}</dt><dd>{{ report.runs.replayed }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.live-unpaired' | translate }}</dt><dd>{{ report.runs.liveUnpaired }}</dd></div>\n <div><dt>{{ 'nh-assistant.admin.evaluation.runs.variant-unpaired' | translate }}</dt><dd>{{ report.runs.variantUnpaired }}</dd></div>\n </dl>\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.small-numbers' | translate }}</p>\n @if (report.runs.replayed > 0) {\n <p class=\"muted\">{{ 'nh-assistant.admin.evaluation.replayed-hint' | translate }}</p>\n }\n @if (report.runs.truncated) {\n <p class=\"message\" role=\"status\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.evaluation.truncated' | translate }}</p>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-tools-title'\">\n <h4 [id]=\"id + '-tools-title'\">{{ 'nh-assistant.admin.evaluation.tools-title' | translate }}</h4>\n @if (report.tools.length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.evaluation.tools-empty' | translate }}</p>\n } @else {\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-tools-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.tool' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.agreed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.live-only' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.variant-only' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.rejected-not-proposed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.rejected-also-proposed' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.approved-missed' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.live-decisions' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of report.tools; track row.toolId) {\n <tr [attr.data-evaluation-tool]=\"row.toolId\">\n <th scope=\"row\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.tool' | translate\"><span class=\"mono\">{{ row.toolId }}</span></th>\n <td class=\"number\" data-agreed [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.agreed' | translate\">\n {{ row.agreed }}\n @if (share(row.agreed, total(row)); as fraction) {\n <span class=\"muted\">({{ fraction * 100 | number: '1.0-0' }}%)</span>\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-only' | translate\">{{ row.liveOnly }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.variant-only' | translate\">{{ row.variantOnly }}</td>\n <td class=\"number\" data-rejected-not-proposed [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.rejected-not-proposed' | translate\">{{ row.rejectedLiveNotProposed }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.rejected-also-proposed' | translate\">{{ row.rejectedLiveAlsoProposed }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.approved-missed' | translate\">{{ row.approvedLiveMissed }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-decisions' | translate\">\n {{ 'nh-assistant.admin.evaluation.decisions' | translate: row.liveDecisions }}\n @if (categories(row).length > 0) {\n <ul class=\"badges\">\n @for (item of categories(row); track item.category) {\n <li>\n <span class=\"badge\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-cost-title'\">\n <h4 [id]=\"id + '-cost-title'\">{{ 'nh-assistant.admin.evaluation.cost-title' | translate }}</h4>\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-cost-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.measure' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.live' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.variant' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of costRows(); track row.key) {\n <tr [attr.data-cost]=\"row.key\">\n <th scope=\"row\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.measure' | translate\">{{ 'nh-assistant.admin.evaluation.cost.' + row.key | translate }}</th>\n @for (side of [row.live, row.variant]; track $index) {\n <td class=\"number\" [attr.data-label]=\"($index === 0 ? 'nh-assistant.admin.evaluation.columns.live' : 'nh-assistant.admin.evaluation.columns.variant') | translate\">\n @switch (row.key) {\n @case ('runs') { {{ side.runs }} }\n @case ('model-calls') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageModelCalls | number: '1.0-2'), p95: side.p95ModelCalls, total: side.modelCalls } }}\n }\n @case ('tokens') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageTokens | number: '1.0-0'), p95: side.p95Tokens, total: side.tokens } }}\n }\n @case ('tool-calls') {\n {{ 'nh-assistant.admin.evaluation.cost.average-p95' | translate: { average: (side.averageToolCalls | number: '1.0-2'), p95: side.p95ToolCalls, total: side.toolCalls } }}\n }\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n\n @if (showRouting()) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-routing-title'\">\n <h4 [id]=\"id + '-routing-title'\">{{ 'nh-assistant.admin.evaluation.routing-title' | translate }}</h4>\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-routing-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.live-skill' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.variant-skill' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.evaluation.columns.runs' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of report.routing; track $index) {\n <tr>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.live-skill' | translate\">{{ row.liveSkill ?? ('nh-assistant.admin.evaluation.no-skill' | translate) }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.variant-skill' | translate\">{{ row.variantSkill ?? ('nh-assistant.admin.evaluation.no-skill' | translate) }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.evaluation.columns.runs' | translate\">{{ row.runs }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n }\n\n @if (report.differences.length > 0) {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-differences-title'\">\n <h4 [id]=\"id + '-differences-title'\">{{ 'nh-assistant.admin.evaluation.differences-title' | translate }}</h4>\n <ul class=\"cards\">\n @for (difference of report.differences; track difference.liveRunId + difference.variantRunId + $index) {\n <li class=\"card\" [attr.data-difference]=\"difference.kind\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ difference.toolId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.kind.' + difference.kind | translate }}</span>\n @if (difference.liveStatus; as status) {\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.live-status' | translate: { status } }}</span>\n }\n @if (difference.replayed) {\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.replayed' | translate }}</span>\n }\n </div>\n @if (canOpenThreads) {\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"openThread(difference.liveConversationId)\">\n {{ 'nh-assistant.admin.evaluation.open-live' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"openThread(difference.variantConversationId)\">\n {{ 'nh-assistant.admin.evaluation.open-variant' | translate }}\n </button>\n </div>\n }\n </li>\n }\n </ul>\n </section>\n }\n }\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-replay-title'\">\n <h4 [id]=\"id + '-replay-title'\">{{ 'nh-assistant.admin.evaluation.replay-title' | translate }}</h4>\n <p class=\"muted\" [id]=\"id + '-replay-hint'\">{{ 'nh-assistant.admin.evaluation.replay-hint' | translate: { max: maxReplayRuns } }}</p>\n <div class=\"inline\">\n <div class=\"field\">\n <label [for]=\"id + '-replay-runs'\">{{ 'nh-assistant.admin.evaluation.replay-runs' | translate }}</label>\n <input\n [id]=\"id + '-replay-runs'\"\n type=\"number\"\n min=\"1\"\n [max]=\"maxReplayRuns\"\n [value]=\"replayRuns()\"\n [attr.aria-describedby]=\"id + '-replay-hint'\"\n (change)=\"onReplayRuns($event)\" />\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"replaying() || replayRunning() || !variant()\" (click)=\"replay()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.evaluation.replay' | translate }}\n </button>\n </div>\n @if (replayError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ replayErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n @if (replays().length > 0) {\n <ul class=\"cards\" data-replays>\n @for (item of replays(); track item.id) {\n <li class=\"card\" [attr.data-replay]=\"item.status\">\n <div class=\"card-header\">\n <strong>{{ item.createdAt | date: 'short' }}</strong>\n <span class=\"badge\">{{ 'nh-assistant.admin.evaluation.replay-status.' + item.status | translate }}</span>\n </div>\n <p class=\"muted\">\n {{ 'nh-assistant.admin.evaluation.replay-progress' | translate: { replayed: item.runsReplayed, skipped: item.runsSkipped, max: item.maxRuns } }}\n </p>\n @if (item.stopReason; as code) {\n <p class=\"muted\">{{ ['nh-assistant.errors.' + code] | nhAssistantTranslate: code }}</p>\n }\n </li>\n }\n </ul>\n }\n </section>\n</section>\n","import { DatePipe, DOCUMENT, PercentPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n AgentFeedbackCategoryCount,\n AgentFeedbackItem,\n AgentFeedbackSummaryRow,\n AgentProposalFeedbackCategory,\n AgentProposalFeedbackGroup,\n NH_ASSISTANT_FEEDBACK_CATEGORIES,\n StaleKind,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Periods the report offers, in days before now. */\nexport type NhAssistantFeedbackPeriod = 7 | 30 | 90;\n\n/** A summary row with its most frequent feedback categories and why open proposals closed. */\ninterface NhAssistantFeedbackSummaryView extends AgentFeedbackSummaryRow {\n topCategories: AgentFeedbackCategoryCount[];\n /** Open proposals closed before a decision, per kind, most frequent first. */\n invalidatedKinds: { kind: StaleKind; count: number; reasons: string }[];\n}\n\nconst dayMs = 24 * 60 * 60 * 1000;\nconst topCategoryCount = 3;\n\nlet nextId = 0;\n\n/**\n * What people said when they rejected an agent's proposals, for the agent's administrators: per\n * tool and agent version the decisions, the rejection rate, the share of rejections with feedback,\n * the number of different people and the most frequent categories, followed by the feedback itself\n * and a JSON Lines export. Comparing agent versions shows whether a change to the prompt, tools or\n * policy helped. The server requires the assistant admin policy and reports only the caller's scopes.\n */\n@Component({\n selector: 'nh-assistant-agent-feedback-report',\n standalone: true,\n imports: [DatePipe, PercentPipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-agent-feedback-report.component.html',\n styleUrls: ['../nh-assistant-admin-shared.scss', './nh-assistant-agent-feedback-report.component.scss']\n})\nexport class NhAssistantAgentFeedbackReportComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly document = inject(DOCUMENT);\n private summarySubscription?: Subscription;\n private listSubscription?: Subscription;\n\n readonly agentId = input.required<string>();\n /** Feedback per page; the server allows at most 100. */\n readonly itemsPerPage = input(20);\n\n readonly id = `nh-assistant-agent-feedback-${nextId++}`;\n readonly periods: readonly NhAssistantFeedbackPeriod[] = [7, 30, 90];\n readonly categories = NH_ASSISTANT_FEEDBACK_CATEGORIES;\n\n readonly period = signal<NhAssistantFeedbackPeriod>(30);\n readonly toolId = signal('');\n readonly category = signal<AgentProposalFeedbackCategory | ''>('');\n readonly page = signal(1);\n\n readonly summaryLoading = signal(true);\n readonly summaryError = signal<NhAssistantError | null>(null);\n readonly summaryErrorKeys = computed(() => nhAssistantErrorKeys(this.summaryError()));\n readonly rows = signal<AgentFeedbackSummaryRow[]>([]);\n\n readonly listLoading = signal(true);\n readonly listError = signal<NhAssistantError | null>(null);\n readonly listErrorKeys = computed(() => nhAssistantErrorKeys(this.listError()));\n readonly items = signal<AgentFeedbackItem[]>([]);\n readonly total = signal(0);\n readonly pages = computed(() => Math.max(1, Math.ceil(this.total() / this.itemsPerPage())));\n\n readonly exporting = signal(false);\n readonly exportError = signal<NhAssistantError | null>(null);\n readonly exportErrorKeys = computed(() => nhAssistantErrorKeys(this.exportError()));\n readonly canExport = computed(() => !this.exporting() && !this.listLoading() && this.listError() === null && this.total() > 0);\n\n /** Tools with proposals in the period, plus the chosen tool when the period has none of it. */\n readonly tools = computed(() => {\n const tools = new Set(this.rows().map(row => row.toolId));\n if (this.toolId()) {\n tools.add(this.toolId());\n }\n return [...tools].sort();\n });\n readonly visibleRows = computed<NhAssistantFeedbackSummaryView[]>(() => this.rows()\n .filter(row => !this.toolId() || row.toolId === this.toolId())\n .map(row => ({\n ...row,\n topCategories: [...row.categories].sort((left, right) => right.count - left.count).slice(0, topCategoryCount),\n invalidatedKinds: invalidatedKinds(row)\n })));\n readonly filtered = computed(() => this.toolId() !== '' || this.category() !== '');\n\n /** The period the last load asked for, so the list, summary and export agree. */\n private range = periodRange(30);\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.summarySubscription?.unsubscribe();\n this.listSubscription?.unsubscribe();\n });\n effect(() => {\n this.agentId();\n untracked(() => {\n this.toolId.set('');\n this.category.set('');\n this.load();\n });\n });\n }\n\n /** Reloads the summary and the first page of feedback for the chosen period. */\n load(): void {\n this.range = periodRange(this.period());\n this.page.set(1);\n this.loadSummary();\n this.loadList();\n }\n\n onPeriod(event: Event): void {\n this.period.set(Number((event.target as HTMLSelectElement).value) as NhAssistantFeedbackPeriod);\n this.load();\n }\n\n onTool(event: Event): void {\n this.toolId.set((event.target as HTMLSelectElement).value);\n this.page.set(1);\n this.loadList();\n }\n\n onCategory(event: Event): void {\n this.category.set((event.target as HTMLSelectElement).value as AgentProposalFeedbackCategory | '');\n this.page.set(1);\n this.loadList();\n }\n\n goTo(page: number): void {\n this.page.set(Math.min(Math.max(1, page), this.pages()));\n this.loadList();\n }\n\n loadSummary(): void {\n this.summaryLoading.set(true);\n this.summaryError.set(null);\n this.summarySubscription?.unsubscribe();\n this.summarySubscription = this.admin.getAgentFeedbackSummary(this.agentId(), this.range).subscribe({\n next: summary => {\n this.rows.set(summary.rows);\n this.summaryLoading.set(false);\n },\n error: (failure: unknown) => {\n this.rows.set([]);\n this.summaryLoading.set(false);\n this.summaryError.set(toNhAssistantError(failure));\n }\n });\n }\n\n loadList(): void {\n this.listLoading.set(true);\n this.listError.set(null);\n this.exportError.set(null);\n this.listSubscription?.unsubscribe();\n this.listSubscription = this.admin\n .getAgentFeedback(this.agentId(), {\n ...this.range,\n toolId: this.toolId() || undefined,\n category: this.category() || undefined,\n page: this.page(),\n itemsPerPage: this.itemsPerPage()\n })\n .subscribe({\n next: list => {\n this.items.set(list.items);\n this.total.set(list.total);\n this.listLoading.set(false);\n },\n error: (failure: unknown) => {\n this.items.set([]);\n this.total.set(0);\n this.listLoading.set(false);\n this.listError.set(toNhAssistantError(failure));\n }\n });\n }\n\n /** Downloads the feedback of the period and filters as a JSON Lines file. */\n async export(): Promise<void> {\n if (!this.canExport()) {\n return;\n }\n\n this.exporting.set(true);\n this.exportError.set(null);\n try {\n const blob = await this.admin.exportAgentFeedback(this.agentId(), {\n ...this.range,\n toolId: this.toolId() || undefined,\n category: this.category() || undefined\n });\n const url = URL.createObjectURL(blob);\n const link = this.document.createElement('a');\n link.href = url;\n link.download = `agent-feedback-${this.agentId()}.jsonl`;\n link.click();\n URL.revokeObjectURL(url);\n } catch (failure) {\n this.exportError.set(toNhAssistantError(failure));\n } finally {\n this.exporting.set(false);\n }\n }\n\n /** Badge color of a feedback group: wrong and not allowed are failures, not now is a warning. */\n groupClass(group: AgentProposalFeedbackGroup): string {\n switch (group) {\n case 'wrong':\n case 'not-allowed':\n return 'danger';\n case 'right-but-not-now':\n return 'warning';\n default:\n return '';\n }\n }\n}\n\nfunction periodRange(days: number): { from: string; to: string } {\n const to = Date.now();\n return { from: new Date(to - days * dayMs).toISOString(), to: new Date(to).toISOString() };\n}\n\n/**\n * The open proposals of a row that closed before a decision, per kind, with their reason codes for\n * the tooltip. Proposals that closed after their approval are part of the approved count.\n */\nfunction invalidatedKinds(row: AgentFeedbackSummaryRow): { kind: StaleKind; count: number; reasons: string }[] {\n const kinds = new Map<StaleKind, { count: number; reasons: string[] }>();\n for (const item of row.invalidations ?? []) {\n if (item.afterApproval) {\n continue;\n }\n\n const entry = kinds.get(item.kind) ?? { count: 0, reasons: [] };\n entry.count += item.count;\n entry.reasons.push(`${item.reasonCode} (${item.count})`);\n kinds.set(item.kind, entry);\n }\n\n return [...kinds.entries()]\n .map(([kind, entry]) => ({ kind, count: entry.count, reasons: entry.reasons.join(', ') }))\n .sort((left, right) => right.count - left.count);\n}\n","<section class=\"section report\" [attr.aria-labelledby]=\"id + '-title'\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.feedback.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.description' | translate }}</p>\n <p class=\"muted export-hint\" [id]=\"id + '-export-hint'\">{{ 'nh-assistant.admin.feedback.export-hint' | translate }}</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"summaryLoading() || listLoading()\" (click)=\"load()\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.feedback.refresh' | translate }}\n </button>\n <button\n class=\"secondary\"\n type=\"button\"\n [disabled]=\"!canExport()\"\n [attr.aria-describedby]=\"id + '-export-hint'\"\n (click)=\"export()\">\n <nh-assistant-icon name=\"page\" />{{ (exporting() ? 'nh-assistant.admin.feedback.exporting' : 'nh-assistant.admin.feedback.export') | translate }}\n </button>\n </div>\n </header>\n\n <div class=\"filters\">\n <div class=\"field\">\n <label [for]=\"id + '-period'\">{{ 'nh-assistant.admin.feedback.period' | translate }}</label>\n <select [id]=\"id + '-period'\" (change)=\"onPeriod($event)\">\n @for (days of periods; track days) {\n <option [value]=\"days\" [selected]=\"period() === days\">{{ 'nh-assistant.admin.feedback.periods.last-' + days + '-days' | translate }}</option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-tool'\">{{ 'nh-assistant.admin.feedback.tool' | translate }}</label>\n <select [id]=\"id + '-tool'\" [disabled]=\"summaryLoading() && tools().length === 0\" (change)=\"onTool($event)\">\n <option value=\"\" [selected]=\"toolId() === ''\">{{ 'nh-assistant.admin.feedback.all-tools' | translate }}</option>\n @for (tool of tools(); track tool) {\n <option [value]=\"tool\" [selected]=\"toolId() === tool\">{{ tool }}</option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-category'\">{{ 'nh-assistant.admin.feedback.category' | translate }}</label>\n <select [id]=\"id + '-category'\" [attr.aria-describedby]=\"id + '-category-hint'\" (change)=\"onCategory($event)\">\n <option value=\"\" [selected]=\"category() === ''\">{{ 'nh-assistant.admin.feedback.all-categories' | translate }}</option>\n @for (option of categories; track option) {\n <option [value]=\"option\" [selected]=\"category() === option\">{{ 'nh-assistant.proposal-feedback.categories.' + option | translate }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-category-hint'\"><span>{{ 'nh-assistant.admin.feedback.category-hint' | translate }}</span></p>\n </div>\n </div>\n\n @if (exportError(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ exportErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-summary-title'\" [attr.aria-busy]=\"summaryLoading()\">\n <h4 [id]=\"id + '-summary-title'\">{{ 'nh-assistant.admin.feedback.summary-title' | translate }}</h4>\n @if (summaryLoading() && rows().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (summaryError(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ summaryErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"loadSummary()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (visibleRows().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.feedback.summary-empty' | translate }}</p>\n } @else {\n <div class=\"table-container\">\n <table class=\"summary-table\" [attr.aria-labelledby]=\"id + '-summary-title'\">\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.tool' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.version' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.approved' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.rejected' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.expired' | translate }}</th>\n <th scope=\"col\" class=\"number\" [attr.title]=\"'nh-assistant.admin.feedback.invalidated-hint' | translate\">\n {{ 'nh-assistant.admin.feedback.columns.invalidated' | translate }}\n </th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.rejection-rate' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.with-feedback' | translate }}</th>\n <th scope=\"col\" class=\"number\">{{ 'nh-assistant.admin.feedback.columns.people' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.feedback.columns.categories' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of visibleRows(); track row.toolId + '|' + row.agentVersion) {\n <tr>\n <th scope=\"row\" class=\"tool\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.tool' | translate\">\n <span class=\"mono\">{{ row.toolId }}</span>\n </th>\n <td [attr.data-label]=\"'nh-assistant.admin.feedback.columns.version' | translate\">\n @if (row.agentVersion === null) {\n {{ 'nh-assistant.admin.feedback.consultations' | translate }}\n } @else {\n {{ 'nh-assistant.admin.feedback.version' | translate: { version: row.agentVersion } }}\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.approved' | translate\">{{ row.approved }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.rejected' | translate\">{{ row.rejected }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.expired' | translate\">{{ row.expired }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.invalidated' | translate\">\n {{ row.invalidated ?? 0 }}\n @if (row.invalidatedKinds.length > 0) {\n <ul class=\"badges\">\n @for (item of row.invalidatedKinds; track item.kind) {\n <li>\n <span class=\"badge\" [attr.title]=\"item.reasons\">\n {{ 'nh-assistant.approval.stale-kind.' + item.kind | translate }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.rejection-rate' | translate\">\n @if (row.rejectionRate === null) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.no-decisions' | translate }}</span>\n } @else {\n {{ row.rejectionRate | percent: '1.0-0' }}\n }\n </td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.with-feedback' | translate\">{{ row.rejectedWithFeedback }}</td>\n <td class=\"number\" [attr.data-label]=\"'nh-assistant.admin.feedback.columns.people' | translate\">{{ row.feedbackAuthors }}</td>\n <td [attr.data-label]=\"'nh-assistant.admin.feedback.columns.categories' | translate\">\n @if (row.topCategories.length === 0) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.no-categories' | translate }}</span>\n } @else {\n <ul class=\"badges\">\n @for (item of row.topCategories; track item.category) {\n <li>\n <span [class]=\"'badge ' + groupClass(item.group)\" [attr.title]=\"'nh-assistant.proposal-feedback.groups.' + item.group | translate\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n <span class=\"count\">{{ item.count }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-list-title'\" [attr.aria-busy]=\"listLoading()\">\n <div class=\"list-header\">\n <h4 [id]=\"id + '-list-title'\">{{ 'nh-assistant.admin.feedback.list-title' | translate }}</h4>\n @if (!listLoading() && listError() === null) {\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.list-count' | translate: { count: total() } }}</span>\n }\n </div>\n @if (listLoading() && items().length === 0) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (listError(); as failure) {\n <div class=\"state\" role=\"alert\">\n <p>{{ listErrorKeys() | nhAssistantTranslate: failure.code }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"loadList()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (items().length === 0) {\n <p class=\"state\">{{ (filtered() ? 'nh-assistant.admin.feedback.list-empty-filtered' : 'nh-assistant.admin.feedback.list-empty') | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (item of items(); track item.id) {\n <li class=\"card\">\n <div class=\"card-header\">\n <strong>{{ item.subjectDisplayName ?? item.subjectId }}</strong>\n <span class=\"muted\">{{ item.presentation?.toolDisplayName ?? item.toolId }}</span>\n @if (item.agentVersion !== null) {\n <span class=\"badge\">{{ 'nh-assistant.admin.feedback.version' | translate: { version: item.agentVersion } }}</span>\n }\n <span [class]=\"'badge ' + groupClass(item.group)\" [attr.title]=\"'nh-assistant.proposal-feedback.groups.' + item.group | translate\">\n {{ 'nh-assistant.proposal-feedback.categories.' + item.category | nhAssistantTranslate: item.category }}\n </span>\n @if (item.bulk) {\n <span class=\"badge\" [attr.title]=\"'nh-assistant.admin.feedback.bulk-hint' | translate\">{{ 'nh-assistant.admin.feedback.bulk' | translate }}</span>\n }\n </div>\n @if (item.text) {\n <blockquote class=\"feedback-text\">{{ item.text }}</blockquote>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.no-text' | translate }}</p>\n }\n <p class=\"proposal\">\n <span class=\"proposal-label\">{{ 'nh-assistant.admin.feedback.proposal' | translate }}</span>\n {{ item.presentation?.summary ?? item.summary }}\n </p>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.agent-runs.proposal.status.' + item.approvalStatus | nhAssistantTranslate: item.approvalStatus }}</span>\n <span>{{ 'nh-assistant.admin.feedback.author' | translate: { actor: item.authorDisplayName || item.authorActorId } }}</span>\n <span>{{ item.updatedAt | date: 'short' }}</span>\n </div>\n </li>\n }\n </ul>\n @if (pages() > 1) {\n <nav class=\"pager\" [attr.aria-label]=\"'nh-assistant.admin.feedback.pages' | translate\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() <= 1 || listLoading()\" (click)=\"goTo(page() - 1)\">\n {{ 'nh-assistant.admin.feedback.previous' | translate }}\n </button>\n <span class=\"muted\">{{ 'nh-assistant.admin.feedback.page' | translate: { page: page(), pages: pages() } }}</span>\n <button class=\"secondary\" type=\"button\" [disabled]=\"page() >= pages() || listLoading()\" (click)=\"goTo(page() + 1)\">\n {{ 'nh-assistant.admin.feedback.next' | translate }}\n </button>\n </nav>\n }\n }\n </section>\n</section>\n","import { DatePipe, DecimalPipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n OnInit,\n afterNextRender,\n computed,\n inject,\n input,\n output,\n signal\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Observable, Subscription, forkJoin } from 'rxjs';\nimport {\n AdminAgent,\n AgentAccountability,\n AgentElevatedReads,\n AgentRunConfiguration,\n AgentRunSettingsRequest,\n DataSkill,\n DataSkillRequest,\n DataSkillVersion,\n DataTrigger,\n DataTriggerRequest,\n NhAssistantAdminApiService,\n NhAssistantError,\n RunCatalog,\n SkillApplyMode,\n SkillComparison,\n TriggerConflict,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\nlet nextId = 0;\n\n/** The longest reason the server stores with a change. */\nconst maxReason = 500;\nconst maxDescription = 300;\nconst maxInstructions = 20_000;\nconst maxMessage = 2_000;\nconst dashCase = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\ntype Form = 'settings' | 'skill' | 'trigger';\n\n/** A removal, promotion or discard that waits for its confirmation. */\ninterface Confirmation {\n action: 'remove-settings' | 'remove-skill' | 'remove-trigger' | 'promote' | 'discard';\n id: string;\n}\n\n/**\n * The run configuration of one agent as data: the run settings of an agent created in the\n * administration, its skills and triggers in code (read only) and as data, and the data that no\n * longer fits the code. Administrators add and change data skills, live at once or as a candidate in\n * shadow that they compare with the live version and promote or discard; they add data triggers on\n * the application's events or on a schedule and put them live. New skills and triggers start in\n * shadow; `changed` tells the agents page to reload the agent's skill states.\n */\n@Component({\n selector: 'nh-assistant-agent-run-configuration',\n standalone: true,\n imports: [DatePipe, DecimalPipe, TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-agent-run-configuration.component.html',\n styleUrls: ['../nh-assistant-admin-shared.scss', './nh-assistant-agent-feedback-report.component.scss']\n})\nexport class NhAssistantAgentRunConfigurationComponent implements OnInit {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly injector = inject(Injector);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private loadSubscription?: Subscription;\n private actionSubscription?: Subscription;\n private detailSubscription?: Subscription;\n\n readonly agent = input.required<AdminAgent>();\n /** A change of the run configuration changed the agent's skills or state. */\n readonly changed = output<void>();\n\n readonly id = `nh-assistant-run-configuration-${nextId++}`;\n readonly maxReason = maxReason;\n readonly maxDescription = maxDescription;\n readonly maxInstructions = maxInstructions;\n readonly maxMessage = maxMessage;\n readonly accountabilities: AgentAccountability[] = ['agent', 'subject-responsible', 'service-account'];\n readonly elevatedReadModes: AgentElevatedReads[] = ['restricted', 'deny'];\n readonly conflicts: TriggerConflict[] = ['coalesce', 'queue', 'supersede', 'ignore'];\n\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly busy = signal(false);\n readonly catalog = signal<RunCatalog | null>(null);\n readonly configuration = signal<AgentRunConfiguration | null>(null);\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n readonly saved = signal<string | null>(null);\n readonly form = signal<Form | null>(null);\n readonly confirming = signal<Confirmation | null>(null);\n readonly reason = signal('');\n\n /** The skill being changed; `null` with the skill form open adds a new skill. */\n readonly editingSkill = signal<DataSkill | null>(null);\n /** The trigger being changed; `null` with the trigger form open adds a new trigger. */\n readonly editingTrigger = signal<DataTrigger | null>(null);\n readonly comparison = signal<{ skillId: string; result: SkillComparison | null; failed: boolean } | null>(null);\n readonly versions = signal<{ skillId: string; items: DataSkillVersion[] | null; failed: boolean } | null>(null);\n\n // Run settings form.\n readonly accountability = signal<AgentAccountability>('service-account');\n readonly serviceAccount = signal('');\n readonly approvalPolicy = signal('');\n readonly ruleHandler = signal('');\n readonly triageProfile = signal('');\n readonly retryCount = signal('3');\n readonly maxConcurrentRuns = signal('4');\n readonly maxRunsPerSubjectPerDay = signal('10');\n readonly maxTokensPerRun = signal('');\n readonly dailyToolCalls = signal('');\n readonly dailyTokens = signal('');\n readonly allowGatewayReads = signal(false);\n readonly delegateFromInitiator = signal(false);\n readonly elevatedReads = signal<AgentElevatedReads>('restricted');\n\n // Skill form.\n readonly skillId = signal('');\n readonly skillDescription = signal('');\n readonly skillInstructions = signal('');\n readonly skillTools = signal<string[]>([]);\n readonly skillProfile = signal('');\n readonly skillRuleHandler = signal('');\n readonly skillApprovalPolicy = signal('');\n readonly skillMaxTokens = signal('');\n readonly skillDailyToolCalls = signal('');\n readonly skillDailyTokens = signal('');\n readonly skillApply = signal<SkillApplyMode>('live');\n\n // Trigger form.\n readonly triggerId = signal('');\n readonly triggerSource = signal<'event' | 'schedule'>('event');\n readonly triggerEvent = signal('');\n readonly triggerCron = signal('');\n readonly triggerTimeZone = signal('');\n readonly triggerSubjectSet = signal('');\n readonly triggerMessage = signal('');\n readonly triggerSkill = signal('');\n readonly triggerConflict = signal<TriggerConflict>('coalesce');\n readonly triggerDebounce = signal('120');\n\n readonly isAdminAgent = computed(() => this.configuration()?.source === 'admin');\n /** An agent created in the administration gets skills and triggers once it has run settings. */\n readonly canAddRunData = computed(() => {\n const configuration = this.configuration();\n return configuration !== null && (configuration.source === 'code' || configuration.runSettings !== null);\n });\n readonly skillOptions = computed(() => {\n const configuration = this.configuration();\n return configuration\n ? [...configuration.codeSkills.map(skill => skill.skillId), ...configuration.dataSkills.map(skill => skill.skillId)]\n : [];\n });\n readonly problems = computed(() => this.configuration()?.problems ?? []);\n readonly skillIdInvalid = computed(() => this.editingSkill() === null && !dashCase.test(this.skillId().trim()));\n readonly triggerIdInvalid = computed(() => this.editingTrigger() === null && !dashCase.test(this.triggerId().trim()));\n readonly descriptionInvalid = computed(() => {\n const description = this.skillDescription().trim();\n return description.length === 0 || description.length > maxDescription;\n });\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.loadSubscription?.unsubscribe();\n this.actionSubscription?.unsubscribe();\n this.detailSubscription?.unsubscribe();\n });\n }\n\n ngOnInit(): void {\n this.load();\n }\n\n load(): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.loadSubscription?.unsubscribe();\n this.loadSubscription = forkJoin([this.admin.getRunCatalog(), this.admin.getAgentConfiguration(this.agent().id)]).subscribe({\n next: ([catalog, configuration]) => {\n this.catalog.set(catalog);\n this.configuration.set(configuration);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n /** The first error of a field from the last failed save, as a translation key. */\n fieldError(field: string): string | null {\n const code = this.error()?.fieldErrors?.[field]?.[0];\n return code ? `nh-assistant.admin.run-config.field-errors.${code}` : null;\n }\n\n editSettings(): void {\n const settings = this.configuration()?.runSettings;\n this.accountability.set(settings?.accountability ?? 'service-account');\n this.serviceAccount.set(settings?.serviceAccountActorId ?? '');\n this.approvalPolicy.set(settings?.approvalPolicy ?? '');\n this.ruleHandler.set(settings?.ruleHandler ?? '');\n this.triageProfile.set(settings?.triageProfile ?? '');\n this.retryCount.set(String(settings?.retryCount ?? 3));\n this.maxConcurrentRuns.set(String(settings?.maxConcurrentRuns ?? 4));\n this.maxRunsPerSubjectPerDay.set(String(settings?.maxRunsPerSubjectPerDay ?? 10));\n this.maxTokensPerRun.set(numberText(settings?.maxTokensPerRun));\n this.dailyToolCalls.set(numberText(settings?.dailyToolCalls));\n this.dailyTokens.set(numberText(settings?.dailyTokens));\n this.allowGatewayReads.set(settings?.allowGatewayReads ?? false);\n this.delegateFromInitiator.set(settings?.delegateFromInitiator ?? false);\n this.elevatedReads.set(settings?.elevatedReads ?? 'restricted');\n this.open('settings');\n }\n\n saveSettings(): void {\n const request: AgentRunSettingsRequest = {\n accountability: this.accountability(),\n serviceAccountActorId: this.accountability() === 'service-account' ? blank(this.serviceAccount()) : null,\n delegateFromInitiator: this.delegateFromInitiator(),\n allowGatewayReads: this.allowGatewayReads(),\n elevatedReads: this.elevatedReads(),\n approvalPolicy: blank(this.approvalPolicy()),\n retryCount: toNumber(this.retryCount()),\n maxConcurrentRuns: toNumber(this.maxConcurrentRuns()),\n maxRunsPerSubjectPerDay: toNumber(this.maxRunsPerSubjectPerDay()),\n maxTokensPerRun: toNumber(this.maxTokensPerRun()),\n dailyToolCalls: toNumber(this.dailyToolCalls()),\n dailyTokens: toNumber(this.dailyTokens()),\n triageProfile: blank(this.triageProfile()),\n ruleHandler: blank(this.ruleHandler()),\n expectedVersion: this.configuration()?.runSettings?.version ?? null,\n reason: blank(this.reason())\n };\n this.run(this.admin.saveRunSettings(this.agent().id, request), 'nh-assistant.admin.run-config.settings.saved');\n }\n\n removeSettings(): void {\n const version = this.configuration()?.runSettings?.version ?? null;\n this.run(this.admin.removeRunSettings(this.agent().id, { expectedVersion: version }), 'nh-assistant.admin.run-config.settings.removed');\n }\n\n addSkill(): void {\n this.editingSkill.set(null);\n this.fillSkill(null);\n this.open('skill');\n }\n\n editSkill(skill: DataSkill): void {\n this.editingSkill.set(skill);\n this.fillSkill(skill);\n this.open('skill');\n }\n\n toggleTool(selector: string, selected: boolean): void {\n this.skillTools.update(tools => selected\n ? [...tools.filter(tool => tool !== selector), selector]\n : tools.filter(tool => tool !== selector));\n }\n\n saveSkill(): void {\n const editing = this.editingSkill();\n const skillId = editing?.skillId ?? this.skillId().trim();\n if (this.skillIdInvalid() || this.descriptionInvalid() || this.skillInstructions().length > maxInstructions) {\n return;\n }\n\n const request: DataSkillRequest = {\n description: this.skillDescription().trim(),\n instructions: blank(this.skillInstructions()),\n tools: this.skillTools(),\n profile: blank(this.skillProfile()),\n ruleHandler: blank(this.skillRuleHandler()),\n approvalPolicy: blank(this.skillApprovalPolicy()),\n maxTokensPerRun: toNumber(this.skillMaxTokens()),\n dailyToolCalls: toNumber(this.skillDailyToolCalls()),\n dailyTokens: toNumber(this.skillDailyTokens()),\n expectedVersion: editing?.version ?? null,\n reason: blank(this.reason()),\n ...(editing ? { apply: this.skillApply() } : {})\n };\n const saved = editing && this.skillApply() === 'shadow'\n ? 'nh-assistant.admin.run-config.skills.saved-candidate'\n : editing ? 'nh-assistant.admin.run-config.skills.saved' : 'nh-assistant.admin.run-config.skills.added';\n this.run(this.admin.saveDataSkill(this.agent().id, skillId, request), saved);\n }\n\n removeSkill(skill: DataSkill): void {\n this.run(\n this.admin.removeDataSkill(this.agent().id, skill.skillId, { expectedVersion: skill.version }),\n 'nh-assistant.admin.run-config.skills.removed');\n }\n\n promote(skill: DataSkill): void {\n const candidate = skill.candidate;\n if (candidate) {\n this.run(\n this.admin.promoteSkillCandidate(this.agent().id, skill.skillId, { version: candidate.version, reason: blank(this.reason()) }),\n 'nh-assistant.admin.run-config.candidate.promoted');\n }\n }\n\n discard(skill: DataSkill): void {\n const candidate = skill.candidate;\n if (candidate) {\n this.run(\n this.admin.discardSkillCandidate(this.agent().id, skill.skillId, { version: candidate.version, reason: blank(this.reason()) }),\n 'nh-assistant.admin.run-config.candidate.discarded');\n }\n }\n\n /** Shows or hides the comparison of a skill's candidate with its live version. */\n toggleComparison(skill: DataSkill): void {\n if (this.comparison()?.skillId === skill.skillId) {\n this.comparison.set(null);\n return;\n }\n\n this.versions.set(null);\n this.comparison.set({ skillId: skill.skillId, result: null, failed: false });\n this.detailSubscription?.unsubscribe();\n this.detailSubscription = this.admin.compareSkillCandidate(this.agent().id, skill.skillId).subscribe({\n next: result => this.comparison.set({ skillId: skill.skillId, result, failed: false }),\n error: () => this.comparison.set({ skillId: skill.skillId, result: null, failed: true })\n });\n }\n\n /** Shows or hides the version history of a skill. */\n toggleVersions(skill: DataSkill): void {\n if (this.versions()?.skillId === skill.skillId) {\n this.versions.set(null);\n return;\n }\n\n this.comparison.set(null);\n this.versions.set({ skillId: skill.skillId, items: null, failed: false });\n this.detailSubscription?.unsubscribe();\n this.detailSubscription = this.admin.getDataSkillVersions(this.agent().id, skill.skillId).subscribe({\n next: items => this.versions.set({ skillId: skill.skillId, items, failed: false }),\n error: () => this.versions.set({ skillId: skill.skillId, items: null, failed: true })\n });\n }\n\n addTrigger(): void {\n this.editingTrigger.set(null);\n this.fillTrigger(null);\n this.open('trigger');\n }\n\n editTrigger(trigger: DataTrigger): void {\n this.editingTrigger.set(trigger);\n this.fillTrigger(trigger);\n this.open('trigger');\n }\n\n /** A schedule skips a tick while a run is busy by default; an event coalesces. */\n setTriggerSource(source: 'event' | 'schedule'): void {\n this.triggerSource.set(source);\n if (this.editingTrigger() === null) {\n this.triggerConflict.set(source === 'schedule' ? 'ignore' : 'coalesce');\n }\n }\n\n saveTrigger(): void {\n const editing = this.editingTrigger();\n if (this.triggerIdInvalid()) {\n return;\n }\n\n const schedule = this.triggerSource() === 'schedule';\n const request: DataTriggerRequest = {\n source: this.triggerSource(),\n skill: blank(this.triggerSkill()),\n event: schedule ? null : blank(this.triggerEvent()),\n cron: schedule ? blank(this.triggerCron()) : null,\n timeZone: schedule ? blank(this.triggerTimeZone()) : null,\n subjectSet: schedule ? blank(this.triggerSubjectSet()) : null,\n message: schedule ? blank(this.triggerMessage()) : null,\n conflict: this.triggerConflict(),\n debounceSeconds: schedule ? null : toNumber(this.triggerDebounce()),\n expectedVersion: editing?.version ?? null,\n reason: blank(this.reason())\n };\n this.run(\n this.admin.saveDataTrigger(this.agent().id, editing?.triggerId ?? this.triggerId().trim(), request),\n editing ? 'nh-assistant.admin.run-config.triggers.saved' : 'nh-assistant.admin.run-config.triggers.added');\n }\n\n setTriggerShadow(trigger: DataTrigger, shadow: boolean): void {\n this.run(\n this.admin.setDataTriggerShadow(this.agent().id, trigger.triggerId, { mode: shadow ? 'shadow' : 'live', reason: null }),\n shadow ? 'nh-assistant.admin.run-config.triggers.in-shadow' : 'nh-assistant.admin.run-config.triggers.live');\n }\n\n removeTrigger(trigger: DataTrigger): void {\n this.run(\n this.admin.removeDataTrigger(this.agent().id, trigger.triggerId, { expectedVersion: trigger.version }),\n 'nh-assistant.admin.run-config.triggers.removed');\n }\n\n confirm(action: Confirmation['action'], id: string): void {\n this.form.set(null);\n this.error.set(null);\n this.saved.set(null);\n this.reason.set('');\n this.confirming.set({ action, id });\n }\n\n isConfirming(action: Confirmation['action'], id: string): boolean {\n const confirming = this.confirming();\n return confirming?.action === action && confirming.id === id;\n }\n\n cancel(): void {\n this.form.set(null);\n this.confirming.set(null);\n this.error.set(null);\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n private fillSkill(skill: DataSkill | null): void {\n this.skillId.set(skill?.skillId ?? '');\n this.skillDescription.set(skill?.description ?? '');\n this.skillInstructions.set(skill?.instructions ?? '');\n this.skillTools.set([...(skill?.tools ?? [])]);\n this.skillProfile.set(skill?.profile ?? '');\n this.skillRuleHandler.set(skill?.ruleHandler ?? '');\n this.skillApprovalPolicy.set(skill?.approvalPolicy ?? '');\n this.skillMaxTokens.set(numberText(skill?.maxTokensPerRun));\n this.skillDailyToolCalls.set(numberText(skill?.dailyToolCalls));\n this.skillDailyTokens.set(numberText(skill?.dailyTokens));\n // A real change is evaluated in shadow first; a small correction goes live.\n this.skillApply.set('shadow');\n }\n\n private fillTrigger(trigger: DataTrigger | null): void {\n this.triggerId.set(trigger?.triggerId ?? '');\n this.triggerSource.set(trigger?.source ?? 'event');\n this.triggerEvent.set(trigger?.event ?? '');\n this.triggerCron.set(trigger?.cron ?? '');\n this.triggerTimeZone.set(trigger?.timeZone ?? '');\n this.triggerSubjectSet.set(trigger?.subjectSet ?? '');\n this.triggerMessage.set(trigger?.message ?? '');\n this.triggerSkill.set(trigger?.skillId ?? '');\n this.triggerConflict.set(trigger?.conflict ?? 'coalesce');\n this.triggerDebounce.set(String(trigger?.debounceSeconds ?? 120));\n }\n\n /** Opens one form at a time and moves the focus into it. */\n private open(form: Form): void {\n this.confirming.set(null);\n this.error.set(null);\n this.saved.set(null);\n this.reason.set('');\n this.form.set(form);\n afterNextRender(() => {\n this.host.nativeElement.querySelector<HTMLElement>(`[data-form=\"${form}\"] input:not([disabled]), [data-form=\"${form}\"] select, [data-form=\"${form}\"] textarea`)?.focus();\n }, { injector: this.injector });\n }\n\n /** Runs a change and reloads the configuration, which every change may affect. */\n private run(request: Observable<unknown>, savedKey: string): void {\n this.busy.set(true);\n this.error.set(null);\n this.saved.set(null);\n this.actionSubscription?.unsubscribe();\n this.actionSubscription = request.subscribe({\n error: (error: unknown) => {\n this.busy.set(false);\n this.error.set(toNhAssistantError(error));\n },\n complete: () => {\n this.busy.set(false);\n this.form.set(null);\n this.confirming.set(null);\n this.comparison.set(null);\n this.versions.set(null);\n this.saved.set(savedKey);\n this.changed.emit();\n this.load();\n }\n });\n }\n}\n\nfunction blank(value: string): string | null {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction toNumber(value: string): number | null {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const parsed = Number(trimmed);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction numberText(value: number | null | undefined): string {\n return value === null || value === undefined ? '' : String(value);\n}\n","<section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading() || busy()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.run-config.title' | translate: { name: agent().displayName } }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.description' | translate }}</p>\n </div>\n </header>\n\n @if (saved(); as key) {\n <p class=\"message success\" role=\"status\">{{ key | translate }}</p>\n }\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading() && !configuration()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (configuration(); as config) {\n @if (problems().length > 0) {\n <div class=\"message warning\" role=\"status\" data-problems>\n <nh-assistant-icon name=\"warning\" />\n <div class=\"stack\">\n <strong>{{ 'nh-assistant.admin.run-config.problems.title' | translate }}</strong>\n <ul>\n @for (problem of problems(); track problem.kind + problem.id) {\n <li>\n {{ 'nh-assistant.admin.run-config.problems.kind.' + problem.kind | translate: { id: problem.id } }}\n {{ 'nh-assistant.admin.run-config.problems.code.' + problem.code | translate }}\n </li>\n }\n </ul>\n </div>\n </div>\n }\n\n @if (config.source === 'admin') {\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-settings-title'\" data-run-settings>\n <header class=\"section-header\">\n <h4 [id]=\"id + '-settings-title'\">{{ 'nh-assistant.admin.run-config.settings.title' | translate }}</h4>\n </header>\n @if (config.runSettings; as settings) {\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.run-config.settings.accountability.' + settings.accountability | translate }}</span>\n @if (settings.serviceAccountActorId) {\n <span class=\"mono\">{{ settings.serviceAccountActorId }}</span>\n }\n @if (settings.ruleHandler) {\n <span>{{ 'nh-assistant.admin.run-config.rule-handler-value' | translate: { name: settings.ruleHandler } }}</span>\n }\n @if (settings.approvalPolicy) {\n <span>{{ 'nh-assistant.admin.run-config.policy-value' | translate: { name: settings.approvalPolicy } }}</span>\n }\n <span>{{ 'nh-assistant.admin.agents.version' | translate: { version: settings.version } }}</span>\n @if (!settings.inEffect) {\n <span class=\"badge danger\">{{ 'nh-assistant.admin.run-config.out-of-effect' | translate }}</span>\n }\n </div>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.settings.rights' | translate }}</p>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.settings.empty' | translate }}</p>\n }\n @if (form() !== 'settings') {\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"editSettings()\">\n <nh-assistant-icon [name]=\"config.runSettings ? 'edit' : 'plus'\" />\n {{ (config.runSettings ? 'nh-assistant.admin.run-config.settings.edit' : 'nh-assistant.admin.run-config.settings.add') | translate }}\n </button>\n @if (config.runSettings) {\n @if (isConfirming('remove-settings', config.agentId)) {\n <span class=\"muted\">{{ 'nh-assistant.admin.run-config.settings.remove-explain' | translate }}</span>\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"removeSettings()\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"confirm('remove-settings', config.agentId)\">\n <nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.run-config.settings.remove' | translate }}\n </button>\n }\n }\n </div>\n } @else {\n <form class=\"stack\" data-form=\"settings\" (submit)=\"$event.preventDefault(); saveSettings()\">\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-accountability'\">{{ 'nh-assistant.admin.run-config.settings.accountability-label' | translate }}</label>\n <select [id]=\"id + '-accountability'\" [attr.aria-describedby]=\"id + '-accountability-hint'\" (change)=\"accountability.set($any(value($event)))\">\n @for (option of accountabilities; track option) {\n <option [value]=\"option\" [selected]=\"accountability() === option\">{{ 'nh-assistant.admin.run-config.settings.accountability.' + option | translate }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-accountability-hint'\">{{ 'nh-assistant.admin.run-config.settings.accountability-hint' | translate }}</p>\n </div>\n @if (accountability() === 'service-account') {\n <div class=\"field\">\n <label [for]=\"id + '-service-account'\">{{ 'nh-assistant.admin.run-config.settings.service-account' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n maxlength=\"256\"\n [id]=\"id + '-service-account'\"\n [value]=\"serviceAccount()\"\n [attr.aria-invalid]=\"fieldError('serviceAccountActorId') ? true : null\"\n [attr.aria-describedby]=\"id + '-service-account-hint'\"\n (input)=\"serviceAccount.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-service-account-hint'\">\n @if (fieldError('serviceAccountActorId'); as key) {\n <span class=\"error-text\">{{ key | translate }}</span>\n }\n </p>\n </div>\n }\n </div>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-rule-handler'\">{{ 'nh-assistant.admin.run-config.rule-handler' | translate }}</label>\n <select [id]=\"id + '-rule-handler'\" [attr.aria-invalid]=\"fieldError('ruleHandler') ? true : null\" (change)=\"ruleHandler.set(value($event))\">\n <option value=\"\" [selected]=\"ruleHandler() === ''\">{{ 'nh-assistant.admin.run-config.model' | translate }}</option>\n @for (handler of catalog()?.ruleHandlers ?? []; track handler.name) {\n <option [value]=\"handler.name\" [selected]=\"ruleHandler() === handler.name\">{{ handler.name }} · {{ handler.description }}</option>\n }\n </select>\n @if (fieldError('ruleHandler'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-policy'\">{{ 'nh-assistant.admin.run-config.approval-policy' | translate }}</label>\n <select [id]=\"id + '-policy'\" [attr.aria-invalid]=\"fieldError('approvalPolicy') ? true : null\" (change)=\"approvalPolicy.set(value($event))\">\n <option value=\"\" [selected]=\"approvalPolicy() === ''\">{{ 'nh-assistant.admin.run-config.none' | translate }}</option>\n @for (policy of catalog()?.approvalPolicies ?? []; track policy) {\n <option [value]=\"policy\" [selected]=\"approvalPolicy() === policy\">{{ policy }}</option>\n }\n </select>\n @if (fieldError('approvalPolicy'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-triage'\">{{ 'nh-assistant.admin.run-config.settings.triage' | translate }}</label>\n <select [id]=\"id + '-triage'\" [attr.aria-describedby]=\"id + '-triage-hint'\" (change)=\"triageProfile.set(value($event))\">\n <option value=\"\" [selected]=\"triageProfile() === ''\">{{ 'nh-assistant.admin.run-config.none' | translate }}</option>\n @for (profile of catalog()?.profiles ?? []; track profile) {\n <option [value]=\"profile\" [selected]=\"triageProfile() === profile\">{{ profile }}</option>\n }\n </select>\n <p class=\"hint\" [id]=\"id + '-triage-hint'\">{{ 'nh-assistant.admin.run-config.settings.triage-hint' | translate }}</p>\n </div>\n </div>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-retries'\">{{ 'nh-assistant.admin.run-config.settings.retries' | translate }}</label>\n <input type=\"number\" min=\"0\" max=\"10\" [id]=\"id + '-retries'\" [value]=\"retryCount()\" [attr.aria-invalid]=\"fieldError('retryCount') ? true : null\" (input)=\"retryCount.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-concurrent'\">{{ 'nh-assistant.admin.run-config.settings.max-concurrent' | translate }}</label>\n <input type=\"number\" min=\"1\" max=\"100\" [id]=\"id + '-concurrent'\" [value]=\"maxConcurrentRuns()\" [attr.aria-invalid]=\"fieldError('maxConcurrentRuns') ? true : null\" (input)=\"maxConcurrentRuns.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-per-subject'\">{{ 'nh-assistant.admin.run-config.settings.max-per-subject' | translate }}</label>\n <input type=\"number\" min=\"1\" max=\"1000\" [id]=\"id + '-per-subject'\" [value]=\"maxRunsPerSubjectPerDay()\" [attr.aria-invalid]=\"fieldError('maxRunsPerSubjectPerDay') ? true : null\" (input)=\"maxRunsPerSubjectPerDay.set(value($event))\" />\n </div>\n </div>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-run-tokens'\">{{ 'nh-assistant.admin.run-config.max-tokens' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-run-tokens'\" [value]=\"maxTokensPerRun()\" (input)=\"maxTokensPerRun.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-daily-calls'\">{{ 'nh-assistant.admin.run-config.daily-tool-calls' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-daily-calls'\" [value]=\"dailyToolCalls()\" [attr.aria-invalid]=\"fieldError('dailyBudget') ? true : null\" (input)=\"dailyToolCalls.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-daily-tokens'\">{{ 'nh-assistant.admin.run-config.daily-tokens' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-daily-tokens'\" [value]=\"dailyTokens()\" [attr.aria-invalid]=\"fieldError('dailyBudget') ? true : null\" (input)=\"dailyTokens.set(value($event))\" />\n </div>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.admin.run-config.budget-hint' | translate }}</p>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-elevated'\">{{ 'nh-assistant.admin.run-config.settings.elevated-reads' | translate }}</label>\n <select [id]=\"id + '-elevated'\" (change)=\"elevatedReads.set($any(value($event)))\">\n @for (mode of elevatedReadModes; track mode) {\n <option [value]=\"mode\" [selected]=\"elevatedReads() === mode\">{{ 'nh-assistant.admin.run-config.settings.elevated.' + mode | translate }}</option>\n }\n </select>\n </div>\n </div>\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"allowGatewayReads()\" (change)=\"allowGatewayReads.set(checked($event))\" />\n <span>\n {{ 'nh-assistant.admin.run-config.settings.gateway-reads' | translate }}\n @if (fieldError('allowGatewayReads'); as key) {\n <span class=\"error-text\">{{ key | translate }}</span>\n }\n </span>\n </label>\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"delegateFromInitiator()\" (change)=\"delegateFromInitiator.set(checked($event))\" />\n <span>{{ 'nh-assistant.admin.run-config.settings.delegate' | translate }}</span>\n </label>\n <div class=\"field\">\n <label [for]=\"id + '-settings-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input type=\"text\" autocomplete=\"off\" [id]=\"id + '-settings-reason'\" [maxLength]=\"maxReason\" [value]=\"reason()\" (input)=\"reason.set(value($event))\" />\n </div>\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancel()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"busy()\">{{ (busy() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}</button>\n </div>\n </form>\n }\n </section>\n }\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-skills-title'\" data-skills>\n <header class=\"section-header\">\n <div>\n <h4 [id]=\"id + '-skills-title'\">{{ 'nh-assistant.admin.agents.skills.title' | translate }}</h4>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.skills.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy() || !canAddRunData() || form() === 'skill'\" (click)=\"addSkill()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.run-config.skills.add' | translate }}\n </button>\n </header>\n @if (!canAddRunData()) {\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.needs-settings' | translate }}</p>\n }\n\n @if (form() === 'skill') {\n <form class=\"stack card\" data-form=\"skill\" (submit)=\"$event.preventDefault(); saveSkill()\">\n <h5>\n @if (editingSkill(); as editing) {\n {{ 'nh-assistant.admin.run-config.skills.edit-title' | translate: { skill: editing.skillId, version: editing.version } }}\n } @else {\n {{ 'nh-assistant.admin.run-config.skills.new-title' | translate }}\n }\n </h5>\n @if (!editingSkill()) {\n <div class=\"field\">\n <label [for]=\"id + '-skill-id'\">{{ 'nh-assistant.admin.run-config.skills.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n maxlength=\"64\"\n [id]=\"id + '-skill-id'\"\n [value]=\"skillId()\"\n [attr.aria-invalid]=\"skillId().length > 0 && skillIdInvalid() ? true : null\"\n [attr.aria-describedby]=\"id + '-skill-id-hint'\"\n (input)=\"skillId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-skill-id-hint'\">\n <span [class.error-text]=\"skillId().length > 0 && skillIdInvalid()\">{{ 'nh-assistant.admin.run-config.skills.id-hint' | translate }}</span>\n </p>\n </div>\n }\n <div class=\"field\">\n <label [for]=\"id + '-skill-description'\">{{ 'nh-assistant.admin.run-config.skills.description-label' | translate }}</label>\n <input\n type=\"text\"\n [id]=\"id + '-skill-description'\"\n [maxLength]=\"maxDescription\"\n [value]=\"skillDescription()\"\n [attr.aria-invalid]=\"fieldError('description') ? true : null\"\n [attr.aria-describedby]=\"id + '-skill-description-hint'\"\n (input)=\"skillDescription.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-skill-description-hint'\">\n @if (fieldError('description'); as key) {\n <span class=\"error-text\">{{ key | translate }}</span>\n } @else {\n <span>{{ 'nh-assistant.admin.run-config.skills.description-hint' | translate }}</span>\n }\n <span class=\"counter\">{{ 'nh-assistant.admin.characters' | translate: { count: skillDescription().length, max: maxDescription } }}</span>\n </p>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-skill-instructions'\">{{ 'nh-assistant.admin.run-config.skills.instructions' | translate }}</label>\n <textarea\n rows=\"6\"\n [id]=\"id + '-skill-instructions'\"\n [value]=\"skillInstructions()\"\n [attr.aria-invalid]=\"skillInstructions().length > maxInstructions ? true : null\"\n [attr.aria-describedby]=\"id + '-skill-instructions-hint'\"\n (input)=\"skillInstructions.set(value($event))\"></textarea>\n <p class=\"hint\" [id]=\"id + '-skill-instructions-hint'\">\n <span>{{ 'nh-assistant.admin.run-config.skills.instructions-hint' | translate }}</span>\n <span class=\"counter\" [class.error-text]=\"skillInstructions().length > maxInstructions\">{{ 'nh-assistant.admin.characters' | translate: { count: skillInstructions().length, max: maxInstructions } }}</span>\n </p>\n </div>\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.run-config.skills.tools' | translate }}</legend>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.skills.tools-hint' | translate }}</p>\n @for (selector of config.toolSelectors; track selector) {\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"skillTools().includes(selector)\" (change)=\"toggleTool(selector, checked($event))\" />\n <span class=\"mono\">{{ selector }}</span>\n </label>\n } @empty {\n <p class=\"muted\">{{ 'nh-assistant.admin.agent-editor.no-selectors' | translate }}</p>\n }\n @if (fieldError('tools'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </fieldset>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-skill-rules'\">{{ 'nh-assistant.admin.run-config.rule-handler' | translate }}</label>\n <select [id]=\"id + '-skill-rules'\" [attr.aria-invalid]=\"fieldError('ruleHandler') ? true : null\" (change)=\"skillRuleHandler.set(value($event))\">\n <option value=\"\" [selected]=\"skillRuleHandler() === ''\">{{ 'nh-assistant.admin.run-config.model' | translate }}</option>\n @for (handler of catalog()?.ruleHandlers ?? []; track handler.name) {\n <option [value]=\"handler.name\" [selected]=\"skillRuleHandler() === handler.name\">{{ handler.name }} · {{ handler.description }}</option>\n }\n </select>\n @if (fieldError('ruleHandler'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-skill-profile'\">{{ 'nh-assistant.admin.run-config.skills.profile' | translate }}</label>\n <select [id]=\"id + '-skill-profile'\" [attr.aria-invalid]=\"fieldError('profile') ? true : null\" (change)=\"skillProfile.set(value($event))\">\n <option value=\"\" [selected]=\"skillProfile() === ''\">{{ 'nh-assistant.admin.run-config.skills.agent-profile' | translate }}</option>\n @for (profile of catalog()?.profiles ?? []; track profile) {\n <option [value]=\"profile\" [selected]=\"skillProfile() === profile\">{{ profile }}</option>\n }\n </select>\n @if (fieldError('profile'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-skill-policy'\">{{ 'nh-assistant.admin.run-config.approval-policy' | translate }}</label>\n <select [id]=\"id + '-skill-policy'\" [attr.aria-invalid]=\"fieldError('approvalPolicy') ? true : null\" (change)=\"skillApprovalPolicy.set(value($event))\">\n <option value=\"\" [selected]=\"skillApprovalPolicy() === ''\">{{ 'nh-assistant.admin.run-config.skills.agent-policy' | translate }}</option>\n @for (policy of catalog()?.approvalPolicies ?? []; track policy) {\n <option [value]=\"policy\" [selected]=\"skillApprovalPolicy() === policy\">{{ policy }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-skill-tokens'\">{{ 'nh-assistant.admin.run-config.max-tokens' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-skill-tokens'\" [value]=\"skillMaxTokens()\" [attr.aria-invalid]=\"fieldError('maxTokensPerRun') ? true : null\" (input)=\"skillMaxTokens.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-skill-calls'\">{{ 'nh-assistant.admin.run-config.daily-tool-calls' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-skill-calls'\" [value]=\"skillDailyToolCalls()\" [attr.aria-invalid]=\"fieldError('dailyBudget') ? true : null\" (input)=\"skillDailyToolCalls.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-skill-daily-tokens'\">{{ 'nh-assistant.admin.run-config.daily-tokens' | translate }}</label>\n <input type=\"number\" min=\"1\" [id]=\"id + '-skill-daily-tokens'\" [value]=\"skillDailyTokens()\" [attr.aria-invalid]=\"fieldError('dailyBudget') ? true : null\" (input)=\"skillDailyTokens.set(value($event))\" />\n </div>\n </div>\n <p class=\"hint\">{{ 'nh-assistant.admin.run-config.budget-hint' | translate }}</p>\n @if (editingSkill()) {\n <fieldset class=\"subsection\" data-apply>\n <legend>{{ 'nh-assistant.admin.run-config.skills.apply' | translate }}</legend>\n <label class=\"check\">\n <input type=\"radio\" [name]=\"id + '-apply'\" value=\"shadow\" [checked]=\"skillApply() === 'shadow'\" (change)=\"skillApply.set('shadow')\" />\n <span>{{ 'nh-assistant.admin.run-config.skills.apply-shadow' | translate }}</span>\n </label>\n <label class=\"check\">\n <input type=\"radio\" [name]=\"id + '-apply'\" value=\"live\" [checked]=\"skillApply() === 'live'\" (change)=\"skillApply.set('live')\" />\n <span>{{ 'nh-assistant.admin.run-config.skills.apply-live' | translate }}</span>\n </label>\n </fieldset>\n } @else {\n <p class=\"hint\">{{ 'nh-assistant.admin.run-config.skills.starts-in-shadow' | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-skill-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input type=\"text\" autocomplete=\"off\" [id]=\"id + '-skill-reason'\" [maxLength]=\"maxReason\" [value]=\"reason()\" (input)=\"reason.set(value($event))\" />\n </div>\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancel()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"busy() || skillIdInvalid() || descriptionInvalid() || skillInstructions().length > maxInstructions\">\n {{ (busy() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n </form>\n }\n\n @if (config.codeSkills.length === 0 && config.dataSkills.length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.run-config.skills.empty' | translate }}</p>\n } @else {\n <ul class=\"skills\">\n @for (skill of config.codeSkills; track skill.skillId) {\n <li class=\"skill\" [attr.data-code-skill]=\"skill.skillId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ skill.skillId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.agents.source-code' | translate }}</span>\n </div>\n <p class=\"muted\">{{ skill.description }}</p>\n </li>\n }\n @for (skill of config.dataSkills; track skill.skillId) {\n <li class=\"skill\" [attr.data-data-skill]=\"skill.skillId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ skill.skillId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.agents.version' | translate: { version: skill.version } }}</span>\n @if (!skill.inEffect) {\n <span class=\"badge danger\">{{ 'nh-assistant.admin.run-config.out-of-effect' | translate }}</span>\n }\n @if (skill.candidate) {\n <span class=\"badge warning\" data-candidate-badge>{{ 'nh-assistant.admin.run-config.candidate.badge' | translate: { version: skill.candidate.version } }}</span>\n }\n </div>\n <p class=\"muted\">{{ skill.description }}</p>\n <div class=\"meta\">\n @if (skill.ruleHandler) {\n <span>{{ 'nh-assistant.admin.run-config.rule-handler-value' | translate: { name: skill.ruleHandler } }}</span>\n }\n @if (skill.profile) {\n <span>{{ 'nh-assistant.admin.run-config.profile-value' | translate: { name: skill.profile } }}</span>\n }\n <span>{{ 'nh-assistant.admin.agents.tool-count' | translate: { count: skill.tools.length } }}</span>\n <span>{{ 'nh-assistant.admin.run-config.changed' | translate: { user: skill.changedBy, date: (skill.changedAt | date: 'medium') } }}</span>\n </div>\n @if (skill.candidate; as candidate) {\n <div class=\"subsection\" data-candidate>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.candidate.explain' | translate: { version: candidate.version, description: candidate.description } }}</p>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [attr.aria-expanded]=\"comparison()?.skillId === skill.skillId\" (click)=\"toggleComparison(skill)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.run-config.candidate.compare' | translate }}\n </button>\n @if (isConfirming('promote', skill.skillId)) {\n <button class=\"primary\" type=\"button\" [disabled]=\"busy()\" (click)=\"promote(skill)\">{{ 'nh-assistant.admin.run-config.candidate.confirm-promote' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else if (isConfirming('discard', skill.skillId)) {\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"discard(skill)\">{{ 'nh-assistant.admin.run-config.candidate.confirm-discard' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"confirm('promote', skill.skillId)\">{{ 'nh-assistant.admin.run-config.candidate.promote' | translate }}</button>\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"confirm('discard', skill.skillId)\">{{ 'nh-assistant.admin.run-config.candidate.discard' | translate }}</button>\n }\n </div>\n @if (comparison(); as shown) {\n @if (shown.skillId === skill.skillId) {\n @if (shown.failed) {\n <p class=\"message error\" role=\"alert\">{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n } @else if (shown.result; as result) {\n <table class=\"summary-table\" data-comparison>\n <caption class=\"visually-hidden\">{{ 'nh-assistant.admin.run-config.candidate.comparison' | translate: { skill: skill.skillId } }}</caption>\n <thead>\n <tr>\n <th scope=\"col\">{{ 'nh-assistant.admin.evaluation.columns.measure' | translate }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.run-config.candidate.live-column' | translate: { version: result.live.version } }}</th>\n <th scope=\"col\">{{ 'nh-assistant.admin.run-config.candidate.candidate-column' | translate: { version: result.candidate.version } }}</th>\n </tr>\n </thead>\n <tbody>\n <tr><th scope=\"row\">{{ 'nh-assistant.admin.run-config.candidate.runs' | translate }}</th><td>{{ result.live.runs | number }}</td><td>{{ result.candidate.runs | number }}</td></tr>\n <tr><th scope=\"row\">{{ 'nh-assistant.admin.run-config.candidate.completed' | translate }}</th><td>{{ result.live.completed | number }}</td><td>{{ result.candidate.completed | number }}</td></tr>\n <tr><th scope=\"row\">{{ 'nh-assistant.admin.run-config.candidate.failed' | translate }}</th><td>{{ result.live.failed | number }}</td><td>{{ result.candidate.failed | number }}</td></tr>\n <tr><th scope=\"row\">{{ 'nh-assistant.admin.run-config.candidate.proposals' | translate }}</th><td>{{ result.live.proposals | number }}</td><td>{{ result.candidate.proposals | number }}</td></tr>\n <tr><th scope=\"row\">{{ 'nh-assistant.admin.run-config.candidate.tokens' | translate }}</th><td>{{ result.live.tokens | number }}</td><td>{{ result.candidate.tokens | number }}</td></tr>\n </tbody>\n </table>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.candidate.paired' | translate: { count: result.pairedEvents, date: (result.from | date: 'medium') } }}</p>\n } @else {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n }\n }\n }\n </div>\n }\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"editSkill(skill)\">\n <nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [attr.aria-expanded]=\"versions()?.skillId === skill.skillId\" (click)=\"toggleVersions(skill)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.run-config.skills.versions' | translate }}\n </button>\n @if (isConfirming('remove-skill', skill.skillId)) {\n <span class=\"muted\">{{ 'nh-assistant.admin.run-config.skills.remove-explain' | translate }}</span>\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"removeSkill(skill)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"confirm('remove-skill', skill.skillId)\">\n <nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}\n </button>\n }\n </div>\n @if (versions(); as shown) {\n @if (shown.skillId === skill.skillId) {\n @if (shown.failed) {\n <p class=\"message error\" role=\"alert\">{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n } @else if (shown.items; as items) {\n <ul class=\"history\" data-versions>\n @for (version of items; track version.version) {\n <li>\n <span class=\"badge\">{{ 'nh-assistant.admin.agents.version' | translate: { version: version.version } }}</span>\n <span class=\"badge\" [class.success]=\"version.status === 'live'\" [class.warning]=\"version.status === 'candidate'\">{{ 'nh-assistant.admin.run-config.status.' + version.status | translate }}</span>\n <span>{{ version.description }}</span>\n <span class=\"muted\">{{ 'nh-assistant.admin.run-config.changed' | translate: { user: version.createdBy, date: (version.createdAt | date: 'medium') } }}</span>\n @if (version.reason) {\n <span class=\"muted\">{{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: version.reason } }}</span>\n }\n </li>\n }\n </ul>\n } @else {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n }\n }\n }\n </li>\n }\n </ul>\n }\n </section>\n\n <section class=\"subsection\" [attr.aria-labelledby]=\"id + '-triggers-title'\" data-triggers>\n <header class=\"section-header\">\n <div>\n <h4 [id]=\"id + '-triggers-title'\">{{ 'nh-assistant.admin.run-config.triggers.title' | translate }}</h4>\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.triggers.description' | translate }}</p>\n </div>\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy() || !canAddRunData() || form() === 'trigger'\" (click)=\"addTrigger()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.run-config.triggers.add' | translate }}\n </button>\n </header>\n\n @if (form() === 'trigger') {\n <form class=\"stack card\" data-form=\"trigger\" (submit)=\"$event.preventDefault(); saveTrigger()\">\n <h5>\n @if (editingTrigger(); as editing) {\n {{ 'nh-assistant.admin.run-config.triggers.edit-title' | translate: { trigger: editing.triggerId } }}\n } @else {\n {{ 'nh-assistant.admin.run-config.triggers.new-title' | translate }}\n }\n </h5>\n @if (!editingTrigger()) {\n <div class=\"field\">\n <label [for]=\"id + '-trigger-id'\">{{ 'nh-assistant.admin.run-config.triggers.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n maxlength=\"64\"\n [id]=\"id + '-trigger-id'\"\n [value]=\"triggerId()\"\n [attr.aria-invalid]=\"(triggerId().length > 0 && triggerIdInvalid()) || fieldError('triggerId') ? true : null\"\n [attr.aria-describedby]=\"id + '-trigger-id-hint'\"\n (input)=\"triggerId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-trigger-id-hint'\">\n @if (fieldError('triggerId'); as key) {\n <span class=\"error-text\">{{ key | translate }}</span>\n } @else {\n <span [class.error-text]=\"triggerId().length > 0 && triggerIdInvalid()\">{{ 'nh-assistant.admin.run-config.skills.id-hint' | translate }}</span>\n }\n </p>\n </div>\n }\n <fieldset class=\"subsection\">\n <legend>{{ 'nh-assistant.admin.run-config.triggers.source' | translate }}</legend>\n <label class=\"check\">\n <input type=\"radio\" [name]=\"id + '-source'\" value=\"event\" [checked]=\"triggerSource() === 'event'\" (change)=\"setTriggerSource('event')\" />\n <span>{{ 'nh-assistant.admin.run-config.triggers.source-event' | translate }}</span>\n </label>\n <label class=\"check\">\n <input type=\"radio\" [name]=\"id + '-source'\" value=\"schedule\" [checked]=\"triggerSource() === 'schedule'\" (change)=\"setTriggerSource('schedule')\" />\n <span>{{ 'nh-assistant.admin.run-config.triggers.source-schedule' | translate }}</span>\n </label>\n </fieldset>\n @if (triggerSource() === 'event') {\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-trigger-event'\">{{ 'nh-assistant.admin.run-config.triggers.event' | translate }}</label>\n <select [id]=\"id + '-trigger-event'\" [attr.aria-invalid]=\"fieldError('event') ? true : null\" (change)=\"triggerEvent.set(value($event))\">\n <option value=\"\" [selected]=\"triggerEvent() === ''\" disabled>{{ 'nh-assistant.admin.run-config.choose' | translate }}</option>\n @for (event of catalog()?.triggerEvents ?? []; track event.name) {\n <option [value]=\"event.name\" [selected]=\"triggerEvent() === event.name\">{{ event.name }} · {{ event.description }}</option>\n }\n </select>\n @if (fieldError('event'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-trigger-debounce'\">{{ 'nh-assistant.admin.run-config.triggers.debounce' | translate }}</label>\n <input type=\"number\" min=\"0\" max=\"3600\" [id]=\"id + '-trigger-debounce'\" [value]=\"triggerDebounce()\" [attr.aria-invalid]=\"fieldError('debounceSeconds') ? true : null\" (input)=\"triggerDebounce.set(value($event))\" />\n </div>\n </div>\n } @else {\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-trigger-cron'\">{{ 'nh-assistant.admin.run-config.triggers.cron' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n autocomplete=\"off\"\n maxlength=\"128\"\n [id]=\"id + '-trigger-cron'\"\n [value]=\"triggerCron()\"\n [attr.aria-invalid]=\"fieldError('cron') ? true : null\"\n [attr.aria-describedby]=\"id + '-trigger-cron-hint'\"\n (input)=\"triggerCron.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-trigger-cron-hint'\">\n @if (fieldError('cron'); as key) {\n <span class=\"error-text\">{{ key | translate }}</span>\n } @else {\n <span>{{ 'nh-assistant.admin.run-config.triggers.cron-hint' | translate }}</span>\n }\n </p>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-trigger-zone'\">{{ 'nh-assistant.admin.run-config.triggers.time-zone' | translate }}</label>\n <input type=\"text\" class=\"mono\" autocomplete=\"off\" maxlength=\"64\" [id]=\"id + '-trigger-zone'\" [value]=\"triggerTimeZone()\" [attr.placeholder]=\"'UTC'\" (input)=\"triggerTimeZone.set(value($event))\" />\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-trigger-set'\">{{ 'nh-assistant.admin.run-config.triggers.subject-set' | translate }}</label>\n <select [id]=\"id + '-trigger-set'\" [attr.aria-invalid]=\"fieldError('subjectSet') ? true : null\" (change)=\"triggerSubjectSet.set(value($event))\">\n <option value=\"\" [selected]=\"triggerSubjectSet() === ''\" disabled>{{ 'nh-assistant.admin.run-config.choose' | translate }}</option>\n @for (set of catalog()?.subjectSets ?? []; track set.name) {\n <option [value]=\"set.name\" [selected]=\"triggerSubjectSet() === set.name\">{{ set.name }} · {{ set.description }}</option>\n }\n </select>\n @if (fieldError('subjectSet'); as key) {\n <p class=\"hint\"><span class=\"error-text\">{{ key | translate }}</span></p>\n }\n </div>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-trigger-message'\">{{ 'nh-assistant.admin.run-config.triggers.message' | translate }}</label>\n <textarea rows=\"2\" [id]=\"id + '-trigger-message'\" [maxLength]=\"maxMessage\" [value]=\"triggerMessage()\" [attr.aria-invalid]=\"fieldError('message') ? true : null\" (input)=\"triggerMessage.set(value($event))\"></textarea>\n </div>\n }\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-trigger-skill'\">{{ 'nh-assistant.admin.run-config.triggers.skill' | translate }}</label>\n <select [id]=\"id + '-trigger-skill'\" [attr.aria-invalid]=\"fieldError('skill') ? true : null\" (change)=\"triggerSkill.set(value($event))\">\n <option value=\"\" [selected]=\"triggerSkill() === ''\">{{ 'nh-assistant.admin.run-config.triggers.agent-routes' | translate }}</option>\n @for (skill of skillOptions(); track skill) {\n <option [value]=\"skill\" [selected]=\"triggerSkill() === skill\">{{ skill }}</option>\n }\n </select>\n </div>\n <div class=\"field\">\n <label [for]=\"id + '-trigger-conflict'\">{{ 'nh-assistant.admin.run-config.triggers.conflict' | translate }}</label>\n <select [id]=\"id + '-trigger-conflict'\" (change)=\"triggerConflict.set($any(value($event)))\">\n @for (conflict of conflicts; track conflict) {\n <option [value]=\"conflict\" [selected]=\"triggerConflict() === conflict\">{{ 'nh-assistant.admin.run-config.triggers.conflicts.' + conflict | translate }}</option>\n }\n </select>\n </div>\n </div>\n @if (!editingTrigger()) {\n <p class=\"hint\">{{ 'nh-assistant.admin.run-config.triggers.starts-in-shadow' | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-trigger-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input type=\"text\" autocomplete=\"off\" [id]=\"id + '-trigger-reason'\" [maxLength]=\"maxReason\" [value]=\"reason()\" (input)=\"reason.set(value($event))\" />\n </div>\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancel()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"busy() || triggerIdInvalid()\">{{ (busy() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}</button>\n </div>\n </form>\n }\n\n @if (config.codeTriggers.length === 0 && config.dataTriggers.length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.run-config.triggers.empty' | translate }}</p>\n } @else {\n <ul class=\"skills\">\n @for (trigger of config.codeTriggers; track trigger.triggerId) {\n <li class=\"skill\" [attr.data-code-trigger]=\"trigger.triggerId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ trigger.triggerId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.agents.source-code' | translate }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.run-config.triggers.sources.' + trigger.source | translate }}</span>\n </div>\n @if (trigger.skillId) {\n <p class=\"muted\">{{ 'nh-assistant.admin.run-config.triggers.skill-value' | translate: { skill: trigger.skillId } }}</p>\n }\n </li>\n }\n @for (trigger of config.dataTriggers; track trigger.triggerId) {\n <li class=\"skill\" [attr.data-data-trigger]=\"trigger.triggerId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ trigger.triggerId }}</span>\n <span class=\"badge\">{{ 'nh-assistant.admin.run-config.triggers.sources.' + trigger.source | translate }}</span>\n @if (trigger.shadow) {\n <span class=\"badge warning\" data-shadow-badge>{{ 'nh-assistant.admin.agents.shadow.badge' | translate }}</span>\n }\n @if (!trigger.inEffect) {\n <span class=\"badge danger\">{{ 'nh-assistant.admin.run-config.out-of-effect' | translate }}</span>\n }\n </div>\n <div class=\"meta\">\n @if (trigger.source === 'event') {\n <span class=\"mono\">{{ trigger.event }}</span>\n } @else {\n <span class=\"mono\">{{ trigger.cron }} {{ trigger.timeZone ?? 'UTC' }}</span>\n <span class=\"mono\">{{ trigger.subjectSet }}</span>\n }\n <span>{{ (trigger.skillId ? 'nh-assistant.admin.run-config.triggers.skill-value' : 'nh-assistant.admin.run-config.triggers.agent-routes') | translate: { skill: trigger.skillId } }}</span>\n <span>{{ 'nh-assistant.admin.run-config.triggers.conflicts.' + trigger.conflict | translate }}</span>\n <span>{{ 'nh-assistant.admin.agents.version' | translate: { version: trigger.version } }}</span>\n </div>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busy()\" (click)=\"editTrigger(trigger)\">\n <nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" [attr.data-trigger-shadow]=\"trigger.shadow ? 'live' : 'shadow'\" [disabled]=\"busy()\" (click)=\"setTriggerShadow(trigger, !trigger.shadow)\">\n {{ (trigger.shadow ? 'nh-assistant.admin.agents.shadow.action.live' : 'nh-assistant.admin.agents.shadow.action.shadow') | translate }}\n </button>\n @if (isConfirming('remove-trigger', trigger.triggerId)) {\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"removeTrigger(trigger)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" [disabled]=\"busy()\" (click)=\"confirm('remove-trigger', trigger.triggerId)\">\n <nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}\n </button>\n }\n </div>\n </li>\n }\n </ul>\n }\n </section>\n }\n</section>\n","import { DatePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n afterNextRender,\n computed,\n inject,\n signal,\n viewChild\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Observable, Subscription, forkJoin } from 'rxjs';\nimport {\n AdminAgent,\n AgentShadowMode,\n AgentShadowState,\n AgentSkillState,\n AgentState,\n McpServer,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n NhAssistantStore,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError,\n SetAgentStateRequest,\n ToolCatalogEntry\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminAgentEditorComponent } from './nh-assistant-admin-agent-editor.component';\nimport { NhAssistantAgentEvaluationComponent } from './nh-assistant-agent-evaluation.component';\nimport { NhAssistantAgentFeedbackReportComponent } from './nh-assistant-agent-feedback-report.component';\nimport { NhAssistantAgentRunConfigurationComponent } from './nh-assistant-agent-run-configuration.component';\n\nlet nextId = 0;\n\ntype AgentStateAction = SetAgentStateRequest['state'];\n\n/** The longest reason the server stores with a state change. */\nconst maxStateReason = 500;\n\n/**\n * Agent administration: code agents (override, reset) and agents created here (edit, delete),\n * and for every agent its run state with pause, stop and resume, its shadow mode and that of each\n * skill, and the technical account of an agent that answers to one, each with an optional reason.\n * Editing opens `nh-assistant-admin-agent-editor`; the feedback action opens\n * `nh-assistant-agent-feedback-report` for the agent, the evaluation action of an agent with\n * shadow variants opens `nh-assistant-agent-evaluation`, and the run configuration action opens\n * `nh-assistant-agent-run-configuration` for the skills, triggers and run settings defined as data.\n */\n@Component({\n selector: 'nh-assistant-admin-agents',\n standalone: true,\n imports: [\n DatePipe,\n TranslatePipe,\n NhAssistantTranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminAgentEditorComponent,\n NhAssistantAgentEvaluationComponent,\n NhAssistantAgentFeedbackReportComponent,\n NhAssistantAgentRunConfigurationComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-agents.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminAgentsComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private readonly store = inject(NhAssistantStore);\n private readonly injector = inject(Injector);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly backButton = viewChild<ElementRef<HTMLButtonElement>>('back');\n private readonly reasonInput = viewChild<ElementRef<HTMLInputElement>>('reasonInput');\n private subscription?: Subscription;\n private actionSubscription?: Subscription;\n\n readonly id = `nh-assistant-admin-agents-${nextId++}`;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly agents = signal<AdminAgent[]>([]);\n readonly tools = signal<ToolCatalogEntry[]>([]);\n readonly servers = signal<McpServer[]>([]);\n /** `undefined`: list; `null`: new agent; an agent: editing that agent. */\n readonly editing = signal<AdminAgent | null | undefined>(undefined);\n /** The agent whose feedback report is shown instead of the list. */\n readonly reporting = signal<AdminAgent | null>(null);\n /** The agent whose comparison with its shadow variants is shown instead of the list. */\n readonly evaluating = signal<AdminAgent | null>(null);\n /** The agent whose run configuration is shown instead of the list. */\n readonly configuring = signal<AdminAgent | null>(null);\n readonly confirming = signal<{ agentId: string; action: 'delete' | 'reset' } | null>(null);\n readonly busyAgentId = signal<string | null>(null);\n /** The state change whose reason is being entered, of the agent or one of its skills. */\n readonly changingState = signal<{ agentId: string; skillId?: string; state: AgentStateAction } | null>(null);\n /** The shadow mode change whose reason is being entered, of the agent or one of its skills. */\n readonly changingShadow = signal<{ agentId: string; skillId?: string; mode: AgentShadowMode } | null>(null);\n /** The change of the technical account being entered: a new account, or the one in code. */\n readonly changingAccount = signal<{ agentId: string; mode: 'set' | 'code' } | null>(null);\n readonly accountId = signal('');\n readonly stateReason = signal('');\n readonly maxReason = maxStateReason;\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.actionSubscription?.unsubscribe();\n });\n this.load();\n }\n\n load(): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = forkJoin([this.admin.getAgents(), this.admin.getTools(), this.admin.getMcpServers()]).subscribe({\n next: ([agents, tools, servers]) => {\n this.agents.set(agents);\n this.tools.set(tools);\n this.servers.set(servers);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n create(): void {\n this.error.set(null);\n this.editing.set(null);\n }\n\n edit(agent: AdminAgent): void {\n this.error.set(null);\n this.editing.set(agent);\n }\n\n /** Shows what people said when they rejected the agent's proposals. */\n openReport(agent: AdminAgent): void {\n this.error.set(null);\n this.confirming.set(null);\n this.reporting.set(agent);\n afterNextRender(() => this.backButton()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /** The shadow variants of an agent, by id. */\n variantsOf(agent: AdminAgent): string[] {\n return this.agents()\n .filter(item => item.shadowOf === agent.id)\n .map(item => item.id);\n }\n\n /** Compares the agent with its shadow variants. */\n openEvaluation(agent: AdminAgent): void {\n this.error.set(null);\n this.confirming.set(null);\n this.evaluating.set(agent);\n afterNextRender(() => this.backButton()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /**\n * Whether the agent can run on its own and so has a run configuration: an agent in code with runs,\n * or any agent created here, which gets run settings as data.\n */\n hasRunConfiguration(agent: AdminAgent): boolean {\n return agent.source === 'admin' || (agent.shadow !== null && agent.shadow !== undefined);\n }\n\n /** Shows the agent's skills, triggers and run settings defined as data. */\n openRunConfiguration(agent: AdminAgent): void {\n this.error.set(null);\n this.confirming.set(null);\n this.configuring.set(agent);\n afterNextRender(() => this.backButton()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /** Returns to the list, refreshed, and to the run configuration action of the agent. */\n closeRunConfiguration(): void {\n const agentId = this.configuring()?.id;\n this.configuring.set(null);\n this.refreshAgents();\n if (agentId !== undefined) {\n afterNextRender(() => {\n const action = Array.from(this.host.nativeElement.querySelectorAll<HTMLButtonElement>('[data-run-config-agent]'))\n .find(item => item.dataset['runConfigAgent'] === agentId);\n action?.focus();\n }, { injector: this.injector });\n }\n }\n\n /** Returns to the list and to the evaluation action of the agent whose comparison was open. */\n closeEvaluation(): void {\n const agentId = this.evaluating()?.id;\n this.evaluating.set(null);\n if (agentId !== undefined) {\n afterNextRender(() => {\n const action = Array.from(this.host.nativeElement.querySelectorAll<HTMLButtonElement>('[data-evaluation-agent]'))\n .find(item => item.dataset['evaluationAgent'] === agentId);\n action?.focus();\n }, { injector: this.injector });\n }\n }\n\n /** Returns to the list and to the feedback action of the agent whose report was open. */\n closeReport(): void {\n const agentId = this.reporting()?.id;\n this.reporting.set(null);\n if (agentId !== undefined) {\n afterNextRender(() => {\n const host = this.host.nativeElement;\n const action = Array.from(host.querySelectorAll<HTMLButtonElement>('[data-feedback-agent]'))\n .find(item => item.dataset['feedbackAgent'] === agentId);\n action?.focus();\n }, { injector: this.injector });\n }\n }\n\n onSaved(agent: AdminAgent): void {\n this.agents.update(agents => agents.some(item => item.id === agent.id)\n ? agents.map(item => item.id === agent.id ? agent : item)\n : [...agents, agent]);\n this.editing.set(undefined);\n this.refreshChat();\n }\n\n /** The state changes the agent allows: none for an agent that is disabled in code. */\n stateActions(agent: AdminAgent): AgentStateAction[] {\n switch (agent.runState) {\n case 'active':\n return ['paused', 'stopped'];\n case 'paused':\n return ['active', 'stopped'];\n case 'stopped':\n return ['active'];\n default:\n return [];\n }\n }\n\n /** The state changes a skill allows. */\n skillActions(skill: AgentSkillState): AgentStateAction[] {\n switch (skill.runState) {\n case 'active':\n return ['paused', 'stopped'];\n case 'paused':\n return ['active', 'stopped'];\n default:\n return ['active'];\n }\n }\n\n /** Opens the reason form of a state change of the agent or, with a skill, of that skill. */\n askState(agent: AdminAgent, state: AgentStateAction, skill?: AgentSkillState): void {\n this.closeForms();\n this.changingState.set({ agentId: agent.id, skillId: skill?.skillId, state });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n /**\n * The shadow modes an agent or skill can change to: the opposite of its own mode, and the mode\n * in code once an administrator overrode it. A shadow variant, and an agent without runs that\n * only chats, offer none.\n */\n shadowActions(shadow: AgentShadowState | null | undefined): AgentShadowMode[] {\n if (!shadow || shadow.locked) {\n return [];\n }\n const own = shadow.override ?? shadow.configured;\n const actions: AgentShadowMode[] = [own ? 'live' : 'shadow'];\n return shadow.override === null ? actions : [...actions, 'code'];\n }\n\n /** Opens the reason form of a shadow mode change of the agent or, with a skill, of that skill. */\n askShadow(agent: AdminAgent, mode: AgentShadowMode, skill?: AgentSkillState): void {\n this.closeForms();\n this.changingShadow.set({ agentId: agent.id, skillId: skill?.skillId, mode });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n isChangingShadow(agentId: string, mode: AgentShadowMode, skillId?: string): boolean {\n const change = this.changingShadow();\n return change?.agentId === agentId && change.mode === mode && change.skillId === skillId;\n }\n\n applyShadow(agent: AdminAgent): void {\n const change = this.changingShadow();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const reason = this.stateReason().trim();\n const request = { mode: change.mode, reason: reason.length > 0 ? reason : null };\n if (change.skillId !== undefined) {\n this.run(\n agent.id,\n this.admin.setSkillShadow(agent.id, change.skillId, request),\n skill => this.replace(withSkill(agent, skill)));\n return;\n }\n\n this.run(\n agent.id,\n this.admin.setAgentShadow(agent.id, request),\n state => this.replace(withState(agent, state)));\n }\n\n /** Opens the form that changes the technical account, or returns to the one in code. */\n askAccount(agent: AdminAgent, mode: 'set' | 'code'): void {\n this.closeForms();\n this.changingAccount.set({ agentId: agent.id, mode });\n afterNextRender(() => this.reasonInput()?.nativeElement.focus(), { injector: this.injector });\n }\n\n isChangingAccount(agentId: string, mode: 'set' | 'code'): boolean {\n const change = this.changingAccount();\n return change?.agentId === agentId && change.mode === mode;\n }\n\n applyAccount(agent: AdminAgent): void {\n const change = this.changingAccount();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const actorId = change.mode === 'set' ? this.accountId().trim() : null;\n if (actorId === '') {\n return;\n }\n const reason = this.stateReason().trim();\n this.run(\n agent.id,\n this.admin.setServiceAccount(agent.id, { actorId, reason: reason.length > 0 ? reason : null }),\n state => this.replace(withState(agent, state)));\n }\n\n isChangingState(agentId: string, state: AgentStateAction, skillId?: string): boolean {\n const change = this.changingState();\n return change?.agentId === agentId && change.state === state && change.skillId === skillId;\n }\n\n applyState(agent: AdminAgent): void {\n const change = this.changingState();\n if (change?.agentId !== agent.id) {\n return;\n }\n\n const reason = this.stateReason().trim();\n const request = { state: change.state, reason: reason.length > 0 ? reason : null };\n if (change.skillId !== undefined) {\n this.run(\n agent.id,\n this.admin.setSkillState(agent.id, change.skillId, request),\n skill => this.replace(withSkill(agent, skill)));\n return;\n }\n\n this.run(\n agent.id,\n this.admin.setAgentState(agent.id, request),\n state => this.replace(withState(agent, state)));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n\n confirm(agentId: string, action: 'delete' | 'reset'): void {\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n this.confirming.set({ agentId, action });\n }\n\n isConfirming(agentId: string, action: 'delete' | 'reset'): boolean {\n const confirming = this.confirming();\n return confirming?.agentId === agentId && confirming.action === action;\n }\n\n reset(agent: AdminAgent): void {\n this.run(agent.id, this.admin.resetAgent(agent.id), updated => this.replace(updated));\n }\n\n remove(agent: AdminAgent): void {\n this.run<void>(agent.id, this.admin.deleteAgent(agent.id), () => {\n this.agents.update(agents => agents.filter(item => item.id !== agent.id));\n });\n }\n\n private run<T>(agentId: string, request: Observable<T>, done: (result: T) => void): void {\n this.busyAgentId.set(agentId);\n this.confirming.set(null);\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n this.error.set(null);\n this.actionSubscription?.unsubscribe();\n this.actionSubscription = request.subscribe({\n next: result => done(result),\n complete: () => {\n this.busyAgentId.set(null);\n this.refreshChat();\n },\n error: (error: unknown) => {\n this.busyAgentId.set(null);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n /** Closes the open confirmation and change forms before another opens; one is open at a time. */\n private closeForms(): void {\n this.confirming.set(null);\n this.error.set(null);\n this.stateReason.set('');\n this.accountId.set('');\n this.changingState.set(null);\n this.changingShadow.set(null);\n this.changingAccount.set(null);\n }\n\n private replace(agent: AdminAgent): void {\n this.agents.update(agents => agents.map(item => item.id === agent.id ? agent : item));\n }\n\n /**\n * Reloads the agents behind the visible list, for example their skills after the run\n * configuration changed; the list stays as it is when that fails.\n */\n private refreshAgents(): void {\n this.subscription?.unsubscribe();\n this.subscription = this.admin.getAgents().subscribe({\n next: agents => this.agents.set(agents),\n error: () => undefined\n });\n this.refreshChat();\n }\n\n /** Agent changes affect the agent picker of the panel. */\n private refreshChat(): void {\n void this.store.reloadStatus();\n }\n}\n\nfunction withState(agent: AdminAgent, state: AgentState): AdminAgent {\n return {\n ...agent,\n isEnabled: state.runState !== 'stopped',\n runState: state.runState,\n stateChangedAt: state.changedAt,\n stateChangedBy: state.changedBy,\n stateReason: state.reason,\n waitingInputs: state.waitingInputs,\n skills: state.skills ?? agent.skills,\n shadow: state.shadow ?? agent.shadow,\n serviceAccount: state.serviceAccount === undefined ? agent.serviceAccount : state.serviceAccount\n };\n}\n\nfunction withSkill(agent: AdminAgent, skill: AgentSkillState): AdminAgent {\n return {\n ...agent,\n skills: (agent.skills ?? []).map(item => item.skillId === skill.skillId ? skill : item)\n };\n}\n","@if (editing() !== undefined) {\n <nh-assistant-admin-agent-editor\n [agent]=\"editing() ?? null\"\n [tools]=\"tools()\"\n [servers]=\"servers()\"\n (saved)=\"onSaved($event)\"\n (cancelled)=\"editing.set(undefined)\" />\n} @else if (reporting(); as agent) {\n <div class=\"stack\">\n <div>\n <button #back class=\"secondary\" type=\"button\" (click)=\"closeReport()\">\n {{ 'nh-assistant.admin.feedback.back' | translate }}\n </button>\n </div>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.agent' | translate: { name: agent.displayName, id: agent.id } }}</p>\n <nh-assistant-agent-feedback-report [agentId]=\"agent.id\" />\n </div>\n} @else if (configuring(); as agent) {\n <div class=\"stack\">\n <div>\n <button #back class=\"secondary\" type=\"button\" (click)=\"closeRunConfiguration()\">\n {{ 'nh-assistant.admin.run-config.back' | translate }}\n </button>\n </div>\n <nh-assistant-agent-run-configuration [agent]=\"agent\" />\n </div>\n} @else if (evaluating(); as agent) {\n <div class=\"stack\">\n <div>\n <button #back class=\"secondary\" type=\"button\" (click)=\"closeEvaluation()\">\n {{ 'nh-assistant.admin.evaluation.back' | translate }}\n </button>\n </div>\n <p class=\"muted\">{{ 'nh-assistant.admin.feedback.agent' | translate: { name: agent.displayName, id: agent.id } }}</p>\n <nh-assistant-agent-evaluation [agentId]=\"agent.id\" [variants]=\"variantsOf(agent)\" />\n </div>\n} @else {\n <section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.agents.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.description' | translate }}</p>\n </div>\n <button class=\"primary\" type=\"button\" [disabled]=\"loading() || loadFailed()\" (click)=\"create()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.agents.new' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (agents().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.agents.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (agent of agents(); track agent.id) {\n <li class=\"card\" [class.inactive]=\"agent.runState !== 'active'\" [attr.aria-busy]=\"busyAgentId() === agent.id\">\n <div class=\"card-header\">\n <strong>{{ agent.displayName }}</strong>\n <span class=\"mono muted\">{{ agent.id }}</span>\n <span class=\"badge\">{{ (agent.source === 'code' ? 'nh-assistant.admin.agents.source-code' : 'nh-assistant.admin.agents.source-admin') | translate }}</span>\n @if (agent.isOverridden) {\n <span class=\"badge warning\">{{ 'nh-assistant.admin.agents.overridden' | translate }}</span>\n }\n <span\n class=\"badge\"\n [class.success]=\"agent.runState === 'active'\"\n [class.warning]=\"agent.runState === 'paused'\"\n [class.danger]=\"agent.runState === 'stopped'\">{{ 'nh-assistant.admin.agents.state.' + agent.runState | translate }}</span>\n @if (agent.shadow?.shadow) {\n <span class=\"badge warning\" data-shadow-badge>{{ 'nh-assistant.admin.agents.shadow.badge' | translate }}</span>\n }\n </div>\n @if (agent.description) {\n <p class=\"muted\">{{ agent.description }}</p>\n }\n @if (agent.runState === 'configured-off') {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.configured-off-hint' | translate }}</p>\n } @else if (agent.runState !== 'active') {\n <p class=\"muted\">\n @if (agent.stateChangedAt) {\n {{ 'nh-assistant.admin.agents.state.changed' | translate: { user: agent.stateChangedBy, date: (agent.stateChangedAt | date: 'medium') } }}\n }\n @if (agent.stateReason) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: agent.stateReason } }}\n }\n </p>\n @if (agent.runState === 'paused') {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.waiting' | translate: { count: agent.waitingInputs } }}</p>\n }\n }\n @if (agent.shadow; as shadow) {\n @if (shadow.shadow) {\n <p class=\"muted\">\n {{ (shadow.locked ? 'nh-assistant.admin.agents.shadow.locked' : 'nh-assistant.admin.agents.shadow.hint') | translate }}\n @if (shadow.changedAt && shadow.override !== null) {\n {{ 'nh-assistant.admin.agents.shadow.changed' | translate: { user: shadow.changedBy, date: (shadow.changedAt | date: 'medium') } }}\n }\n @if (shadow.reason && shadow.override !== null) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: shadow.reason } }}\n }\n </p>\n }\n }\n @if (agent.serviceAccount; as account) {\n <p class=\"muted\" data-service-account>\n <span class=\"mono\">{{ 'nh-assistant.admin.agents.service-account.label' | translate: { account: account.actorId } }}</span>\n @if (account.overridden) {\n {{ 'nh-assistant.admin.agents.service-account.configured' | translate: { account: account.configuredActorId } }}\n @if (account.reason) {\n {{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: account.reason } }}\n }\n }\n </p>\n }\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.agents.autonomy.' + agent.autonomy | translate }}</span>\n <span>{{ 'nh-assistant.admin.agents.tool-count' | translate: { count: agent.toolSelectors.length } }}</span>\n <span>{{ 'nh-assistant.admin.agents.server-count' | translate: { count: agent.mcpServerIds.length } }}</span>\n <span>{{ 'nh-assistant.admin.agents.version' | translate: { version: agent.version } }}</span>\n @if (agent.requiredPolicy) {\n <span class=\"mono\">{{ agent.requiredPolicy }}</span>\n }\n </div>\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"edit(agent)\">\n <nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}\n </button>\n @for (action of stateActions(agent); track action) {\n <button\n type=\"button\"\n [class.secondary]=\"action !== 'stopped'\"\n [class.danger]=\"action === 'stopped'\"\n [attr.aria-expanded]=\"isChangingState(agent.id, action)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askState(agent, action)\">\n {{ 'nh-assistant.admin.agents.state.action.' + action | translate }}\n </button>\n }\n @if (agent.runState !== 'configured-off') {\n @for (mode of shadowActions(agent.shadow); track mode) {\n <button\n class=\"secondary\"\n type=\"button\"\n [attr.data-shadow-action]=\"mode\"\n [attr.aria-expanded]=\"isChangingShadow(agent.id, mode)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askShadow(agent, mode)\">\n {{ 'nh-assistant.admin.agents.shadow.action.' + mode | translate }}\n </button>\n }\n }\n @if (agent.serviceAccount; as account) {\n <button\n class=\"secondary\"\n type=\"button\"\n data-account-action=\"set\"\n [attr.aria-expanded]=\"isChangingAccount(agent.id, 'set')\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askAccount(agent, 'set')\">\n {{ 'nh-assistant.admin.agents.service-account.action.set' | translate }}\n </button>\n @if (account.overridden) {\n <button\n class=\"secondary\"\n type=\"button\"\n data-account-action=\"code\"\n [attr.aria-expanded]=\"isChangingAccount(agent.id, 'code')\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askAccount(agent, 'code')\">\n {{ 'nh-assistant.admin.agents.service-account.action.code' | translate }}\n </button>\n }\n }\n @if (hasRunConfiguration(agent)) {\n <button class=\"secondary\" type=\"button\" [attr.data-run-config-agent]=\"agent.id\" (click)=\"openRunConfiguration(agent)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.agents.run-config' | translate }}\n </button>\n }\n <button class=\"secondary\" type=\"button\" [attr.data-feedback-agent]=\"agent.id\" (click)=\"openReport(agent)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.agents.feedback' | translate }}\n </button>\n @if (variantsOf(agent).length > 0) {\n <button class=\"secondary\" type=\"button\" [attr.data-evaluation-agent]=\"agent.id\" (click)=\"openEvaluation(agent)\">\n <nh-assistant-icon name=\"list\" />{{ 'nh-assistant.admin.agents.evaluation' | translate }}\n </button>\n }\n @if (agent.source === 'code' && agent.isOverridden) {\n @if (isConfirming(agent.id, 'reset')) {\n <span class=\"muted\">{{ 'nh-assistant.admin.agents.reset-keeps-state' | translate }}</span>\n <button class=\"danger\" type=\"button\" (click)=\"reset(agent)\">{{ 'nh-assistant.admin.agents.confirm-reset' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"secondary\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"confirm(agent.id, 'reset')\">\n <nh-assistant-icon name=\"refresh\" />{{ 'nh-assistant.admin.agents.reset' | translate }}\n </button>\n }\n }\n @if (agent.source === 'admin') {\n @if (isConfirming(agent.id, 'delete')) {\n <button class=\"danger\" type=\"button\" (click)=\"remove(agent)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirming.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" [disabled]=\"busyAgentId() !== null\" (click)=\"confirm(agent.id, 'delete')\">\n <nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}\n </button>\n }\n }\n </div>\n @if (agent.skills?.length) {\n <ul class=\"skills\" [attr.aria-label]=\"'nh-assistant.admin.agents.skills.title' | translate\">\n @for (skill of agent.skills; track skill.skillId) {\n <li class=\"skill\" [attr.data-skill]=\"skill.skillId\">\n <div class=\"card-header\">\n <span class=\"mono\">{{ skill.skillId }}</span>\n <span\n class=\"badge\"\n [class.success]=\"skill.runState === 'active'\"\n [class.warning]=\"skill.runState === 'paused'\"\n [class.danger]=\"skill.runState === 'stopped'\">{{ 'nh-assistant.admin.agents.state.' + skill.runState | translate }}</span>\n @if (skill.shadow?.shadow) {\n <span class=\"badge warning\" data-shadow-badge>{{ 'nh-assistant.admin.agents.shadow.badge' | translate }}</span>\n }\n </div>\n <p class=\"muted\">{{ skill.description }}</p>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.agents.skills.usage' | translate: { calls: skill.toolCallsToday, tokens: skill.tokensToday } }}</span>\n @if (skill.dailyToolCalls !== null) {\n <span>{{ 'nh-assistant.admin.agents.skills.budget' | translate: { calls: skill.dailyToolCalls, tokens: skill.dailyTokens } }}</span>\n }\n @if (skill.runState === 'paused') {\n <span>{{ 'nh-assistant.admin.agents.state.waiting' | translate: { count: skill.waitingInputs } }}</span>\n }\n @if (skill.reason) {\n <span>{{ 'nh-assistant.admin.agents.state.reason' | translate: { reason: skill.reason } }}</span>\n }\n </div>\n @if (agent.runState !== 'configured-off') {\n <div class=\"card-actions\">\n @for (action of skillActions(skill); track action) {\n <button\n type=\"button\"\n [class.secondary]=\"action !== 'stopped'\"\n [class.danger]=\"action === 'stopped'\"\n [attr.aria-label]=\"('nh-assistant.admin.agents.state.action.' + action | translate) + ' ' + skill.skillId\"\n [attr.aria-expanded]=\"isChangingState(agent.id, action, skill.skillId)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askState(agent, action, skill)\">\n {{ 'nh-assistant.admin.agents.state.action.' + action | translate }}\n </button>\n }\n @for (mode of shadowActions(skill.shadow); track mode) {\n <button\n class=\"secondary\"\n type=\"button\"\n [attr.data-shadow-action]=\"mode\"\n [attr.aria-label]=\"('nh-assistant.admin.agents.shadow.action.' + mode | translate) + ' ' + skill.skillId\"\n [attr.aria-expanded]=\"isChangingShadow(agent.id, mode, skill.skillId)\"\n [disabled]=\"busyAgentId() !== null\"\n (click)=\"askShadow(agent, mode, skill)\">\n {{ 'nh-assistant.admin.agents.shadow.action.' + mode | translate }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n @if (changingState(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" (submit)=\"$event.preventDefault(); applyState(agent)\">\n @if (change.skillId) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.skills.explain.' + change.state | translate: { skill: change.skillId } }}</p>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.state.explain.' + change.state | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" [class.primary]=\"change.state !== 'stopped'\" [class.danger]=\"change.state === 'stopped'\" [disabled]=\"busyAgentId() !== null\">\n {{ 'nh-assistant.admin.agents.state.confirm.' + change.state | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingState.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n @if (changingShadow(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" data-shadow-form (submit)=\"$event.preventDefault(); applyShadow(agent)\">\n @if (change.skillId) {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.shadow.skill-explain.' + change.mode | translate: { skill: change.skillId } }}</p>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.shadow.explain.' + change.mode | translate }}</p>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-shadow-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-shadow-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" class=\"primary\" [disabled]=\"busyAgentId() !== null\">\n {{ 'nh-assistant.admin.agents.shadow.confirm.' + change.mode | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingShadow.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n @if (changingAccount(); as change) {\n @if (change.agentId === agent.id) {\n <form class=\"stack\" data-account-form (submit)=\"$event.preventDefault(); applyAccount(agent)\">\n <p class=\"muted\">{{ 'nh-assistant.admin.agents.service-account.explain.' + change.mode | translate: { account: agent.serviceAccount?.configuredActorId } }}</p>\n @if (change.mode === 'set') {\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-account'\">{{ 'nh-assistant.admin.agents.service-account.input-label' | translate }}</label>\n <input\n #reasonInput\n type=\"text\"\n autocomplete=\"off\"\n required\n [id]=\"id + '-' + agent.id + '-account'\"\n maxLength=\"256\"\n [value]=\"accountId()\"\n (input)=\"accountId.set(value($event))\" />\n </div>\n }\n <div class=\"field\">\n <label [for]=\"id + '-' + agent.id + '-account-reason'\">{{ 'nh-assistant.admin.agents.state.reason-label' | translate }}</label>\n <input\n type=\"text\"\n autocomplete=\"off\"\n [id]=\"id + '-' + agent.id + '-account-reason'\"\n [maxLength]=\"maxReason\"\n [value]=\"stateReason()\"\n (input)=\"stateReason.set(value($event))\" />\n </div>\n <div class=\"card-actions\">\n <button type=\"submit\" class=\"primary\" [disabled]=\"busyAgentId() !== null || (change.mode === 'set' && accountId().trim() === '')\">\n {{ 'nh-assistant.admin.agents.service-account.confirm.' + change.mode | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"changingAccount.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n </div>\n </form>\n }\n }\n </li>\n }\n </ul>\n }\n </section>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpAuthMode,\n McpServer,\n McpServerInput,\n ɵNH_ASSISTANT_DASH_CASE as NH_ASSISTANT_DASH_CASE,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/**\n * What happens to the stored secret on save. `keep` omits `secret`, `replace` sends the\n * new value and `clear` sends `\"\"`. The stored value is never shown.\n */\nexport type NhAssistantSecretAction = 'keep' | 'replace' | 'clear';\n\nlet nextId = 0;\n\n/** Creates or edits one MCP server with a write-only secret. */\n@Component({\n selector: 'nh-assistant-admin-mcp-server-editor',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-server-editor.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpServerEditorComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n\n /** The server to edit, or null for a new server. */\n readonly server = input<McpServer | null>(null);\n readonly saved = output<McpServer>();\n readonly cancelled = output<void>();\n\n readonly id = `nh-assistant-server-editor-${nextId++}`;\n readonly authModes: readonly McpAuthMode[] = ['none', 'bearer', 'api-key', 'forward-user-token'];\n\n readonly serverId = signal('');\n readonly displayName = signal('');\n readonly url = signal('');\n readonly authMode = signal<McpAuthMode>('none');\n readonly headerName = signal('');\n readonly requiredPolicy = signal('');\n readonly isEnabled = signal(true);\n readonly secretAction = signal<NhAssistantSecretAction>('keep');\n /** The new secret while typing. Never filled from the server. */\n readonly secret = signal('');\n readonly submitted = signal(false);\n readonly saving = signal(false);\n readonly error = signal<NhAssistantError | null>(null);\n\n readonly isNew = computed(() => this.server() === null);\n readonly hasSecret = computed(() => this.server()?.hasSecret === true);\n readonly usesSecret = computed(() => this.authMode() === 'bearer' || this.authMode() === 'api-key');\n readonly showSecretInput = computed(() => this.usesSecret() && (!this.hasSecret() || this.secretAction() === 'replace'));\n readonly idInvalid = computed(() => this.isNew() && (this.serverId().length > 40 || !NH_ASSISTANT_DASH_CASE.test(this.serverId())));\n readonly nameMissing = computed(() => this.displayName().trim().length === 0);\n readonly urlInvalid = computed(() => !isAllowedUrl(this.url().trim()));\n readonly valid = computed(() => !this.idInvalid() && !this.nameMissing() && !this.urlInvalid());\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n\n effect(() => {\n const server = this.server();\n untracked(() => this.reset(server));\n });\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n setSecretAction(action: NhAssistantSecretAction): void {\n this.secretAction.set(action);\n this.secret.set('');\n }\n\n onSecretInput(event: Event): void {\n this.secret.set(this.value(event));\n if (!this.hasSecret()) {\n this.secretAction.set(this.secret().length > 0 ? 'replace' : 'keep');\n }\n }\n\n save(): void {\n this.submitted.set(true);\n if (!this.valid() || this.saving()) {\n return;\n }\n\n const authMode = this.authMode();\n const policy = this.requiredPolicy().trim();\n const header = this.headerName().trim();\n const input: McpServerInput = {\n id: this.isNew() ? this.serverId() : this.server()!.id,\n displayName: this.displayName().trim(),\n url: this.url().trim(),\n authMode,\n headerName: authMode === 'api-key' && header.length > 0 ? header : null,\n requiredPolicy: policy.length > 0 ? policy : null,\n isEnabled: this.isEnabled()\n };\n\n // Write-only secret: omitted keeps the stored value, \"\" clears it.\n const action = this.secretAction();\n if (!this.usesSecret() && this.hasSecret()) {\n input.secret = '';\n } else if (action === 'clear') {\n input.secret = '';\n } else if (action === 'replace' && this.secret().length > 0) {\n input.secret = this.secret();\n }\n\n const existing = this.server();\n const request = existing ? this.admin.updateMcpServer(existing.id, input) : this.admin.createMcpServer(input);\n\n this.saving.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = request.subscribe({\n next: server => {\n this.saving.set(false);\n this.secret.set('');\n this.saved.emit(server);\n },\n error: (error: unknown) => {\n this.saving.set(false);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private reset(server: McpServer | null): void {\n this.serverId.set(server?.id ?? '');\n this.displayName.set(server?.displayName ?? '');\n this.url.set(server?.url ?? 'https://');\n this.authMode.set(server?.authMode ?? 'none');\n this.headerName.set(server?.headerName ?? '');\n this.requiredPolicy.set(server?.requiredPolicy ?? '');\n this.isEnabled.set(server?.isEnabled ?? true);\n this.secretAction.set('keep');\n this.secret.set('');\n this.submitted.set(false);\n this.error.set(null);\n }\n}\n\nfunction isAllowedUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === 'https:' || (url.protocol === 'http:' && url.hostname === 'localhost');\n } catch {\n return false;\n }\n}\n","<form class=\"section card\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"saving()\" autocomplete=\"off\" (submit)=\"$event.preventDefault(); save()\">\n <h3 [id]=\"id + '-title'\">\n @if (server(); as current) {\n {{ 'nh-assistant.admin.server-editor.edit-title' | translate: { name: current.displayName } }}\n } @else {\n {{ 'nh-assistant.admin.server-editor.new-title' | translate }}\n }\n </h3>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-id'\">{{ 'nh-assistant.admin.server-editor.id' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n [id]=\"id + '-id'\"\n [value]=\"serverId()\"\n [disabled]=\"!isNew()\"\n [attr.aria-describedby]=\"id + '-id-hint'\"\n [attr.aria-invalid]=\"submitted() && idInvalid() ? true : null\"\n (input)=\"serverId.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-id-hint'\">\n <span [class.error-text]=\"submitted() && idInvalid()\">\n {{ (submitted() && idInvalid() ? 'nh-assistant.admin.invalid-id' : 'nh-assistant.admin.server-editor.id-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-name'\">{{ 'nh-assistant.admin.server-editor.display-name' | translate }}</label>\n <input\n type=\"text\"\n [id]=\"id + '-name'\"\n [value]=\"displayName()\"\n [attr.aria-invalid]=\"submitted() && nameMissing() ? true : null\"\n [attr.aria-describedby]=\"id + '-name-hint'\"\n (input)=\"displayName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-name-hint'\">\n @if (submitted() && nameMissing()) {\n <span class=\"error-text\">{{ 'nh-assistant.admin.required' | translate }}</span>\n }\n </p>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-url'\">{{ 'nh-assistant.admin.server-editor.url' | translate }}</label>\n <input\n type=\"url\"\n class=\"mono\"\n inputmode=\"url\"\n [id]=\"id + '-url'\"\n [value]=\"url()\"\n [attr.aria-describedby]=\"id + '-url-hint'\"\n [attr.aria-invalid]=\"submitted() && urlInvalid() ? true : null\"\n (input)=\"url.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-url-hint'\">\n <span [class.error-text]=\"submitted() && urlInvalid()\">\n {{ (submitted() && urlInvalid() ? 'nh-assistant.admin.server-editor.url-invalid' : 'nh-assistant.admin.server-editor.url-hint') | translate }}\n </span>\n </p>\n </div>\n\n <div class=\"grid\">\n <div class=\"field\">\n <label [for]=\"id + '-auth'\">{{ 'nh-assistant.admin.server-editor.auth-mode' | translate }}</label>\n <select [id]=\"id + '-auth'\" (change)=\"authMode.set($any(value($event)))\">\n @for (mode of authModes; track mode) {\n <option [value]=\"mode\" [selected]=\"authMode() === mode\">{{ 'nh-assistant.admin.mcp.auth.' + mode | translate }}</option>\n }\n </select>\n </div>\n\n @if (authMode() === 'api-key') {\n <div class=\"field\">\n <label [for]=\"id + '-header'\">{{ 'nh-assistant.admin.server-editor.header-name' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n placeholder=\"X-Api-Key\"\n [id]=\"id + '-header'\"\n [value]=\"headerName()\"\n [attr.aria-describedby]=\"id + '-header-hint'\"\n (input)=\"headerName.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-header-hint'\">{{ 'nh-assistant.admin.server-editor.header-name-hint' | translate }}</p>\n </div>\n }\n </div>\n\n @if (authMode() === 'forward-user-token') {\n <p class=\"message warning\" role=\"note\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.server-editor.forward-warning' | translate }}</p>\n }\n\n @if (usesSecret()) {\n <fieldset class=\"field\">\n <legend>{{ 'nh-assistant.admin.server-editor.secret' | translate }}</legend>\n @if (hasSecret()) {\n <div class=\"meta secret-state\">\n @switch (secretAction()) {\n @case ('clear') {\n <span class=\"badge warning\">{{ 'nh-assistant.admin.server-editor.secret-will-clear' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('keep')\">{{ 'nh-assistant.admin.server-editor.secret-undo' | translate }}</button>\n }\n @case ('replace') {\n <span class=\"badge\">{{ 'nh-assistant.admin.server-editor.secret-set' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('keep')\">{{ 'nh-assistant.admin.server-editor.secret-undo' | translate }}</button>\n }\n @default {\n <span class=\"badge success\">{{ 'nh-assistant.admin.server-editor.secret-set' | translate }}</span>\n <button class=\"secondary\" type=\"button\" (click)=\"setSecretAction('replace')\">{{ 'nh-assistant.admin.server-editor.secret-replace' | translate }}</button>\n <button class=\"danger\" type=\"button\" (click)=\"setSecretAction('clear')\">{{ 'nh-assistant.admin.server-editor.secret-clear' | translate }}</button>\n }\n }\n </div>\n } @else {\n <p class=\"muted\">{{ 'nh-assistant.admin.server-editor.secret-none' | translate }}</p>\n }\n @if (showSecretInput()) {\n <label class=\"visually-hidden\" [for]=\"id + '-secret'\">{{ 'nh-assistant.admin.server-editor.secret-new' | translate }}</label>\n <input\n type=\"password\"\n class=\"mono\"\n autocomplete=\"new-password\"\n spellcheck=\"false\"\n [id]=\"id + '-secret'\"\n [attr.placeholder]=\"'nh-assistant.admin.server-editor.secret-new' | translate\"\n [attr.aria-describedby]=\"id + '-secret-hint'\"\n [value]=\"secret()\"\n (input)=\"onSecretInput($event)\" />\n }\n <p class=\"hint\" [id]=\"id + '-secret-hint'\">{{ 'nh-assistant.admin.server-editor.secret-hint' | translate }}</p>\n </fieldset>\n }\n\n <div class=\"field\">\n <label [for]=\"id + '-policy'\">{{ 'nh-assistant.admin.server-editor.required-policy' | translate }}</label>\n <input\n type=\"text\"\n class=\"mono\"\n [id]=\"id + '-policy'\"\n [value]=\"requiredPolicy()\"\n [attr.aria-describedby]=\"id + '-policy-hint'\"\n (input)=\"requiredPolicy.set(value($event))\" />\n <p class=\"hint\" [id]=\"id + '-policy-hint'\">{{ 'nh-assistant.admin.server-editor.required-policy-hint' | translate }}</p>\n </div>\n\n <label class=\"check\">\n <input type=\"checkbox\" [checked]=\"isEnabled()\" (change)=\"isEnabled.set(checked($event))\" />\n <span>{{ 'nh-assistant.admin.server-editor.enabled' | translate }}</span>\n </label>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"cancelled.emit()\">{{ 'nh-assistant.admin.cancel' | translate }}</button>\n <button class=\"primary\" type=\"submit\" [disabled]=\"saving()\">\n {{ (saving() ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.save') | translate }}\n </button>\n </div>\n</form>\n","import { ChangeDetectionStrategy, Component, DestroyRef, computed, effect, inject, input, output, signal, untracked } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpServer,\n McpTool,\n McpToolEffect,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\n\n/** Unsaved changes of one tool row. */\ninterface ToolDraft {\n isEnabled: boolean;\n effect: McpToolEffect;\n descriptionOverride: string;\n}\n\nlet nextId = 0;\n\n/**\n * The tools of one MCP server. Every tool starts disabled as a change that needs approval;\n * the administrator enables it and chooses the effect. Remote annotations appear as hints\n * only, and a changed remote input schema is shown as a warning.\n */\n@Component({\n selector: 'nh-assistant-admin-mcp-tools',\n standalone: true,\n imports: [TranslatePipe, NhAssistantTranslatePipe, NhAssistantIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-tools.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpToolsComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n private rowSubscription?: Subscription;\n\n readonly server = input.required<McpServer>();\n readonly closed = output<void>();\n /** Emitted after a sync so the host can refresh the server's sync status. */\n readonly synced = output<void>();\n\n readonly id = `nh-assistant-mcp-tools-${nextId++}`;\n readonly effects: readonly McpToolEffect[] = ['mutation', 'read-only'];\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly syncing = signal(false);\n readonly savingTool = signal<string | null>(null);\n readonly savedTool = signal<string | null>(null);\n readonly tools = signal<McpTool[]>([]);\n readonly drafts = signal<Record<string, ToolDraft>>({});\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.rowSubscription?.unsubscribe();\n });\n\n effect(() => {\n const server = this.server();\n untracked(() => this.load(server.id));\n });\n }\n\n load(serverId = this.server().id): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.getMcpTools(serverId).subscribe({\n next: tools => {\n this.setTools(tools);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n sync(): void {\n this.syncing.set(true);\n this.error.set(null);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.syncMcpServer(this.server().id).subscribe({\n next: tools => {\n this.setTools(tools);\n this.syncing.set(false);\n this.synced.emit();\n },\n error: (error: unknown) => {\n this.syncing.set(false);\n this.error.set(toNhAssistantError(error));\n this.synced.emit();\n }\n });\n }\n\n draft(tool: McpTool): ToolDraft {\n return this.drafts()[tool.remoteName] ?? toDraft(tool);\n }\n\n isDirty(tool: McpTool): boolean {\n const draft = this.draft(tool);\n return draft.isEnabled !== tool.isEnabled || draft.effect !== tool.effect ||\n draft.descriptionOverride !== (tool.descriptionOverride ?? '');\n }\n\n change(tool: McpTool, patch: Partial<ToolDraft>): void {\n this.savedTool.set(null);\n this.drafts.update(drafts => ({ ...drafts, [tool.remoteName]: { ...this.draft(tool), ...patch } }));\n }\n\n value(event: Event): string {\n return (event.target as HTMLInputElement | HTMLSelectElement).value;\n }\n\n checked(event: Event): boolean {\n return (event.target as HTMLInputElement).checked;\n }\n\n save(tool: McpTool): void {\n const draft = this.draft(tool);\n const override = draft.descriptionOverride.trim();\n\n this.savingTool.set(tool.remoteName);\n this.savedTool.set(null);\n this.error.set(null);\n this.rowSubscription?.unsubscribe();\n this.rowSubscription = this.admin.updateMcpTool(this.server().id, tool.remoteName, {\n isEnabled: draft.isEnabled,\n effect: draft.effect,\n descriptionOverride: override.length > 0 ? override : null\n }).subscribe({\n next: updated => {\n this.tools.update(tools => tools.map(item => item.remoteName === updated.remoteName ? updated : item));\n this.drafts.update(drafts => {\n const { [updated.remoteName]: removed, ...rest } = drafts;\n return rest;\n });\n this.savingTool.set(null);\n this.savedTool.set(updated.remoteName);\n },\n error: (error: unknown) => {\n this.savingTool.set(null);\n this.error.set(toNhAssistantError(error));\n }\n });\n }\n\n private setTools(tools: McpTool[]): void {\n this.tools.set(tools);\n this.drafts.set({});\n this.savedTool.set(null);\n }\n}\n\nfunction toDraft(tool: McpTool): ToolDraft {\n return { isEnabled: tool.isEnabled, effect: tool.effect, descriptionOverride: tool.descriptionOverride ?? '' };\n}\n","<section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading() || syncing()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.tools.title' | translate: { name: server().displayName } }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.tools.description' | translate }}</p>\n </div>\n <div class=\"actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"closed.emit()\">{{ 'nh-assistant.admin.tools.back' | translate }}</button>\n <button class=\"primary\" type=\"button\" [disabled]=\"syncing()\" (click)=\"sync()\">\n <nh-assistant-icon name=\"refresh\" />{{ (syncing() ? 'nh-assistant.admin.mcp.syncing' : 'nh-assistant.admin.mcp.sync') | translate }}\n </button>\n </div>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (tools().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.tools.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (tool of tools(); track tool.remoteName) {\n <li class=\"card\" [class.inactive]=\"!tool.isEnabled\" [attr.data-status]=\"tool.status\" [attr.aria-busy]=\"savingTool() === tool.remoteName\">\n <div class=\"card-header\">\n <strong class=\"mono\">{{ tool.remoteName }}</strong>\n <span class=\"badge\"\n [class.warning]=\"tool.status === 'schema-changed'\"\n [class.danger]=\"tool.status === 'missing'\">{{ 'nh-assistant.admin.tools.status.' + tool.status | translate }}</span>\n <span class=\"badge\" [class.success]=\"tool.isEnabled\">{{ (tool.isEnabled ? 'nh-assistant.admin.enabled' : 'nh-assistant.admin.disabled') | translate }}</span>\n @if (tool.readOnlyHint !== null) {\n <span class=\"badge hint\" [attr.title]=\"'nh-assistant.admin.tools.description' | translate\">\n {{ (tool.readOnlyHint ? 'nh-assistant.admin.tools.hint-read-only' : 'nh-assistant.admin.tools.hint-mutation') | translate }}\n </span>\n }\n </div>\n <span class=\"mono muted\">{{ tool.localId }}</span>\n\n @if (tool.status === 'schema-changed') {\n <p class=\"message warning\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.tools.schema-changed-warning' | translate }}</p>\n }\n @if (tool.status === 'missing') {\n <p class=\"message error\"><nh-assistant-icon name=\"warning\" />{{ 'nh-assistant.admin.tools.missing-warning' | translate }}</p>\n }\n\n <p class=\"muted\"><span class=\"label\">{{ 'nh-assistant.admin.tools.remote-description' | translate }}</span>{{ tool.description }}</p>\n\n <div class=\"grid\">\n <label class=\"check\">\n <input\n type=\"checkbox\"\n [checked]=\"draft(tool).isEnabled\"\n [disabled]=\"tool.status === 'missing'\"\n (change)=\"change(tool, { isEnabled: checked($event) })\" />\n <span>{{ 'nh-assistant.admin.tools.enabled' | translate }}</span>\n </label>\n <div class=\"field\">\n <label [for]=\"id + '-effect-' + $index\">{{ 'nh-assistant.admin.tools.effect' | translate }}</label>\n <select [id]=\"id + '-effect-' + $index\" (change)=\"change(tool, { effect: $any(value($event)) })\">\n @for (effect of effects; track effect) {\n <option [value]=\"effect\" [selected]=\"draft(tool).effect === effect\">{{ 'nh-assistant.admin.effect.' + effect | translate }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"field\">\n <label [for]=\"id + '-override-' + $index\">{{ 'nh-assistant.admin.tools.description-override' | translate }}</label>\n <input\n type=\"text\"\n maxlength=\"1000\"\n [id]=\"id + '-override-' + $index\"\n [value]=\"draft(tool).descriptionOverride\"\n [attr.aria-describedby]=\"id + '-override-hint-' + $index\"\n (input)=\"change(tool, { descriptionOverride: value($event) })\" />\n <p class=\"hint\" [id]=\"id + '-override-hint-' + $index\">{{ 'nh-assistant.admin.tools.description-override-hint' | translate }}</p>\n </div>\n\n <div class=\"card-actions\">\n <button class=\"primary\" type=\"button\" [disabled]=\"!isDirty(tool) || savingTool() !== null\" (click)=\"save(tool)\">\n {{ (savingTool() === tool.remoteName ? 'nh-assistant.admin.saving' : 'nh-assistant.admin.tools.save') | translate }}\n </button>\n @if (savedTool() === tool.remoteName) {\n <span class=\"badge success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.saved' | translate }}</span>\n }\n </div>\n </li>\n }\n </ul>\n }\n</section>\n","import { DatePipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Subscription } from 'rxjs';\nimport {\n McpServer,\n McpServerTestResult,\n NhAssistantAdminApiService,\n NhAssistantError,\n ɵnhAssistantErrorKeys as nhAssistantErrorKeys,\n nhAssistantErrorMessageKey,\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n ɵNhAssistantTranslatePipe as NhAssistantTranslatePipe,\n ɵtoNhAssistantError as toNhAssistantError\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminMcpServerEditorComponent } from './nh-assistant-admin-mcp-server-editor.component';\nimport { NhAssistantAdminMcpToolsComponent } from './nh-assistant-admin-mcp-tools.component';\n\n/** Result of the latest connection test per server. */\ninterface TestState {\n running: boolean;\n result: McpServerTestResult | null;\n}\n\nlet nextId = 0;\n\n/**\n * MCP server administration: list, connection test, tool sync, the server editor and the\n * tool table of one server.\n */\n@Component({\n selector: 'nh-assistant-admin-mcp-servers',\n standalone: true,\n imports: [\n DatePipe,\n TranslatePipe,\n NhAssistantTranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminMcpServerEditorComponent,\n NhAssistantAdminMcpToolsComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin-mcp-servers.component.html',\n styleUrl: '../nh-assistant-admin-shared.scss'\n})\nexport class NhAssistantAdminMcpServersComponent {\n private readonly admin = inject(NhAssistantAdminApiService);\n private subscription?: Subscription;\n private readonly actions = new Subscription();\n\n readonly id = `nh-assistant-admin-mcp-${nextId++}`;\n readonly loading = signal(true);\n readonly loadFailed = signal(false);\n readonly servers = signal<McpServer[]>([]);\n /** `undefined`: list; `null`: new server; a server: editing that server. */\n readonly editing = signal<McpServer | null | undefined>(undefined);\n readonly toolsOf = signal<McpServer | null>(null);\n readonly tests = signal<Record<string, TestState>>({});\n readonly confirmingDelete = signal<string | null>(null);\n readonly error = signal<NhAssistantError | null>(null);\n readonly errorKeys = computed(() => nhAssistantErrorKeys(this.error()));\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.subscription?.unsubscribe();\n this.actions.unsubscribe();\n });\n this.load();\n }\n\n load(): void {\n this.loading.set(true);\n this.loadFailed.set(false);\n this.subscription?.unsubscribe();\n this.subscription = this.admin.getMcpServers().subscribe({\n next: servers => {\n this.servers.set(servers);\n this.loading.set(false);\n },\n error: () => {\n this.loading.set(false);\n this.loadFailed.set(true);\n }\n });\n }\n\n /** Reloads the list silently, for example after a sync changed the sync status. */\n refresh(): void {\n this.actions.add(this.admin.getMcpServers().subscribe({ next: servers => this.servers.set(servers), error: () => undefined }));\n }\n\n create(): void {\n this.error.set(null);\n this.editing.set(null);\n }\n\n edit(server: McpServer): void {\n this.error.set(null);\n this.editing.set(server);\n }\n\n onSaved(server: McpServer): void {\n this.servers.update(servers => servers.some(item => item.id === server.id)\n ? servers.map(item => item.id === server.id ? server : item)\n : [...servers, server]);\n this.editing.set(undefined);\n }\n\n test(server: McpServer): void {\n this.setTest(server.id, { running: true, result: null });\n this.actions.add(this.admin.testMcpServer(server.id).subscribe({\n next: result => this.setTest(server.id, { running: false, result }),\n error: (error: unknown) => {\n const failure = toNhAssistantError(error);\n this.setTest(server.id, { running: false, result: { ok: false, code: failure.code, toolCount: null } });\n }\n }));\n }\n\n testState(serverId: string): TestState | null {\n return this.tests()[serverId] ?? null;\n }\n\n testErrorKeys(code: string | null): string[] {\n return code ? [nhAssistantErrorMessageKey(code), 'nh-assistant.errors.generic'] : ['nh-assistant.errors.generic'];\n }\n\n remove(server: McpServer): void {\n this.confirmingDelete.set(null);\n this.error.set(null);\n this.actions.add(this.admin.deleteMcpServer(server.id).subscribe({\n complete: () => this.servers.update(servers => servers.filter(item => item.id !== server.id)),\n error: (error: unknown) => this.error.set(toNhAssistantError(error))\n }));\n }\n\n private setTest(serverId: string, state: TestState): void {\n this.tests.update(tests => ({ ...tests, [serverId]: state }));\n }\n}\n","@if (editing() !== undefined) {\n <nh-assistant-admin-mcp-server-editor [server]=\"editing() ?? null\" (saved)=\"onSaved($event)\" (cancelled)=\"editing.set(undefined)\" />\n} @else if (toolsOf(); as server) {\n <nh-assistant-admin-mcp-tools [server]=\"server\" (closed)=\"toolsOf.set(null); refresh()\" (synced)=\"refresh()\" />\n} @else {\n <section class=\"section\" [attr.aria-labelledby]=\"id + '-title'\" [attr.aria-busy]=\"loading()\">\n <header class=\"section-header\">\n <div>\n <h3 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.mcp.title' | translate }}</h3>\n <p class=\"muted\">{{ 'nh-assistant.admin.mcp.description' | translate }}</p>\n </div>\n <button class=\"primary\" type=\"button\" [disabled]=\"loading() || loadFailed()\" (click)=\"create()\">\n <nh-assistant-icon name=\"plus\" />{{ 'nh-assistant.admin.mcp.new' | translate }}\n </button>\n </header>\n\n @if (error(); as failure) {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ errorKeys() | nhAssistantTranslate: failure.code }}</p>\n }\n\n @if (loading()) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (loadFailed()) {\n <div class=\"state\" role=\"alert\">\n <p>{{ 'nh-assistant.admin.load-failed' | translate }}</p>\n <button class=\"secondary\" type=\"button\" (click)=\"load()\">{{ 'nh-assistant.admin.retry' | translate }}</button>\n </div>\n } @else if (servers().length === 0) {\n <p class=\"state\">{{ 'nh-assistant.admin.mcp.empty' | translate }}</p>\n } @else {\n <ul class=\"cards\">\n @for (server of servers(); track server.id) {\n <li class=\"card\" [class.inactive]=\"!server.isEnabled\">\n <div class=\"card-header\">\n <strong>{{ server.displayName }}</strong>\n <span class=\"mono muted\">{{ server.id }}</span>\n <span class=\"badge\" [class.success]=\"server.isEnabled\">{{ (server.isEnabled ? 'nh-assistant.admin.enabled' : 'nh-assistant.admin.disabled') | translate }}</span>\n @if (server.lastSyncStatus) {\n <span class=\"badge\" [class.success]=\"server.lastSyncStatus === 'ok'\" [class.danger]=\"server.lastSyncStatus === 'failed'\">\n {{ (server.lastSyncStatus === 'ok' ? 'nh-assistant.admin.mcp.sync-ok' : 'nh-assistant.admin.mcp.sync-failed') | translate }}\n </span>\n }\n </div>\n <span class=\"mono muted url\">{{ server.url }}</span>\n <div class=\"meta\">\n <span>{{ 'nh-assistant.admin.mcp.auth.' + server.authMode | translate }}</span>\n @if (server.authMode === 'bearer' || server.authMode === 'api-key') {\n <span class=\"badge\" [class.success]=\"server.hasSecret\" [class.warning]=\"!server.hasSecret\">\n {{ (server.hasSecret ? 'nh-assistant.admin.mcp.secret-set' : 'nh-assistant.admin.mcp.no-secret') | translate }}\n </span>\n }\n <span>\n @if (server.lastSyncAt) {\n {{ 'nh-assistant.admin.mcp.last-sync' | translate: { date: (server.lastSyncAt | date: 'medium') } }}\n } @else {\n {{ 'nh-assistant.admin.mcp.never-synced' | translate }}\n }\n </span>\n <span>\n @if (server.assignedAgentIds.length > 0) {\n {{ 'nh-assistant.admin.mcp.assigned' | translate: { agents: server.assignedAgentIds.join(', ') } }}\n } @else {\n {{ 'nh-assistant.admin.mcp.unassigned' | translate }}\n }\n </span>\n </div>\n\n @if (testState(server.id); as state) {\n @if (state.running) {\n <p class=\"muted\" role=\"status\">{{ 'nh-assistant.admin.mcp.testing' | translate }}</p>\n } @else if (state.result?.ok) {\n <p class=\"message success\" role=\"status\"><nh-assistant-icon name=\"check\" />{{ 'nh-assistant.admin.mcp.test-ok' | translate: { count: state.result?.toolCount ?? 0 } }}</p>\n } @else {\n <p class=\"message error\" role=\"alert\"><nh-assistant-icon name=\"warning\" />{{ testErrorKeys(state.result?.code ?? null) | nhAssistantTranslate: (state.result?.code ?? '') }}</p>\n }\n }\n\n <div class=\"card-actions\">\n <button class=\"secondary\" type=\"button\" (click)=\"edit(server)\"><nh-assistant-icon name=\"edit\" />{{ 'nh-assistant.admin.edit' | translate }}</button>\n <button class=\"secondary\" type=\"button\" [disabled]=\"testState(server.id)?.running\" (click)=\"test(server)\">\n <nh-assistant-icon name=\"link\" />{{ 'nh-assistant.admin.mcp.test' | translate }}\n </button>\n <button class=\"secondary\" type=\"button\" (click)=\"toolsOf.set(server)\"><nh-assistant-icon name=\"tool\" />{{ 'nh-assistant.admin.mcp.tools' | translate }}</button>\n @if (confirmingDelete() === server.id) {\n <button class=\"danger\" type=\"button\" (click)=\"remove(server)\">{{ 'nh-assistant.admin.confirm-delete' | translate }}</button>\n <button class=\"secondary\" type=\"button\" (click)=\"confirmingDelete.set(null)\">{{ 'nh-assistant.admin.keep' | translate }}</button>\n } @else {\n <button class=\"danger\" type=\"button\" (click)=\"confirmingDelete.set(server.id)\"><nh-assistant-icon name=\"trash\" />{{ 'nh-assistant.admin.delete' | translate }}</button>\n }\n </div>\n </li>\n }\n </ul>\n }\n </section>\n}\n","import { ChangeDetectionStrategy, Component, ElementRef, afterNextRender, inject, input, signal } from '@angular/core';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport {\n ɵNhAssistantIconComponent as NhAssistantIconComponent,\n NhAssistantStore\n} from '@newheap/platform-ai-chat';\nimport { NhAssistantAdminAgentsComponent } from './agents/nh-assistant-admin-agents.component';\nimport { NhAssistantAdminContextComponent } from './context/nh-assistant-admin-context.component';\nimport { NhAssistantAdminMcpServersComponent } from './mcp/nh-assistant-admin-mcp-servers.component';\n\nexport type NhAssistantAdminTab = 'context' | 'agents' | 'mcp-servers';\n\nlet nextId = 0;\n\n/**\n * The assistant administration page with the tabs Context, Agents and MCP servers. The host\n * routes to it and guards the route with its admin permission; the component additionally\n * shows a no-access state unless the server reports `canAdminister`.\n */\n@Component({\n selector: 'nh-assistant-admin',\n standalone: true,\n imports: [\n TranslatePipe,\n NhAssistantIconComponent,\n NhAssistantAdminContextComponent,\n NhAssistantAdminAgentsComponent,\n NhAssistantAdminMcpServersComponent\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nh-assistant-admin.component.html',\n styleUrl: './nh-assistant-admin.component.scss'\n})\nexport class NhAssistantAdminComponent {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly store = inject(NhAssistantStore);\n\n /** Tab shown first. */\n readonly initialTab = input<NhAssistantAdminTab>('context');\n\n readonly id = `nh-assistant-admin-${nextId++}`;\n readonly tabs: readonly NhAssistantAdminTab[] = ['context', 'agents', 'mcp-servers'];\n readonly activeTab = signal<NhAssistantAdminTab | null>(null);\n readonly ready = signal(false);\n\n constructor() {\n afterNextRender(() => {\n void this.store.initialize().then(() => this.ready.set(true));\n });\n }\n\n selected(): NhAssistantAdminTab {\n return this.activeTab() ?? this.initialTab();\n }\n\n select(tab: NhAssistantAdminTab): void {\n this.activeTab.set(tab);\n }\n\n /** Arrow keys, Home and End move between tabs as the ARIA tabs pattern describes. */\n onTabKeydown(event: KeyboardEvent): void {\n const index = this.tabs.indexOf(this.selected());\n const last = this.tabs.length - 1;\n const targets: Record<string, number> = {\n ArrowRight: index === last ? 0 : index + 1,\n ArrowLeft: index === 0 ? last : index - 1,\n Home: 0,\n End: last\n };\n const next = targets[event.key];\n if (next === undefined) {\n return;\n }\n\n event.preventDefault();\n this.select(this.tabs[next]);\n this.host.nativeElement.querySelector<HTMLElement>(`#${this.id}-tab-${this.tabs[next]}`)?.focus();\n }\n}\n","<section class=\"admin\" [attr.aria-labelledby]=\"id + '-title'\">\n <header class=\"page-header\">\n <nh-assistant-icon class=\"page-icon\" name=\"admin\" />\n <div>\n <h2 [id]=\"id + '-title'\">{{ 'nh-assistant.admin.title' | translate }}</h2>\n <p>{{ 'nh-assistant.admin.description' | translate }}</p>\n </div>\n </header>\n\n @if (!ready() || (store.statusLoading() && !store.enabled())) {\n <p class=\"state\" role=\"status\">{{ 'nh-assistant.admin.loading' | translate }}</p>\n } @else if (!store.enabled()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.panel.unavailable-title' | translate }}</p>\n <p>{{ 'nh-assistant.panel.unavailable-description' | translate }}</p>\n </div>\n } @else if (!store.canAdminister()) {\n <div class=\"state\">\n <nh-assistant-icon class=\"state-icon\" name=\"warning\" />\n <p class=\"state-title\">{{ 'nh-assistant.admin.forbidden-title' | translate }}</p>\n <p>{{ 'nh-assistant.admin.forbidden-description' | translate }}</p>\n </div>\n } @else {\n <div class=\"tabs\" role=\"tablist\" [attr.aria-label]=\"'nh-assistant.admin.tabs-label' | translate\" (keydown)=\"onTabKeydown($event)\">\n @for (tab of tabs; track tab) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"tab\"\n [id]=\"id + '-tab-' + tab\"\n [attr.aria-selected]=\"selected() === tab\"\n [attr.aria-controls]=\"id + '-panel'\"\n [attr.tabindex]=\"selected() === tab ? 0 : -1\"\n (click)=\"select(tab)\">\n {{ 'nh-assistant.admin.tabs.' + tab | translate }}\n </button>\n }\n </div>\n\n <div class=\"panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"id + '-panel'\" [attr.aria-labelledby]=\"id + '-tab-' + selected()\">\n @switch (selected()) {\n @case ('context') {\n <nh-assistant-admin-context />\n }\n @case ('agents') {\n <nh-assistant-admin-agents />\n }\n @case ('mcp-servers') {\n <nh-assistant-admin-mcp-servers />\n }\n }\n </div>\n }\n</section>\n","/*\n * Public API surface of @newheap/platform-ai-chat/admin.\n *\n * The administration page is a separate entry point so hosts load it only on their lazy\n * admin route and the chat panel stays small.\n */\nexport * from './nh-assistant-admin.component';\nexport * from './context/nh-assistant-admin-context.component';\nexport * from './agents/nh-assistant-admin-agents.component';\nexport * from './agents/nh-assistant-admin-agent-editor.component';\nexport * from './agents/nh-assistant-agent-evaluation.component';\nexport * from './agents/nh-assistant-agent-feedback-report.component';\nexport * from './agents/nh-assistant-agent-run-configuration.component';\nexport * from './mcp/nh-assistant-admin-mcp-servers.component';\nexport * from './mcp/nh-assistant-admin-mcp-server-editor.component';\nexport * from './mcp/nh-assistant-admin-mcp-tools.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["nextId","nhAssistantErrorKeys","toNhAssistantError","NhAssistantIconComponent","NhAssistantTranslatePipe","NH_ASSISTANT_DASH_CASE","dayMs","periodRange"],"mappings":"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"}
|