@memberjunction/ng-ai-test-harness 5.22.0 → 5.24.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.
@@ -1,16 +1,16 @@
1
- import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
1
+ import { Component, Input, Output, EventEmitter, ViewChild, ChangeDetectorRef, inject } from '@angular/core';
2
2
  import { Metadata } from '@memberjunction/core';
3
3
  import { AITestHarnessComponent } from './ai-test-harness.component';
4
4
  import * as i0 from "@angular/core";
5
- import * as i1 from "@progress/kendo-angular-dialog";
5
+ import * as i1 from "@memberjunction/ng-ui-components";
6
6
  import * as i2 from "@memberjunction/ng-shared-generic";
7
7
  import * as i3 from "./ai-test-harness.component";
8
- const _c0 = ["kendoWindow"];
8
+ const _c0 = ["mjWindow"];
9
9
  function TestHarnessCustomWindowComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
10
10
  i0.ɵɵelement(0, "img", 3);
11
11
  } if (rf & 2) {
12
12
  const ctx_r1 = i0.ɵɵnextContext();
13
- i0.ɵɵproperty("src", ctx_r1.agent == null ? null : ctx_r1.agent.LogoURL, i0.ɵɵsanitizeUrl);
13
+ i0.ɵɵproperty("src", ctx_r1.Agent == null ? null : ctx_r1.Agent.LogoURL, i0.ɵɵsanitizeUrl);
14
14
  } }
15
15
  function TestHarnessCustomWindowComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
16
16
  i0.ɵɵelement(0, "i", 4);
@@ -25,7 +25,7 @@ function TestHarnessCustomWindowComponent_Conditional_17_Template(rf, ctx) { if
25
25
  } if (rf & 2) {
26
26
  const ctx_r1 = i0.ɵɵnextContext();
27
27
  i0.ɵɵadvance();
28
- i0.ɵɵproperty("text", "Loading " + (ctx_r1.mode === "agent" ? "AI Agent" : "AI Prompt") + "...");
28
+ i0.ɵɵproperty("text", "Loading " + (ctx_r1.Mode === "agent" ? "AI Agent" : "AI Prompt") + "...");
29
29
  } }
30
30
  function TestHarnessCustomWindowComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
31
31
  i0.ɵɵelementStart(0, "div", 15);
@@ -36,220 +36,191 @@ function TestHarnessCustomWindowComponent_Conditional_18_Template(rf, ctx) { if
36
36
  } if (rf & 2) {
37
37
  const ctx_r1 = i0.ɵɵnextContext();
38
38
  i0.ɵɵadvance(3);
39
- i0.ɵɵtextInterpolate(ctx_r1.error);
39
+ i0.ɵɵtextInterpolate(ctx_r1.Error);
40
40
  } }
41
41
  function TestHarnessCustomWindowComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
42
42
  const _r3 = i0.ɵɵgetCurrentView();
43
43
  i0.ɵɵelementStart(0, "mj-ai-test-harness", 19);
44
- i0.ɵɵlistener("runOpened", function TestHarnessCustomWindowComponent_Conditional_19_Template_mj_ai_test_harness_runOpened_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRunOpened($event)); });
44
+ i0.ɵɵlistener("runOpened", function TestHarnessCustomWindowComponent_Conditional_19_Template_mj_ai_test_harness_runOpened_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnRunOpened($event)); });
45
45
  i0.ɵɵelementEnd();
46
46
  } if (rf & 2) {
47
47
  const ctx_r1 = i0.ɵɵnextContext();
48
- i0.ɵɵproperty("entity", ctx_r1.agent || ctx_r1.prompt || null)("mode", ctx_r1.mode)("isVisible", true);
48
+ i0.ɵɵproperty("entity", ctx_r1.Agent || ctx_r1.Prompt || null)("mode", ctx_r1.Mode)("isVisible", true);
49
49
  } }
