UNPKG

@memberjunction/ng-ai-test-harness

Version:

MemberJunction AI Test Harness - A reusable component for testing AI agents and prompts with beautiful UX

163 lines 6.86 kB
import { Injectable, createComponent } from '@angular/core'; import { TestHarnessCustomWindowComponent } from './test-harness-custom-window.component'; import { Subject } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "./window-dock.service"; /** * Service for managing test harness windows for AI Agents and AI Prompts. * Creates Kendo Window components with custom titlebar including minimize button. */ export class TestHarnessWindowManagerService { constructor(appRef, injector, dockService) { this.appRef = appRef; this.injector = injector; this.dockService = dockService; this.openWindows = new Map(); this.windowCounter = 0; } /** * Opens the AI Agent Test Harness in a window */ openAgentTestHarness(options) { const data = { agentId: options.agentId, agent: options.agent, title: options.title, width: options.width || '90vw', height: options.height || '90vh', initialDataContext: options.initialDataContext, initialTemplateData: options.initialTemplateData, mode: 'agent' }; return this.createWindow(data, options.viewContainerRef); } /** * Opens the AI Prompt Test Harness in a window */ openPromptTestHarness(options) { const data = { promptId: options.promptId, prompt: options.prompt, title: options.title || 'Test AI Prompt', width: options.width || '90vw', height: options.height || '90vh', initialTemplateVariables: options.initialTemplateVariables, selectedModelId: options.selectedModelId, mode: 'prompt' }; return this.createWindow(data, options.viewContainerRef); } /** * Creates a test harness window */ createWindow(data, viewContainerRef) { const resultSubject = new Subject(); const windowId = `test-harness-${++this.windowCounter}`; // Create component const componentRef = createComponent(TestHarnessCustomWindowComponent, { environmentInjector: this.appRef.injector, elementInjector: this.injector, hostElement: document.createElement('div') }); // Set component data componentRef.instance.data = data; // Handle window events componentRef.instance.closeWindow.subscribe(() => { this.closeWindow(windowId); resultSubject.next({ success: true }); resultSubject.complete(); }); // Handle minimize event componentRef.instance.minimizeWindow.subscribe(() => { const title = componentRef.instance.windowTitle; let icon = 'fa-solid fa-flask'; // default let iconUrl; // Get the appropriate icon based on mode and entity if (componentRef.instance.mode === 'agent' && componentRef.instance.agent) { // For agents, use LogoURL since AIAgentEntityExtended doesn't have IconClass if (componentRef.instance.agent.LogoURL) { iconUrl = componentRef.instance.agent.LogoURL; icon = undefined; // Clear icon when using URL } else { icon = 'fa-solid fa-robot'; // Default agent icon } } else if (componentRef.instance.mode === 'prompt') { icon = 'fa-solid fa-comment-dots'; // Default prompt icon } // Add to dock with icon or iconUrl this.dockService.addWindow(windowId, title, icon, () => { // Restore callback componentRef.instance.restoreFromMinimized(); }, iconUrl); }); // Handle restore event componentRef.instance.restoreWindow.subscribe(() => { // Remove from dock this.dockService.removeWindow(windowId); }); // Handle execution state changes componentRef.instance.executionStateChange.subscribe((state) => { if (state.isExecuting) { // Show indeterminate progress (spinning/pulsing) this.dockService.updateWindowProgress(windowId, 50); // 50% for indeterminate animation } else { // Clear progress this.dockService.updateWindowProgress(windowId, undefined); } }); // Attach to DOM if (viewContainerRef) { // When using viewContainerRef, the view is automatically attached to Angular viewContainerRef.insert(componentRef.hostView); } else { // When appending to document.body, we need to manually attach to Angular document.body.appendChild(componentRef.location.nativeElement); this.appRef.attachView(componentRef.hostView); } // Store reference with info about how it was created this.openWindows.set(windowId, { componentRef, usedViewContainerRef: !!viewContainerRef }); return resultSubject.asObservable(); } /** * Closes a specific window */ closeWindow(windowId) { const windowInfo = this.openWindows.get(windowId); if (windowInfo) { // Remove from dock if minimized this.dockService.removeWindow(windowId); // Only detach from appRef if we attached it manually (not using viewContainerRef) if (!windowInfo.usedViewContainerRef) { this.appRef.detachView(windowInfo.componentRef.hostView); } windowInfo.componentRef.destroy(); this.openWindows.delete(windowId); } } /** * Closes all open windows */ closeAllWindows() { this.openWindows.forEach((windowInfo, id) => { this.closeWindow(id); }); } static { this.ɵfac = function TestHarnessWindowManagerService_Factory(t) { return new (t || TestHarnessWindowManagerService)(i0.ɵɵinject(i0.ApplicationRef), i0.ɵɵinject(i0.Injector), i0.ɵɵinject(i1.WindowDockService)); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TestHarnessWindowManagerService, factory: TestHarnessWindowManagerService.ɵfac, providedIn: 'root' }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestHarnessWindowManagerService, [{ type: Injectable, args: [{ providedIn: 'root' }] }], () => [{ type: i0.ApplicationRef }, { type: i0.Injector }, { type: i1.WindowDockService }], null); })(); //# sourceMappingURL=test-harness-window-manager.service.js.map