UNPKG

@memberjunction/ng-ai-test-harness

Version:

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

172 lines 6.5 kB
import { Injectable } from '@angular/core'; import { AITestHarnessWindowComponent } from './ai-test-harness-window.component'; import { Subject } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "@progress/kendo-angular-dialog"; /** * Service for managing test harness windows for AI Agents and AI Prompts. * Uses Kendo Window component which provides maximize and close functionality. * * Note: Kendo Window created via WindowService does not include a minimize button * in the titlebar. The window supports maximize/restore and close actions only. * To add minimize functionality, a custom window component with custom titlebar * would need to be implemented. */ export class TestHarnessWindowService { constructor(windowService) { this.windowService = windowService; 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.openWindow(data, options.viewContainerRef); } /** * Opens the AI Prompt Test Harness in a window */ openPromptTestHarness(options) { console.log('🎯 openPromptTestHarness called with options:', options); console.log('📌 promptRunId:', options.promptRunId); 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, promptRunId: options.promptRunId, mode: 'prompt' }; console.log('📦 Final AITestHarnessWindowData:', data); return this.openWindow(data, options.viewContainerRef); } /** * Opens a test harness window */ openWindow(data, viewContainerRef) { const resultSubject = new Subject(); const windowId = `test-harness-${++this.windowCounter}`; const windowSettings = { title: data.title || 'AI Test Harness', content: AITestHarnessWindowComponent, width: this.convertToNumber(data.width) || 1200, height: this.convertToNumber(data.height) || 800, minWidth: 800, minHeight: 600, draggable: true, resizable: true, state: 'default', cssClass: 'test-harness-window-wrapper' }; if (viewContainerRef) { windowSettings.appendTo = viewContainerRef; } const windowRef = this.windowService.open(windowSettings); this.openWindows.set(windowId, windowRef); // Pass data to the component const componentRef = windowRef.content; if (componentRef && componentRef.instance) { componentRef.instance.data = data; // Handle window close componentRef.instance.closeWindow.subscribe(() => { this.closeWindow(windowId); // Don't complete the observable here, as the window.result will handle it }); } // Handle window close via close button windowRef.result.subscribe({ next: (result) => { this.openWindows.delete(windowId); resultSubject.next({ success: true, result: result }); resultSubject.complete(); }, error: (error) => { this.openWindows.delete(windowId); resultSubject.next({ success: false, error: error.message || 'Test failed' }); resultSubject.complete(); } }); return resultSubject.asObservable(); } /** * Closes a specific window */ closeWindow(windowId) { const windowRef = this.openWindows.get(windowId); if (windowRef) { try { windowRef.close(); this.openWindows.delete(windowId); } catch (error) { console.error('Error closing window:', error); // Force delete from map even if close fails this.openWindows.delete(windowId); } } } /** * Closes all open windows */ closeAllWindows() { this.openWindows.forEach((windowRef, id) => { windowRef.close(); }); this.openWindows.clear(); } /** * Helper method to convert string dimensions to pixel numbers */ convertToNumber(value) { if (!value) return undefined; if (typeof value === 'number') return value; // Handle percentage values if (value.endsWith('vw') || value.endsWith('vh')) { const percentage = parseFloat(value) / 100; if (value.endsWith('vw')) { return window.innerWidth * percentage; } else { return window.innerHeight * percentage; } } // Handle pixel values if (value.endsWith('px')) { return parseFloat(value); } // Try to parse as number const parsed = parseFloat(value); return isNaN(parsed) ? undefined : parsed; } static { this.ɵfac = function TestHarnessWindowService_Factory(t) { return new (t || TestHarnessWindowService)(i0.ɵɵinject(i1.WindowService)); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TestHarnessWindowService, factory: TestHarnessWindowService.ɵfac, providedIn: 'root' }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestHarnessWindowService, [{ type: Injectable, args: [{ providedIn: 'root' }] }], () => [{ type: i1.WindowService }], null); })(); //# sourceMappingURL=test-harness-window.service.js.map