50
50
  export class TestHarnessCustomWindowComponent {
51
- constructor(renderer, elementRef, cdr) {
52
- this.renderer = renderer;
53
- this.elementRef = elementRef;
54
- this.cdr = cdr;
55
- this.data = {};
56
- this.closeWindow = new EventEmitter();
57
- this.minimizeWindow = new EventEmitter();
58
- this.restoreWindow = new EventEmitter();
59
- this.executionStateChange = new EventEmitter();
60
- this.windowTitle = 'AI Test Harness';
61
- this.width = 1200;
62
- this.height = 800;
63
- this.windowTop = 100;
64
- this.windowLeft = 100;
65
- this.loading = true;
66
- this.error = '';
67
- this.windowState = 'default';
68
- this.isMaximized = false;
69
- this.isMinimized = false;
51
+ constructor() {
52
+ this.Data = {};
53
+ this.CloseWindow = new EventEmitter();
54
+ this.MinimizeWindow = new EventEmitter();
55
+ this.RestoreWindow = new EventEmitter();
56
+ this.ExecutionStateChange = new EventEmitter();
57
+ this.WindowTitle = 'AI Test Harness';
58
+ this.WindowVisible = false;
59
+ this.Width = 1200;
60
+ this.Height = 800;
61
+ this.WindowTop = 100;
62
+ this.WindowLeft = 100;
63
+ this.Loading = true;
64
+ this.Error = '';
65
+ this.WindowState = 'default';
66
+ this.IsMaximized = false;
67
+ this.IsMinimized = false;
70
68
  // Store original dimensions for restore
71
69
  this.originalWidth = 1200;
72
70
  this.originalHeight = 800;
73
71
  this.originalTop = 100;
74
72
  this.originalLeft = 100;
75
- // Minimized dimensions
76
- this.MINIMIZED_WIDTH = 400;
77
- this.MINIMIZED_HEIGHT = 60;
78
- this.mode = 'agent';
73
+ this.Mode = 'agent';
79
74
  this.metadata = new Metadata();
75
+ this.executionCheckInterval = null;
76
+ this.cdr = inject(ChangeDetectorRef);
80
77
  }
81
78
  ngOnInit() {
82
79
  // Set window dimensions
83
- this.width = this.convertToNumber(this.data.width) || 1200;
84
- this.height = this.convertToNumber(this.data.height) || 800;
80
+ this.Width = this.convertToNumber(this.Data.width) || 1200;
81
+ this.Height = this.convertToNumber(this.Data.height) || 800;
85
82
  // Store original dimensions
86
- this.originalWidth = this.width;
87
- this.originalHeight = this.height;
83
+ this.originalWidth = this.Width;
84
+ this.originalHeight = this.Height;
88
85
  // Calculate centered position
89
- const windowWidth = window.innerWidth;
90
- const windowHeight = window.innerHeight;
91
- this.windowLeft = Math.max(0, (windowWidth - this.width) / 2);
92
- this.windowTop = Math.max(0, (windowHeight - this.height) / 2);
86
+ const viewportWidth = window.innerWidth;
87
+ const viewportHeight = window.innerHeight;
88
+ this.WindowLeft = Math.max(0, (viewportWidth - this.Width) / 2);
89
+ this.WindowTop = Math.max(0, (viewportHeight - this.Height) / 2);
93
90
  // Store original position
94
- this.originalLeft = this.windowLeft;
95
- this.originalTop = this.windowTop;
91
+ this.originalLeft = this.WindowLeft;
92
+ this.originalTop = this.WindowTop;
96
93
  // Determine mode
97
- this.mode = this.data.mode || (this.data.promptId || this.data.prompt ? 'prompt' : 'agent');
94
+ this.Mode = this.Data.mode || (this.Data.promptId || this.Data.prompt ? 'prompt' : 'agent');
95
+ // Set initial title from data if available
96
+ if (this.Data.title) {
97
+ this.WindowTitle = this.Data.title;
98
+ }
99
+ else if (this.Data.agent) {
100
+ this.WindowTitle = `Test: ${this.Data.agent.Name}`;
101
+ }
102
+ else if (this.Data.prompt) {
103
+ this.WindowTitle = `Test: ${this.Data.prompt.Name}`;
104
+ }
105
+ // Show window now that position is calculated
106
+ this.WindowVisible = true;
98
107
  // Load entity
99
- this.loadEntity();
108
+ this.LoadEntity();
100
109
  }
101
- async loadEntity() {
110
+ async LoadEntity() {
102
111
  try {
103
- if (this.mode === 'agent') {
104
- if (this.data.agent) {
105
- this.agent = this.data.agent;
106
- this.windowTitle = this.data.title || `Test: ${this.agent.Name}`;
107
- }
108
- else if (this.data.agentId) {
109
- const agentEntity = await this.metadata.GetEntityObject('MJ: AI Agents');
110
- await agentEntity.Load(this.data.agentId);
111
- if (agentEntity.IsSaved) {
112
- this.agent = agentEntity;
113
- this.windowTitle = this.data.title || `Test: ${this.agent.Name}`;
114
- }
115
- else {
116
- throw new Error('Agent not found');
117
- }
118
- }
119
- else {
120
- throw new Error('No agent provided');
121
- }
112
+ if (this.Mode === 'agent') {
113
+ await this.loadAgent();
122
114
  }
123
115
  else {
124
- if (this.data.prompt) {
125
- this.prompt = this.data.prompt;
126
- this.windowTitle = this.data.title || `Test: ${this.prompt.Name}`;
127
- }
128
- else if (this.data.promptId) {
129
- const promptEntity = await this.metadata.GetEntityObject('MJ: AI Prompts');
130
- await promptEntity.Load(this.data.promptId);
131
- if (promptEntity.IsSaved) {
132
- this.prompt = promptEntity;
133
- this.windowTitle = this.data.title || `Test: ${this.prompt.Name}`;
134
- }
135
- else {
136
- throw new Error('Prompt not found');
137
- }
138
- }
139
- else {
140
- throw new Error('No prompt provided');
141
- }
116
+ await this.loadPrompt();
142
117
  }
143
- this.loading = false;
118
+ this.Loading = false;
119
+ this.cdr.detectChanges();
144
120
  }
145
121
  catch (err) {
146
- this.error = err.message || 'Failed to load entity';
147
- this.loading = false;
122
+ this.Error = err instanceof Error ? err.message : 'Failed to load entity';
123
+ this.Loading = false;
124
+ this.cdr.detectChanges();
148
125
  }
149
126
  }
150
- onClose() {
151
- // When the Kendo Window's close event fires (from the default X button),
152
- // emit our closeWindow event to notify the window manager
153
- this.closeWindow.emit();
154
- }
155
- closeButtonClick() {
156
- // When our custom close button is clicked, emit the close event
157
- // This will trigger the window to close and call our onClose handler
158
- if (this.kendoWindow) {
159
- this.kendoWindow.close.emit();
127
+ async loadAgent() {
128
+ if (this.Data.agent) {
129
+ this.Agent = this.Data.agent;
130
+ this.WindowTitle = this.Data.title || `Test: ${this.Agent.Name}`;
131
+ }
132
+ else if (this.Data.agentId) {
133
+ const agentEntity = await this.metadata.GetEntityObject('MJ: AI Agents');
134
+ await agentEntity.Load(this.Data.agentId);
135
+ if (agentEntity.IsSaved) {
136
+ this.Agent = agentEntity;
137
+ this.WindowTitle = this.Data.title || `Test: ${this.Agent.Name}`;
138
+ }
139
+ else {
140
+ throw new Error('Agent not found');
141
+ }
160
142
  }
161
143
  else {
162
- // If kendoWindow is not available, directly emit the close event
163
- this.onClose();
144
+ throw new Error('No agent provided');
164
145
  }
165
146
  }
166
- onStateChange(state) {
167
- this.windowState = state;
168
- this.isMaximized = state === 'maximized';
169
- this.isMinimized = state === 'minimized';
170
- // Handle restore from minimized
171
- if (this.isMinimized && state !== 'minimized') {
172
- this.restoreFromMinimized();
147
+ async loadPrompt() {
148
+ if (this.Data.prompt) {
149
+ this.Prompt = this.Data.prompt;
150
+ this.WindowTitle = this.Data.title || `Test: ${this.Prompt.Name}`;
173
151
  }
174
- // Adjust content height on any state change
175
- if (state !== 'minimized') {
176
- setTimeout(() => this.adjustContentHeight(), 100);
152
+ else if (this.Data.promptId) {
153
+ const promptEntity = await this.metadata.GetEntityObject('MJ: AI Prompts');
154
+ await promptEntity.Load(this.Data.promptId);
155
+ if (promptEntity.IsSaved) {
156
+ this.Prompt = promptEntity;
157
+ this.WindowTitle = this.Data.title || `Test: ${this.Prompt.Name}`;
158
+ }
159
+ else {
160
+ throw new Error('Prompt not found');
161
+ }
177
162
  }
178
- }
179
- onWindowResize() {
180
- // Handle Kendo Window resize event
181
- if (!this.isMinimized) {
182
- // Use a small delay to ensure the DOM has updated
183
- setTimeout(() => this.adjustContentHeight(), 50);
163
+ else {
164
+ throw new Error('No prompt provided');
184
165
  }
185
166
  }
186
- onRunOpened(event) {
167
+ OnClose() {
168
+ this.CloseWindow.emit();
169
+ }
170
+ CloseButtonClick() {
171
+ this.OnClose();
172
+ }
173
+ OnStateChange(state) {
174
+ this.WindowState = state;
175
+ this.IsMaximized = state === 'maximized';
176
+ }
177
+ OnWindowResize() {
178
+ // Window was resized — no special handling needed as mj-window tracks dimensions internally
179
+ }
180
+ OnRunOpened(_event) {
187
181
  // Auto-minimize the test harness window when a run is opened
188
- this.minimize();
182
+ this.Minimize();
189
183
  }
190
- minimize() {
191
- if (!this.isMinimized) {
184
+ Minimize() {
185
+ if (!this.IsMinimized) {
192
186
  // Store current dimensions before minimizing
193
- this.originalWidth = this.width;
194
- this.originalHeight = this.height;
195
- this.originalTop = this.windowTop;
196
- this.originalLeft = this.windowLeft;
187
+ this.originalWidth = this.Width;
188
+ this.originalHeight = this.Height;
189
+ this.originalTop = this.WindowTop;
190
+ this.originalLeft = this.WindowLeft;
197
191
  // Hide the window when minimized (dock will show icon)
198
- this.isMinimized = true;
199
- this.minimizeWindow.emit();
200
- // Hide the window element
201
- let windowElement = this.elementRef.nativeElement.querySelector('.k-window');
202
- if (!windowElement && this.elementRef.nativeElement.closest) {
203
- windowElement = this.elementRef.nativeElement.closest('.k-window');
204
- }
205
- if (windowElement) {
206
- this.renderer.setStyle(windowElement, 'display', 'none');
207
- }
192
+ this.IsMinimized = true;
193
+ this.WindowVisible = false;
194
+ this.MinimizeWindow.emit();
195
+ this.cdr.detectChanges();
208
196
  }
209
197
  }
210
- restoreFromMinimized() {
211
- this.width = this.originalWidth;
212
- this.height = this.originalHeight;
213
- this.windowTop = this.originalTop;
214
- this.windowLeft = this.originalLeft;
215
- this.windowState = 'default';
216
- this.isMinimized = false;
217
- // Show the window element
218
- let windowElement = this.elementRef.nativeElement.querySelector('.k-window');
219
- if (!windowElement && this.elementRef.nativeElement.closest) {
220
- windowElement = this.elementRef.nativeElement.closest('.k-window');
221
- }
222
- if (windowElement) {
223
- this.renderer.setStyle(windowElement, 'display', 'block');
224
- }
225
- // Update position after state change
226
- setTimeout(() => {
227
- this.updateWindowPosition();
228
- // Force Angular change detection
229
- this.cdr.detectChanges();
230
- // Force the Kendo Window to recalculate its internal dimensions
231
- if (this.kendoWindow) {
232
- // Trigger resize event to fix content sizing
233
- window.dispatchEvent(new Event('resize'));
234
- // Use the shared method to adjust content height
235
- this.adjustContentHeight();
236
- }
237
- }, 100);
198
+ RestoreFromMinimized() {
199
+ this.Width = this.originalWidth;
200
+ this.Height = this.originalHeight;
201
+ this.WindowTop = this.originalTop;
202
+ this.WindowLeft = this.originalLeft;
203
+ this.WindowState = 'default';
204
+ this.IsMinimized = false;
205
+ this.IsMaximized = false;
206
+ this.WindowVisible = true;
207
+ this.cdr.detectChanges();
238
208
  // Emit restore event
239
- this.restoreWindow.emit();
209
+ this.RestoreWindow.emit();
240
210
  }
241
- toggleMaximize() {
242
- if (this.isMinimized) {
211
+ ToggleMaximize() {
212
+ if (this.IsMinimized) {
243
213
  // First restore from minimized, then maximize
244
- this.restoreFromMinimized();
214
+ this.RestoreFromMinimized();
245
215
  setTimeout(() => {
246
- this.windowState = 'maximized';
247
- this.isMaximized = true;
248
- }, 600);
216
+ this.WindowState = 'maximized';
217
+ this.IsMaximized = true;
218
+ this.cdr.detectChanges();
219
+ }, 100);
249
220
  }
250
221
  else {
251
- this.windowState = this.isMaximized ? 'default' : 'maximized';
252
- this.isMaximized = !this.isMaximized;
222
+ this.WindowState = this.IsMaximized ? 'default' : 'maximized';
223
+ this.IsMaximized = !this.IsMaximized;
253
224
  }
254
225
  }
255
226
  convertToNumber(value) {
@@ -276,249 +247,163 @@ export class TestHarnessCustomWindowComponent {
276
247
  return isNaN(parsed) ? undefined : parsed;
277
248
  }
278
249
  ngAfterViewInit() {
279
- // Set initial position if needed
280
- setTimeout(() => {
281
- this.updateWindowPosition();
282
- this.adjustContentHeight();
283
- }, 100);
284
250
  // Set up execution tracking
285
251
  this.setupExecutionTracking();
286
- // Set up window resize listener
287
- this.setupResizeListener();
288
- }
289
- adjustContentHeight() {
290
- // Ensure the window content wrapper has proper height
291
- const contentWrapper = this.elementRef.nativeElement.querySelector('.k-window-content');
292
- if (contentWrapper && this.kendoWindow) {
293
- // Get the actual window element to check current dimensions
294
- const windowElement = this.elementRef.nativeElement.querySelector('.k-window') ||
295
- this.elementRef.nativeElement.closest('.k-window');
296
- // Update our tracked dimensions if the window has been resized
297
- if (windowElement) {
298
- const rect = windowElement.getBoundingClientRect();
299
- if (rect.width > 0)
300
- this.width = rect.width;
301
- if (rect.height > 0)
302
- this.height = rect.height;
303
- }
304
- // Calculate the actual content height (window height minus titlebar and some padding)
305
- const windowHeight = this.height;
306
- const titlebarHeight = 40; // Titlebar height
307
- const bottomPadding = 10; // Extra space to prevent clipping
308
- const contentHeight = windowHeight - titlebarHeight - bottomPadding;
309
- this.renderer.setStyle(contentWrapper, 'height', `${contentHeight}px`);
310
- this.renderer.setStyle(contentWrapper, 'display', 'flex');
311
- this.renderer.setStyle(contentWrapper, 'flex-direction', 'column');
312
- }
313
- // Also update the test harness container
314
- const testHarnessContainer = this.elementRef.nativeElement.querySelector('mj-ai-test-harness');
315
- if (testHarnessContainer) {
316
- this.renderer.setStyle(testHarnessContainer, 'flex', '1');
317
- this.renderer.setStyle(testHarnessContainer, 'height', '100%');
318
- this.renderer.setStyle(testHarnessContainer, 'overflow', 'hidden');
319
- }
320
- }
321
- setupResizeListener() {
322
- // Debounced resize handler
323
- let resizeTimeout;
324
- const handleResize = () => {
325
- clearTimeout(resizeTimeout);
326
- resizeTimeout = setTimeout(() => {
327
- if (!this.isMinimized) {
328
- this.adjustContentHeight();
329
- }
330
- }, 100);
331
- };
332
- // Listen for window resize events
333
- window.addEventListener('resize', handleResize);
334
- // Store the handler for cleanup
335
- this.resizeHandler = handleResize;
336
- // Note: Kendo Window resize events are handled by the (resize) event binding in the template
337
252
  }
338
253
  setupExecutionTracking() {
339
254
  // Use a timer to check the test harness execution state
340
- // This is needed because the test harness doesn't emit events for execution state changes
341
- if (this.testHarness) {
342
- // Initial state
255
+ if (this.TestHarness) {
343
256
  let lastExecutingState = false;
344
- // Check execution state periodically
345
- const checkInterval = setInterval(() => {
346
- if (this.testHarness && this.testHarness.isExecuting !== lastExecutingState) {
347
- lastExecutingState = this.testHarness.isExecuting;
348
- this.executionStateChange.emit({ isExecuting: lastExecutingState });
257
+ this.executionCheckInterval = setInterval(() => {
258
+ if (this.TestHarness && this.TestHarness.isExecuting !== lastExecutingState) {
259
+ lastExecutingState = this.TestHarness.isExecuting;
260
+ this.ExecutionStateChange.emit({ isExecuting: lastExecutingState });
349
261
  }
350
262
  }, 100);
351
- // Store interval for cleanup
352
- this.executionCheckInterval = checkInterval;
353
263
  }
354
264
  }
355
265
  ngOnDestroy() {
356
- // Clean up execution tracking interval
357
266
  if (this.executionCheckInterval) {
358
267
  clearInterval(this.executionCheckInterval);
359
268
  }
360
- // Clean up resize listener
361
- if (this.resizeHandler) {
362
- window.removeEventListener('resize', this.resizeHandler);
363
- }
364
- // Ensure window is properly closed and cleaned up
365
- if (this.kendoWindow) {
366
- this.kendoWindow.close.emit();
367
- }
368
- }
369
- updateWindowPosition() {
370
- // Find the window element - it might be in the parent if we're inside a wrapper
371
- let windowElement = this.elementRef.nativeElement.querySelector('.k-window');
372
- if (!windowElement && this.elementRef.nativeElement.closest) {
373
- windowElement = this.elementRef.nativeElement.closest('.k-window');
374
- }
375
- if (windowElement && (this.windowTop !== undefined || this.windowLeft !== undefined)) {
376
- if (this.windowTop !== undefined) {
377
- this.renderer.setStyle(windowElement, 'top', `${this.windowTop}px`);
378
- }
379
- if (this.windowLeft !== undefined) {
380
- this.renderer.setStyle(windowElement, 'left', `${this.windowLeft}px`);
381
- }
382
- }
383
269
  }
384
- static { this.ɵfac = function TestHarnessCustomWindowComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TestHarnessCustomWindowComponent)(i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
270
+ static { this.ɵfac = function TestHarnessCustomWindowComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TestHarnessCustomWindowComponent)(); }; }
385
271
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestHarnessCustomWindowComponent, selectors: [["mj-test-harness-custom-window"]], viewQuery: function TestHarnessCustomWindowComponent_Query(rf, ctx) { if (rf & 1) {
386
272
  i0.ɵɵviewQuery(_c0, 5)(AITestHarnessComponent, 5);
387
273
  } if (rf & 2) {
388
274
  let _t;
389
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoWindow = _t.first);
390
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.testHarness = _t.first);
391
- } }, inputs: { data: "data" }, outputs: { closeWindow: "closeWindow", minimizeWindow: "minimizeWindow", restoreWindow: "restoreWindow", executionStateChange: "executionStateChange" }, standalone: false, decls: 20, vars: 20, consts: [["kendoWindow", ""], [3, "close", "stateChange", "resize", "title", "width", "height", "top", "left", "minWidth", "minHeight", "draggable", "resizable", "state"], [1, "window-title"], ["alt", "Agent logo", 1, "title-logo", 3, "src"], [1, "fa-solid", "fa-robot", "title-icon"], [1, "fa-solid", "fa-comment-dots", "title-icon"], [1, "window-actions"], ["title", "Minimize", 1, "window-action-btn", 3, "click"], [1, "fa-solid", "fa-window-minimize"], [1, "window-action-btn", 3, "click", "title"], [1, "fa-solid"], ["title", "Close", 1, "window-action-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "window-content"], [1, "loading-container"], [1, "error-container"], [3, "entity", "mode", "isVisible"], ["size", "large", 3, "text"], [1, "fa-solid", "fa-exclamation-triangle"], [3, "runOpened", "entity", "mode", "isVisible"]], template: function TestHarnessCustomWindowComponent_Template(rf, ctx) { if (rf & 1) {
275
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.MjWindow = _t.first);
276
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.TestHarness = _t.first);
277
+ } }, inputs: { Data: "Data" }, outputs: { CloseWindow: "CloseWindow", MinimizeWindow: "MinimizeWindow", RestoreWindow: "RestoreWindow", ExecutionStateChange: "ExecutionStateChange" }, standalone: false, decls: 20, vars: 19, consts: [["mjWindow", ""], [3, "Close", "StateChange", "Resize", "Visible", "Title", "Width", "Height", "Top", "Left", "MinWidth", "MinHeight", "Draggable", "Resizable", "State"], [1, "window-title"], ["alt", "Agent logo", 1, "title-logo", 3, "src"], [1, "fa-solid", "fa-robot", "title-icon"], [1, "fa-solid", "fa-comment-dots", "title-icon"], [1, "window-actions"], ["title", "Minimize", 1, "window-action-btn", 3, "click"], [1, "fa-solid", "fa-window-minimize"], [1, "window-action-btn", 3, "click", "title"], [1, "fa-solid"], ["title", "Close", 1, "window-action-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "window-content"], [1, "loading-container"], [1, "error-container"], [3, "entity", "mode", "isVisible"], ["size", "large", 3, "text"], [1, "fa-solid", "fa-exclamation-triangle"], [3, "runOpened", "entity", "mode", "isVisible"]], template: function TestHarnessCustomWindowComponent_Template(rf, ctx) { if (rf & 1) {
392
278
  const _r1 = i0.ɵɵgetCurrentView();
393
- i0.ɵɵelementStart(0, "kendo-window", 1, 0);
394
- i0.ɵɵlistener("close", function TestHarnessCustomWindowComponent_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onClose()); })("stateChange", function TestHarnessCustomWindowComponent_Template_kendo_window_stateChange_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onStateChange($event)); })("resize", function TestHarnessCustomWindowComponent_Template_kendo_window_resize_0_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onWindowResize()); });
395
- i0.ɵɵelementStart(2, "kendo-window-titlebar")(3, "div", 2);
279
+ i0.ɵɵelementStart(0, "mj-window", 1, 0);
280
+ i0.ɵɵlistener("Close", function TestHarnessCustomWindowComponent_Template_mj_window_Close_0_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnClose()); })("StateChange", function TestHarnessCustomWindowComponent_Template_mj_window_StateChange_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnStateChange($event)); })("Resize", function TestHarnessCustomWindowComponent_Template_mj_window_Resize_0_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnWindowResize()); });
281
+ i0.ɵɵelementStart(2, "mj-window-titlebar")(3, "div", 2);
396
282
  i0.ɵɵconditionalCreate(4, TestHarnessCustomWindowComponent_Conditional_4_Template, 1, 1, "img", 3)(5, TestHarnessCustomWindowComponent_Conditional_5_Template, 1, 0, "i", 4)(6, TestHarnessCustomWindowComponent_Conditional_6_Template, 1, 0, "i", 5);
397
283
  i0.ɵɵelementStart(7, "span");
398
284
  i0.ɵɵtext(8);
399
285
  i0.ɵɵelementEnd()();
400
286
  i0.ɵɵelementStart(9, "div", 6)(10, "button", 7);
401
- i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.minimize()); });
287
+ i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.Minimize()); });
402
288
  i0.ɵɵelement(11, "i", 8);
403
289
  i0.ɵɵelementEnd();
404
290
  i0.ɵɵelementStart(12, "button", 9);
405
- i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleMaximize()); });
291
+ i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.ToggleMaximize()); });
406
292
  i0.ɵɵelement(13, "i", 10);
407
293
  i0.ɵɵelementEnd();
408
294
  i0.ɵɵelementStart(14, "button", 11);
409
- i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.closeButtonClick()); });
295
+ i0.ɵɵlistener("click", function TestHarnessCustomWindowComponent_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.CloseButtonClick()); });
410
296
  i0.ɵɵelement(15, "i", 12);
411
297
  i0.ɵɵelementEnd()()();
412
298
  i0.ɵɵelementStart(16, "div", 13);
413
299
  i0.ɵɵconditionalCreate(17, TestHarnessCustomWindowComponent_Conditional_17_Template, 2, 1, "div", 14)(18, TestHarnessCustomWindowComponent_Conditional_18_Template, 4, 1, "div", 15)(19, TestHarnessCustomWindowComponent_Conditional_19_Template, 1, 3, "mj-ai-test-harness", 16);
414
300
  i0.ɵɵelementEnd()();
415
301
  } if (rf & 2) {
416
- i0.ɵɵclassProp("minimized-window", ctx.isMinimized);
417
- i0.ɵɵproperty("title", ctx.windowTitle)("width", ctx.width)("height", ctx.height)("top", ctx.windowTop)("left", ctx.windowLeft)("minWidth", ctx.isMinimized ? 400 : 800)("minHeight", ctx.isMinimized ? 60 : 600)("draggable", true)("resizable", !ctx.isMinimized)("state", ctx.windowState);
302
+ i0.ɵɵproperty("Visible", ctx.WindowVisible)("Title", "")("Width", ctx.Width)("Height", ctx.Height)("Top", ctx.WindowTop)("Left", ctx.WindowLeft)("MinWidth", ctx.IsMinimized ? 400 : 800)("MinHeight", ctx.IsMinimized ? 60 : 600)("Draggable", true)("Resizable", !ctx.IsMinimized)("State", ctx.WindowState);
418
303
  i0.ɵɵadvance(4);
419
- i0.ɵɵconditional(ctx.mode === "agent" && (ctx.agent == null ? null : ctx.agent.LogoURL) ? 4 : ctx.mode === "agent" ? 5 : 6);
304
+ i0.ɵɵconditional(ctx.Mode === "agent" && (ctx.Agent == null ? null : ctx.Agent.LogoURL) ? 4 : ctx.Mode === "agent" ? 5 : 6);
420
305
  i0.ɵɵadvance(4);
421
- i0.ɵɵtextInterpolate(ctx.windowTitle);
306
+ i0.ɵɵtextInterpolate(ctx.WindowTitle);
422
307
  i0.ɵɵadvance(4);
423
- i0.ɵɵproperty("title", ctx.isMaximized ? "Restore" : "Maximize");
308
+ i0.ɵɵproperty("title", ctx.IsMaximized ? "Restore" : "Maximize");
424
309
  i0.ɵɵadvance();
425
- i0.ɵɵclassProp("fa-window-maximize", !ctx.isMaximized)("fa-window-restore", ctx.isMaximized);
310
+ i0.ɵɵclassProp("fa-window-maximize", !ctx.IsMaximized)("fa-window-restore", ctx.IsMaximized);
426
311
  i0.ɵɵadvance(4);
427
- i0.ɵɵconditional(ctx.loading ? 17 : ctx.error ? 18 : 19);
428
- } }, dependencies: [i1.WindowComponent, i1.WindowTitleBarComponent, i2.LoadingComponent, i3.AITestHarnessComponent], styles: ["[_nghost-%COMP%] {\n display: contents;\n }\n \n \n\n\n\n\n \n .minimized-window {\n .k-window-content {\n display: none !important;\n }\n \n .k-window-titlebar {\n border-radius: 4px !important;\n }\n }\n \n .window-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n \n .title-icon {\n color: #666;\n font-size: 16px;\n }\n \n .title-logo {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n }\n \n .window-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n \n .window-action-btn[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 8px;\n cursor: pointer;\n border-radius: 4px;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n \n &:hover {\n background-color: rgba(0, 0, 0, 0.08);\n }\n \n i {\n font-size: 14px;\n color: #666;\n }\n }\n \n .window-content[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n \n .loading-container[_ngcontent-%COMP%], \n .error-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n }\n \n .error-container[_ngcontent-%COMP%] {\n color: #dc3545;\n \n i {\n font-size: 3rem;\n }\n }\n \n mj-ai-test-harness[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n }\n \n \n\n .k-window-content {\n display: flex;\n flex-direction: column;\n }"] }); }
312
+ i0.ɵɵconditional(ctx.Loading ? 17 : ctx.Error ? 18 : 19);
313
+ } }, dependencies: [i1.MJWindowComponent, i1.MJWindowTitlebarComponent, i2.LoadingComponent, i3.AITestHarnessComponent], styles: ["[_nghost-%COMP%] {\n display: contents;\n }\n\n .window-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n\n .title-icon {\n color: var(--mj-text-muted);\n font-size: 16px;\n }\n\n .title-logo {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n }\n\n .window-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n\n .window-action-btn[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 8px;\n cursor: pointer;\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors);\n display: flex;\n align-items: center;\n justify-content: center;\n\n &:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n i {\n font-size: 14px;\n color: var(--mj-text-muted);\n }\n }\n\n .window-content[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .loading-container[_ngcontent-%COMP%], \n .error-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n }\n\n .error-container[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n\n i {\n font-size: 3rem;\n }\n }\n\n mj-ai-test-harness[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n }\n\n \n\n [_nghost-%COMP%] .mj-window-body {\n display: flex;\n flex-direction: column;\n padding: 0;\n }\n\n \n\n [_nghost-%COMP%] .mj-window-close {\n display: none;\n }"] }); }
429
314
  }
430
315
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestHarnessCustomWindowComponent, [{
431
316
  type: Component,
432
317
  args: [{ standalone: false, selector: 'mj-test-harness-custom-window', template: `
433
- <kendo-window
434
- #kendoWindow
435
- [title]="windowTitle"
436
- [width]="width"
437
- [height]="height"
438
- [top]="windowTop"
439
- [left]="windowLeft"
440
- [minWidth]="isMinimized ? 400 : 800"
441
- [minHeight]="isMinimized ? 60 : 600"
442
- [draggable]="true"
443
- [resizable]="!isMinimized"
444
- [state]="windowState"
445
- [class.minimized-window]="isMinimized"
446
- (close)="onClose()"
447
- (stateChange)="onStateChange($event)"
448
- (resize)="onWindowResize()">
449
-
450
- <kendo-window-titlebar>
318
+ <mj-window
319
+ #mjWindow
320
+ [Visible]="WindowVisible"
321
+ [Title]="''"
322
+ [Width]="Width"
323
+ [Height]="Height"
324
+ [Top]="WindowTop"
325
+ [Left]="WindowLeft"
326
+ [MinWidth]="IsMinimized ? 400 : 800"
327
+ [MinHeight]="IsMinimized ? 60 : 600"
328
+ [Draggable]="true"
329
+ [Resizable]="!IsMinimized"
330
+ [State]="WindowState"
331
+ (Close)="OnClose()"
332
+ (StateChange)="OnStateChange($event)"
333
+ (Resize)="OnWindowResize()">
334
+
335
+ <mj-window-titlebar>
451
336
  <div class="window-title">
452
- @if (mode === 'agent' && agent?.LogoURL) {
453
- <img [src]="agent?.LogoURL" class="title-logo" alt="Agent logo" />
454
- } @else if (mode === 'agent') {
337
+ @if (Mode === 'agent' && Agent?.LogoURL) {
338
+ <img [src]="Agent?.LogoURL" class="title-logo" alt="Agent logo" />
339
+ } @else if (Mode === 'agent') {
455
340
  <i class="fa-solid fa-robot title-icon"></i>
456
341
  } @else {
457
342
  <i class="fa-solid fa-comment-dots title-icon"></i>
458
343
  }
459
- <span>{{ windowTitle }}</span>
344
+ <span>{{ WindowTitle }}</span>
460
345
  </div>
461
346
  <div class="window-actions">
462
- <button
463
- (click)="minimize()"
347
+ <button
348
+ (click)="Minimize()"
464
349
  title="Minimize"
465
350
  class="window-action-btn">
466
351
  <i class="fa-solid fa-window-minimize"></i>
467
352
  </button>
468
- <button
469
- (click)="toggleMaximize()"
470
- [title]="isMaximized ? 'Restore' : 'Maximize'"
353
+ <button
354
+ (click)="ToggleMaximize()"
355
+ [title]="IsMaximized ? 'Restore' : 'Maximize'"
471
356
  class="window-action-btn">
472
- <i class="fa-solid" [class.fa-window-maximize]="!isMaximized" [class.fa-window-restore]="isMaximized"></i>
357
+ <i class="fa-solid" [class.fa-window-maximize]="!IsMaximized" [class.fa-window-restore]="IsMaximized"></i>
473
358
  </button>
474
- <button
475
- (click)="closeButtonClick()"
359
+ <button
360
+ (click)="CloseButtonClick()"
476
361
  title="Close"
477
362
  class="window-action-btn">
478
363
  <i class="fa-solid fa-xmark"></i>
479
364
  </button>
480
365
  </div>
481
- </kendo-window-titlebar>
482
-
366
+ </mj-window-titlebar>
367
+
483
368
  <div class="window-content">
484
- @if (loading) {
369
+ @if (Loading) {
485
370
  <div class="loading-container">
486
- <mj-loading [text]="'Loading ' + (mode === 'agent' ? 'AI Agent' : 'AI Prompt') + '...'" size="large"></mj-loading>
371
+ <mj-loading [text]="'Loading ' + (Mode === 'agent' ? 'AI Agent' : 'AI Prompt') + '...'" size="large"></mj-loading>
487
372
  </div>
488
373
  }
489
- @else if (error) {
374
+ @else if (Error) {
490
375
  <div class="error-container">
491
376
  <i class="fa-solid fa-exclamation-triangle"></i>
492
- <p>{{ error }}</p>
377
+ <p>{{ Error }}</p>
493
378
  </div>
494
379
  }
495
380
  @else {
496
381
  <mj-ai-test-harness
497
- [entity]="(agent || prompt) || null"
498
- [mode]="mode"
382
+ [entity]="(Agent || Prompt) || null"
383
+ [mode]="Mode"
499
384
  [isVisible]="true"
500
- (runOpened)="onRunOpened($event)">
385
+ (runOpened)="OnRunOpened($event)">
501
386
  </mj-ai-test-harness>
502
387
  }
503
388
  </div>
504
- </kendo-window>
505
- `, styles: ["\n :host {\n display: contents;\n }\n \n /* Remove animation for snappy performance\n ::ng-deep .window-transition {\n transition: all 0.6s ease-in-out !important;\n } */\n \n ::ng-deep .minimized-window {\n .k-window-content {\n display: none !important;\n }\n \n .k-window-titlebar {\n border-radius: 4px !important;\n }\n }\n \n .window-title {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n \n .title-icon {\n color: #666;\n font-size: 16px;\n }\n \n .title-logo {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n }\n \n .window-actions {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n \n .window-action-btn {\n background: transparent;\n border: none;\n padding: 8px;\n cursor: pointer;\n border-radius: 4px;\n transition: background-color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n \n &:hover {\n background-color: rgba(0, 0, 0, 0.08);\n }\n \n i {\n font-size: 14px;\n color: #666;\n }\n }\n \n .window-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n \n .loading-container,\n .error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n }\n \n .error-container {\n color: #dc3545;\n \n i {\n font-size: 3rem;\n }\n }\n \n mj-ai-test-harness {\n flex: 1;\n overflow: hidden;\n }\n \n /* Ensure Kendo Window content wrapper maintains proper height */\n ::ng-deep .k-window-content {\n display: flex;\n flex-direction: column;\n }\n "] }]
506
- }], () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], { kendoWindow: [{
389
+ </mj-window>
390
+ `, styles: ["\n :host {\n display: contents;\n }\n\n .window-title {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n\n .title-icon {\n color: var(--mj-text-muted);\n font-size: 16px;\n }\n\n .title-logo {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n }\n\n .window-actions {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n\n .window-action-btn {\n background: transparent;\n border: none;\n padding: 8px;\n cursor: pointer;\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors);\n display: flex;\n align-items: center;\n justify-content: center;\n\n &:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n i {\n font-size: 14px;\n color: var(--mj-text-muted);\n }\n }\n\n .window-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .loading-container,\n .error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n }\n\n .error-container {\n color: var(--mj-status-error);\n\n i {\n font-size: 3rem;\n }\n }\n\n mj-ai-test-harness {\n flex: 1;\n overflow: hidden;\n }\n\n /* Ensure mj-window body fills available space for the test harness */\n :host ::ng-deep .mj-window-body {\n display: flex;\n flex-direction: column;\n padding: 0;\n }\n\n /* Hide the default close button since we have custom titlebar actions */\n :host ::ng-deep .mj-window-close {\n display: none;\n }\n "] }]
391
+ }], null, { MjWindow: [{
507
392
  type: ViewChild,
508
- args: ['kendoWindow', { static: false }]
509
- }], testHarness: [{
393
+ args: ['mjWindow', { static: false }]
394
+ }], TestHarness: [{
510
395
  type: ViewChild,
511
396
  args: [AITestHarnessComponent, { static: false }]
512
- }], data: [{
397
+ }], Data: [{
513
398
  type: Input
514
- }], closeWindow: [{
399
+ }], CloseWindow: [{
515
400
  type: Output
516
- }], minimizeWindow: [{
401
+ }], MinimizeWindow: [{
517
402
  type: Output
518
- }], restoreWindow: [{
403
+ }], RestoreWindow: [{
519
404
  type: Output
520
- }], executionStateChange: [{
405
+ }], ExecutionStateChange: [{
521
406
  type: Output
522
407
  }] }); })();
523
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestHarnessCustomWindowComponent, { className: "TestHarnessCustomWindowComponent", filePath: "lib/test-harness-custom-window.component.ts", lineNumber: 200 }); })();
408
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestHarnessCustomWindowComponent, { className: "TestHarnessCustomWindowComponent", filePath: "lib/test-harness-custom-window.component.ts", lineNumber: 191 }); })();
524
409
  //# sourceMappingURL=test-harness-custom-window.component.js.map