@memberjunction/ng-ai-test-harness 5.22.0 → 5.23.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.
@@ -7,16 +7,14 @@ import { AIEngineBase } from '@memberjunction/ai-engine-base';
7
7
  import { ParseJSONRecursive, UUIDsEqual } from '@memberjunction/global';
8
8
  import * as i0 from "@angular/core";
9
9
  import * as i1 from "@angular/platform-browser";
10
- import * as i2 from "@progress/kendo-angular-dialog";
11
- import * as i3 from "@angular/router";
12
- import * as i4 from "@angular/common";
13
- import * as i5 from "@angular/forms";
14
- import * as i6 from "@progress/kendo-angular-buttons";
15
- import * as i7 from "@progress/kendo-angular-dropdowns";
16
- import * as i8 from "@progress/kendo-angular-inputs";
17
- import * as i9 from "@progress/kendo-angular-layout";
18
- import * as i10 from "@memberjunction/ng-code-editor";
19
- import * as i11 from "./agent-execution-monitor.component";
10
+ import * as i2 from "@angular/router";
11
+ import * as i3 from "@angular/common";
12
+ import * as i4 from "@angular/forms";
13
+ import * as i5 from "@memberjunction/ng-ui-components";
14
+ import * as i6 from "angular-split";
15
+ import * as i7 from "@memberjunction/ng-code-editor";
16
+ import * as i8 from "./json-viewer-window.component";
17
+ import * as i9 from "./agent-execution-monitor.component";
20
18
  const _c0 = ["messagesContainer"];
21
19
  const _c1 = ["fileInput"];
22
20
  const _c2 = ["messageInput"];
@@ -29,7 +27,7 @@ const _c8 = (a0, a1, a2, a3) => [a0, a1, a2, a3];
29
27
  const _forTrack0 = ($index, $item) => $item.id;
30
28
  const _forTrack1 = ($index, $item) => $item.ID;
31
29
  function AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
32
- i0.ɵɵelement(0, "img", 13);
30
+ i0.ɵɵelement(0, "img", 14);
33
31
  } if (rf & 2) {
34
32
  const ctx_r1 = i0.ɵɵnextContext(3);
35
33
  i0.ɵɵproperty("src", ctx_r1.getEntityLogoURL(), i0.ɵɵsanitizeUrl)("alt", ctx_r1.getEntityName() + " logo");
@@ -51,39 +49,39 @@ function AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_7_Templa
51
49
  } }
52
50
  function AITestHarnessComponent_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
53
51
  const _r1 = i0.ɵɵgetCurrentView();
54
- i0.ɵɵelementStart(0, "div", 8)(1, "div", 12);
55
- i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_2_Template, 1, 2, "img", 13)(3, AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_3_Template, 1, 2, "i", 14);
52
+ i0.ɵɵelementStart(0, "div", 9)(1, "div", 13);
53
+ i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_2_Template, 1, 2, "img", 14)(3, AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_3_Template, 1, 2, "i", 15);
56
54
  i0.ɵɵelementStart(4, "div")(5, "h3");
57
55
  i0.ɵɵtext(6);
58
56
  i0.ɵɵelementEnd();
59
57
  i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_2_Conditional_7_Template, 2, 1, "p");
60
58
  i0.ɵɵelementEnd()();
61
- i0.ɵɵelementStart(8, "div", 15)(9, "button", 16);
59
+ i0.ɵɵelementStart(8, "div", 16)(9, "button", 17);
62
60
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.clearConversation()); });
63
- i0.ɵɵelement(10, "i", 17);
61
+ i0.ɵɵelement(10, "i", 18);
64
62
  i0.ɵɵtext(11, " Clear ");
65
63
  i0.ɵɵelementEnd();
66
- i0.ɵɵelementStart(12, "button", 18);
64
+ i0.ɵɵelementStart(12, "button", 19);
67
65
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.saveConversation()); });
68
- i0.ɵɵelement(13, "i", 19);
66
+ i0.ɵɵelement(13, "i", 20);
69
67
  i0.ɵɵtext(14, " Save ");
70
68
  i0.ɵɵelementEnd();
71
- i0.ɵɵelementStart(15, "button", 20);
69
+ i0.ɵɵelementStart(15, "button", 21);
72
70
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.exportConversation()); });
73
- i0.ɵɵelement(16, "i", 21);
71
+ i0.ɵɵelement(16, "i", 22);
74
72
  i0.ɵɵtext(17, " Export ");
75
73
  i0.ɵɵelementEnd();
76
- i0.ɵɵelementStart(18, "button", 22);
74
+ i0.ɵɵelementStart(18, "button", 23);
77
75
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.importConversation()); });
78
- i0.ɵɵelement(19, "i", 23);
76
+ i0.ɵɵelement(19, "i", 24);
79
77
  i0.ɵɵtext(20, " Import ");
80
78
  i0.ɵɵelementEnd();
81
- i0.ɵɵelementStart(21, "input", 24, 0);
79
+ i0.ɵɵelementStart(21, "input", 25, 0);
82
80
  i0.ɵɵlistener("change", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_input_change_21_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onFileSelected($event)); });
83
81
  i0.ɵɵelementEnd();
84
- i0.ɵɵelementStart(23, "button", 25);
82
+ i0.ɵɵelementStart(23, "button", 26);
85
83
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_2_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleSidebar()); });
86
- i0.ɵɵelement(24, "i", 26);
84
+ i0.ɵɵelement(24, "i", 27);
87
85
  i0.ɵɵelementEnd()()();
88
86
  } if (rf & 2) {
89
87
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -103,7 +101,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_2_Template(rf, ctx) {
103
101
  i0.ɵɵclassProp("fa-chevron-right", !ctx_r1.showSidebar)("fa-chevron-left", ctx_r1.showSidebar);
104
102
  } }
105
103
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
106
- i0.ɵɵelementStart(0, "div", 29);
104
+ i0.ɵɵelementStart(0, "div", 30);
107
105
  i0.ɵɵelement(1, "i", 44);
108
106
  i0.ɵɵelementStart(2, "h4");
109
107
  i0.ɵɵtext(3, "Start a conversation");
@@ -129,7 +127,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_
129
127
  i0.ɵɵclassMap(ctx_r1.getEntityIconClass());
130
128
  } }
131
129
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Template(rf, ctx) { if (rf & 1) {
132
- i0.ɵɵconditionalCreate(0, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_0_Template, 1, 2, "img", 59)(1, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_1_Template, 1, 2, "i", 14);
130
+ i0.ɵɵconditionalCreate(0, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_0_Template, 1, 2, "img", 59)(1, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_1_Template, 1, 2, "i", 15);
133
131
  i0.ɵɵtext(2);
134
132
  } if (rf & 2) {
135
133
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -214,7 +212,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16
214
212
  i0.ɵɵtext(4, " Payload ");
215
213
  i0.ɵɵelementEnd();
216
214
  i0.ɵɵelementStart(5, "button", 69);
217
- i0.ɵɵelement(6, "i", 26);
215
+ i0.ɵɵelement(6, "i", 27);
218
216
  i0.ɵɵelementEnd()();
219
217
  i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Conditional_7_Template, 2, 3, "div", 70);
220
218
  i0.ɵɵelementEnd();
@@ -228,7 +226,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16
228
226
  } }
229
227
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template(rf, ctx) { if (rf & 1) {
230
228
  const _r4 = i0.ɵɵgetCurrentView();
231
- i0.ɵɵelementStart(0, "div", 30)(1, "div", 45)(2, "span", 46);
229
+ i0.ɵɵelementStart(0, "div", 31)(1, "div", 45)(2, "span", 46);
232
230
  i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_3_Template, 2, 0)(4, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Template, 3, 2);
233
231
  i0.ɵɵelementEnd();
234
232
  i0.ɵɵelementStart(5, "span", 47);
@@ -301,7 +299,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Condit
301
299
  i0.ɵɵproperty("disabled", ctx_r1.isExecuting);
302
300
  } }
303
301
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Template(rf, ctx) { if (rf & 1) {
304
- i0.ɵɵelementStart(0, "div", 32)(1, "div", 72);
302
+ i0.ɵɵelementStart(0, "div", 33)(1, "div", 72);
305
303
  i0.ɵɵelement(2, "i", 73);
306
304
  i0.ɵɵelementStart(3, "span");
307
305
  i0.ɵɵtext(4, "Messages from Prompt Run ");
@@ -328,9 +326,9 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Condi
328
326
  } }
329
327
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
330
328
  const _r10 = i0.ɵɵgetCurrentView();
331
- i0.ɵɵelementStart(0, "div", 33)(1, "kendo-textarea", 81, 2);
332
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template_kendo_textarea_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.currentUserMessage, $event) || (ctx_r1.currentUserMessage = $event); return i0.ɵɵresetView($event); });
333
- i0.ɵɵlistener("keypress", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template_kendo_textarea_keypress_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.handleKeyPress($event)); });
329
+ i0.ɵɵelementStart(0, "div", 34)(1, "textarea", 81, 2);
330
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template_textarea_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.currentUserMessage, $event) || (ctx_r1.currentUserMessage = $event); return i0.ɵɵresetView($event); });
331
+ i0.ɵɵlistener("keypress", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template_textarea_keypress_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.handleKeyPress($event)); });
334
332
  i0.ɵɵelementEnd();
335
333
  i0.ɵɵelementStart(3, "button", 82);
336
334
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.sendMessage()); });
@@ -407,14 +405,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Condi
407
405
  } }
408
406
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template(rf, ctx) { if (rf & 1) {
409
407
  const _r14 = i0.ɵɵgetCurrentView();
410
- i0.ɵɵelementStart(0, "div", 90)(1, "kendo-textbox", 93);
411
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_kendo_textbox_ngModelChange_1_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.name, $event) || (variable_r15.name = $event); return i0.ɵɵresetView($event); });
408
+ i0.ɵɵelementStart(0, "div", 90)(1, "input", 93);
409
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_input_ngModelChange_1_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.name, $event) || (variable_r15.name = $event); return i0.ɵɵresetView($event); });
412
410
  i0.ɵɵelementEnd();
413
- i0.ɵɵelementStart(2, "kendo-dropdownlist", 94);
414
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_kendo_dropdownlist_ngModelChange_2_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.type, $event) || (variable_r15.type = $event); return i0.ɵɵresetView($event); });
411
+ i0.ɵɵelementStart(2, "mj-dropdown", 94);
412
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_mj_dropdown_ngModelChange_2_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.type, $event) || (variable_r15.type = $event); return i0.ɵɵresetView($event); });
415
413
  i0.ɵɵelementEnd();
416
- i0.ɵɵelementStart(3, "kendo-textbox", 95);
417
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_kendo_textbox_ngModelChange_3_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.value, $event) || (variable_r15.value = $event); return i0.ɵɵresetView($event); });
414
+ i0.ɵɵelementStart(3, "input", 95);
415
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_input_ngModelChange_3_listener($event) { const variable_r15 = i0.ɵɵrestoreView(_r14).$implicit; i0.ɵɵtwoWayBindingSet(variable_r15.value, $event) || (variable_r15.value = $event); return i0.ɵɵresetView($event); });
418
416
  i0.ɵɵelementEnd();
419
417
  i0.ɵɵelementStart(4, "button", 96);
420
418
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template_button_click_4_listener() { const $index_r16 = i0.ɵɵrestoreView(_r14).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.removeAgentVariable($index_r16)); });
@@ -428,7 +426,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9
428
426
  i0.ɵɵproperty("disabled", ctx_r1.isExecuting);
429
427
  i0.ɵɵadvance();
430
428
  i0.ɵɵtwoWayProperty("ngModel", variable_r15.type);
431
- i0.ɵɵproperty("data", i0.ɵɵpureFunction4(14, _c8, i0.ɵɵpureFunction0(10, _c4), i0.ɵɵpureFunction0(11, _c5), i0.ɵɵpureFunction0(12, _c6), i0.ɵɵpureFunction0(13, _c7)))("valuePrimitive", true)("disabled", ctx_r1.isExecuting);
429
+ i0.ɵɵproperty("Data", i0.ɵɵpureFunction4(14, _c8, i0.ɵɵpureFunction0(10, _c4), i0.ɵɵpureFunction0(11, _c5), i0.ɵɵpureFunction0(12, _c6), i0.ɵɵpureFunction0(13, _c7)))("ValuePrimitive", true)("Disabled", ctx_r1.isExecuting);
432
430
  i0.ɵɵadvance();
433
431
  i0.ɵɵtwoWayProperty("ngModel", variable_r15.value);
434
432
  i0.ɵɵproperty("placeholder", variable_r15.type === "object" ? "JSON value" : "Value")("disabled", ctx_r1.isExecuting);
@@ -504,8 +502,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Templ
504
502
  i0.ɵɵelementStart(6, "div", 99)(7, "div", 100)(8, "label");
505
503
  i0.ɵɵtext(9, "AI Configuration");
506
504
  i0.ɵɵelementEnd();
507
- i0.ɵɵelementStart(10, "kendo-dropdownlist", 101);
508
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Template_kendo_dropdownlist_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.agentConfigurationId, $event) || (ctx_r1.agentConfigurationId = $event); return i0.ɵɵresetView($event); });
505
+ i0.ɵɵelementStart(10, "mj-dropdown", 101);
506
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Template_mj_dropdown_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.agentConfigurationId, $event) || (ctx_r1.agentConfigurationId = $event); return i0.ɵɵresetView($event); });
509
507
  i0.ɵɵelementEnd();
510
508
  i0.ɵɵelementStart(11, "div", 102);
511
509
  i0.ɵɵconditionalCreate(12, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Conditional_12_Template, 2, 0)(13, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Conditional_13_Template, 1, 0);
@@ -514,20 +512,20 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Templ
514
512
  const ctx_r1 = i0.ɵɵnextContext(3);
515
513
  i0.ɵɵadvance(10);
516
514
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.agentConfigurationId);
517
- i0.ɵɵproperty("data", ctx_r1.availableConfigurations)("valuePrimitive", true);
515
+ i0.ɵɵproperty("Data", ctx_r1.availableConfigurations)("ValuePrimitive", true);
518
516
  i0.ɵɵadvance(2);
519
517
  i0.ɵɵconditional(ctx_r1.agentConfigurationId ? 12 : 13);
520
518
  } }
521
519
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template(rf, ctx) { if (rf & 1) {
522
520
  const _r21 = i0.ɵɵgetCurrentView();
523
- i0.ɵɵelementStart(0, "div", 90)(1, "kendo-textbox", 93);
524
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_kendo_textbox_ngModelChange_1_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.name, $event) || (variable_r22.name = $event); return i0.ɵɵresetView($event); });
521
+ i0.ɵɵelementStart(0, "div", 90)(1, "input", 93);
522
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_input_ngModelChange_1_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.name, $event) || (variable_r22.name = $event); return i0.ɵɵresetView($event); });
525
523
  i0.ɵɵelementEnd();
526
- i0.ɵɵelementStart(2, "kendo-dropdownlist", 94);
527
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_kendo_dropdownlist_ngModelChange_2_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.type, $event) || (variable_r22.type = $event); return i0.ɵɵresetView($event); });
524
+ i0.ɵɵelementStart(2, "mj-dropdown", 94);
525
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_mj_dropdown_ngModelChange_2_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.type, $event) || (variable_r22.type = $event); return i0.ɵɵresetView($event); });
528
526
  i0.ɵɵelementEnd();
529
- i0.ɵɵelementStart(3, "kendo-textbox", 95);
530
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_kendo_textbox_ngModelChange_3_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.value, $event) || (variable_r22.value = $event); return i0.ɵɵresetView($event); });
527
+ i0.ɵɵelementStart(3, "input", 95);
528
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_input_ngModelChange_3_listener($event) { const variable_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(variable_r22.value, $event) || (variable_r22.value = $event); return i0.ɵɵresetView($event); });
531
529
  i0.ɵɵelementEnd();
532
530
  i0.ɵɵelementStart(4, "button", 104);
533
531
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template_button_click_4_listener() { const $index_r23 = i0.ɵɵrestoreView(_r21).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.removeTemplateVariable($index_r23)); });
@@ -541,7 +539,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8
541
539
  i0.ɵɵproperty("disabled", ctx_r1.isExecuting);
542
540
  i0.ɵɵadvance();
543
541
  i0.ɵɵtwoWayProperty("ngModel", variable_r22.type);
544
- i0.ɵɵproperty("data", i0.ɵɵpureFunction4(13, _c8, i0.ɵɵpureFunction0(9, _c4), i0.ɵɵpureFunction0(10, _c5), i0.ɵɵpureFunction0(11, _c6), i0.ɵɵpureFunction0(12, _c7)))("valuePrimitive", true)("disabled", ctx_r1.isExecuting);
542
+ i0.ɵɵproperty("Data", i0.ɵɵpureFunction4(13, _c8, i0.ɵɵpureFunction0(9, _c4), i0.ɵɵpureFunction0(10, _c5), i0.ɵɵpureFunction0(11, _c6), i0.ɵɵpureFunction0(12, _c7)))("ValuePrimitive", true)("Disabled", ctx_r1.isExecuting);
545
543
  i0.ɵɵadvance();
546
544
  i0.ɵɵtwoWayProperty("ngModel", variable_r22.value);
547
545
  i0.ɵɵproperty("placeholder", variable_r22.type === "object" ? "JSON value" : "Value")("disabled", ctx_r1.isExecuting);
@@ -603,14 +601,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Condi
603
601
  i0.ɵɵelementStart(0, "div", 100)(1, "label", 128);
604
602
  i0.ɵɵtext(2, " Top Log Probs ");
605
603
  i0.ɵɵelementEnd();
606
- i0.ɵɵelementStart(3, "kendo-numerictextbox", 129);
607
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template_kendo_numerictextbox_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r26); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topLogProbs, $event) || (ctx_r1.advancedParams.topLogProbs = $event); return i0.ɵɵresetView($event); });
604
+ i0.ɵɵelementStart(3, "mj-numeric-input", 129);
605
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template_mj_numeric_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r26); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topLogProbs, $event) || (ctx_r1.advancedParams.topLogProbs = $event); return i0.ɵɵresetView($event); });
608
606
  i0.ɵɵelementEnd()();
609
607
  } if (rf & 2) {
610
608
  const ctx_r1 = i0.ɵɵnextContext(4);
611
609
  i0.ɵɵadvance(3);
612
610
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.topLogProbs);
613
- i0.ɵɵproperty("min", 2)("max", 20)("step", 1)("format", "n0");
611
+ i0.ɵɵproperty("Min", 2)("Max", 20)("Step", 1)("Format", "n0");
614
612
  } }
615
613
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template(rf, ctx) { if (rf & 1) {
616
614
  const _r24 = i0.ɵɵgetCurrentView();
@@ -627,15 +625,15 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
627
625
  i0.ɵɵelementStart(8, "div", 99)(9, "div", 100)(10, "label");
628
626
  i0.ɵɵtext(11, "AI Model");
629
627
  i0.ɵɵelementEnd();
630
- i0.ɵɵelementStart(12, "kendo-dropdownlist", 107);
631
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_dropdownlist_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedModelId, $event) || (ctx_r1.selectedModelId = $event); return i0.ɵɵresetView($event); });
632
- i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_dropdownlist_ngModelChange_12_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onModelSelectionChange()); });
628
+ i0.ɵɵelementStart(12, "mj-dropdown", 107);
629
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_dropdown_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedModelId, $event) || (ctx_r1.selectedModelId = $event); return i0.ɵɵresetView($event); });
630
+ i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_dropdown_ngModelChange_12_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onModelSelectionChange()); });
633
631
  i0.ɵɵelementEnd()();
634
632
  i0.ɵɵelementStart(13, "div", 100)(14, "label");
635
633
  i0.ɵɵtext(15, "AI Vendor");
636
634
  i0.ɵɵelementEnd();
637
- i0.ɵɵelementStart(16, "kendo-dropdownlist", 108);
638
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_dropdownlist_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedVendorId, $event) || (ctx_r1.selectedVendorId = $event); return i0.ɵɵresetView($event); });
635
+ i0.ɵɵelementStart(16, "mj-dropdown", 108);
636
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_dropdown_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedVendorId, $event) || (ctx_r1.selectedVendorId = $event); return i0.ɵɵresetView($event); });
639
637
  i0.ɵɵelementEnd();
640
638
  i0.ɵɵelementStart(17, "div", 102);
641
639
  i0.ɵɵconditionalCreate(18, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_18_Template, 1, 0)(19, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_19_Template, 1, 0)(20, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_20_Template, 1, 0);
@@ -643,8 +641,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
643
641
  i0.ɵɵelementStart(21, "div", 100)(22, "label");
644
642
  i0.ɵɵtext(23, "AI Configuration");
645
643
  i0.ɵɵelementEnd();
646
- i0.ɵɵelementStart(24, "kendo-dropdownlist", 101);
647
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_dropdownlist_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedConfigurationId, $event) || (ctx_r1.selectedConfigurationId = $event); return i0.ɵɵresetView($event); });
644
+ i0.ɵɵelementStart(24, "mj-dropdown", 101);
645
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_dropdown_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedConfigurationId, $event) || (ctx_r1.selectedConfigurationId = $event); return i0.ɵɵresetView($event); });
648
646
  i0.ɵɵelementEnd();
649
647
  i0.ɵɵelementStart(25, "div", 102);
650
648
  i0.ɵɵconditionalCreate(26, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_26_Template, 2, 0)(27, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_27_Template, 1, 0);
@@ -652,8 +650,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
652
650
  i0.ɵɵelementStart(28, "div", 100)(29, "label");
653
651
  i0.ɵɵtext(30, "Response Format");
654
652
  i0.ɵɵelementEnd();
655
- i0.ɵɵelementStart(31, "kendo-dropdownlist", 109);
656
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_dropdownlist_ngModelChange_31_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedResponseFormat, $event) || (ctx_r1.selectedResponseFormat = $event); return i0.ɵɵresetView($event); });
653
+ i0.ɵɵelementStart(31, "mj-dropdown", 109);
654
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_dropdown_ngModelChange_31_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedResponseFormat, $event) || (ctx_r1.selectedResponseFormat = $event); return i0.ɵɵresetView($event); });
657
655
  i0.ɵɵelementEnd();
658
656
  i0.ɵɵelementStart(32, "div", 102);
659
657
  i0.ɵɵtext(33, " Expected format for AI response (defaults to prompt setting) ");
@@ -661,8 +659,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
661
659
  i0.ɵɵelementStart(34, "div", 100)(35, "label");
662
660
  i0.ɵɵtext(36, "Max Tokens");
663
661
  i0.ɵɵelementEnd();
664
- i0.ɵɵelementStart(37, "kendo-numerictextbox", 110);
665
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.maxTokens, $event) || (ctx_r1.maxTokens = $event); return i0.ɵɵresetView($event); });
662
+ i0.ɵɵelementStart(37, "mj-numeric-input", 110);
663
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.maxTokens, $event) || (ctx_r1.maxTokens = $event); return i0.ɵɵresetView($event); });
666
664
  i0.ɵɵelementEnd();
667
665
  i0.ɵɵelementStart(38, "div", 102);
668
666
  i0.ɵɵtext(39, " Maximum length of generated response ");
@@ -675,56 +673,54 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
675
673
  i0.ɵɵelementStart(44, "div", 102);
676
674
  i0.ɵɵtext(45, " Skip output validation during testing ");
677
675
  i0.ɵɵelementEnd()();
678
- i0.ɵɵelementStart(46, "kendo-expansionpanel", 113);
679
- i0.ɵɵlistener("action", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_expansionpanel_action_46_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleAdvancedParams()); });
680
- i0.ɵɵelementStart(47, "div", 114)(48, "div", 100)(49, "label", 115);
676
+ i0.ɵɵelementStart(46, "mj-accordion-panel", 113)(47, "div", 114)(48, "div", 100)(49, "label", 115);
681
677
  i0.ɵɵtext(50, " Temperature ");
682
678
  i0.ɵɵelementEnd();
683
- i0.ɵɵelementStart(51, "kendo-numerictextbox", 116);
684
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_51_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.temperature, $event) || (ctx_r1.advancedParams.temperature = $event); return i0.ɵɵresetView($event); });
679
+ i0.ɵɵelementStart(51, "mj-numeric-input", 116);
680
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_51_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.temperature, $event) || (ctx_r1.advancedParams.temperature = $event); return i0.ɵɵresetView($event); });
685
681
  i0.ɵɵelementEnd()();
686
682
  i0.ɵɵelementStart(52, "div", 100)(53, "label", 117);
687
683
  i0.ɵɵtext(54, " Top P ");
688
684
  i0.ɵɵelementEnd();
689
- i0.ɵɵelementStart(55, "kendo-numerictextbox", 116);
690
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_55_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topP, $event) || (ctx_r1.advancedParams.topP = $event); return i0.ɵɵresetView($event); });
685
+ i0.ɵɵelementStart(55, "mj-numeric-input", 116);
686
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_55_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topP, $event) || (ctx_r1.advancedParams.topP = $event); return i0.ɵɵresetView($event); });
691
687
  i0.ɵɵelementEnd()();
692
688
  i0.ɵɵelementStart(56, "div", 100)(57, "label", 118);
693
689
  i0.ɵɵtext(58, " Top K ");
694
690
  i0.ɵɵelementEnd();
695
- i0.ɵɵelementStart(59, "kendo-numerictextbox", 116);
696
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_59_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topK, $event) || (ctx_r1.advancedParams.topK = $event); return i0.ɵɵresetView($event); });
691
+ i0.ɵɵelementStart(59, "mj-numeric-input", 116);
692
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_59_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topK, $event) || (ctx_r1.advancedParams.topK = $event); return i0.ɵɵresetView($event); });
697
693
  i0.ɵɵelementEnd()();
698
694
  i0.ɵɵelementStart(60, "div", 100)(61, "label", 119);
699
695
  i0.ɵɵtext(62, " Min P ");
700
696
  i0.ɵɵelementEnd();
701
- i0.ɵɵelementStart(63, "kendo-numerictextbox", 116);
702
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_63_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.minP, $event) || (ctx_r1.advancedParams.minP = $event); return i0.ɵɵresetView($event); });
697
+ i0.ɵɵelementStart(63, "mj-numeric-input", 116);
698
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_63_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.minP, $event) || (ctx_r1.advancedParams.minP = $event); return i0.ɵɵresetView($event); });
703
699
  i0.ɵɵelementEnd()();
704
700
  i0.ɵɵelementStart(64, "div", 100)(65, "label", 120);
705
701
  i0.ɵɵtext(66, " Frequency Penalty ");
706
702
  i0.ɵɵelementEnd();
707
- i0.ɵɵelementStart(67, "kendo-numerictextbox", 116);
708
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_67_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.frequencyPenalty, $event) || (ctx_r1.advancedParams.frequencyPenalty = $event); return i0.ɵɵresetView($event); });
703
+ i0.ɵɵelementStart(67, "mj-numeric-input", 116);
704
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_67_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.frequencyPenalty, $event) || (ctx_r1.advancedParams.frequencyPenalty = $event); return i0.ɵɵresetView($event); });
709
705
  i0.ɵɵelementEnd()();
710
706
  i0.ɵɵelementStart(68, "div", 100)(69, "label", 121);
711
707
  i0.ɵɵtext(70, " Presence Penalty ");
712
708
  i0.ɵɵelementEnd();
713
- i0.ɵɵelementStart(71, "kendo-numerictextbox", 116);
714
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_71_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.presencePenalty, $event) || (ctx_r1.advancedParams.presencePenalty = $event); return i0.ɵɵresetView($event); });
709
+ i0.ɵɵelementStart(71, "mj-numeric-input", 116);
710
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_71_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.presencePenalty, $event) || (ctx_r1.advancedParams.presencePenalty = $event); return i0.ɵɵresetView($event); });
715
711
  i0.ɵɵelementEnd()();
716
712
  i0.ɵɵelementStart(72, "div", 100)(73, "label", 122);
717
713
  i0.ɵɵtext(74, " Seed ");
718
714
  i0.ɵɵelementEnd();
719
- i0.ɵɵelementStart(75, "kendo-numerictextbox", 123);
720
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_numerictextbox_ngModelChange_75_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.seed, $event) || (ctx_r1.advancedParams.seed = $event); return i0.ɵɵresetView($event); });
715
+ i0.ɵɵelementStart(75, "mj-numeric-input", 123);
716
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_numeric_input_ngModelChange_75_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.seed, $event) || (ctx_r1.advancedParams.seed = $event); return i0.ɵɵresetView($event); });
721
717
  i0.ɵɵelementEnd()();
722
718
  i0.ɵɵelementStart(76, "div", 100)(77, "label", 124);
723
719
  i0.ɵɵtext(78, " Stop Sequences ");
724
720
  i0.ɵɵelementEnd();
725
- i0.ɵɵelementStart(79, "kendo-textarea", 125);
726
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_textarea_ngModelChange_79_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.stopSequencesText, $event) || (ctx_r1.stopSequencesText = $event); return i0.ɵɵresetView($event); });
727
- i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_textarea_ngModelChange_79_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.updateStopSequences()); });
721
+ i0.ɵɵelementStart(79, "textarea", 125);
722
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_textarea_ngModelChange_79_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.stopSequencesText, $event) || (ctx_r1.stopSequencesText = $event); return i0.ɵɵresetView($event); });
723
+ i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_textarea_ngModelChange_79_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.updateStopSequences()); });
728
724
  i0.ɵɵelementEnd();
729
725
  i0.ɵɵelementStart(80, "div", 102);
730
726
  i0.ɵɵtext(81, " Separate multiple sequences with commas ");
@@ -732,8 +728,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
732
728
  i0.ɵɵelementStart(82, "div", 100)(83, "label", 126);
733
729
  i0.ɵɵtext(84, " Include Log Probs ");
734
730
  i0.ɵɵelementEnd();
735
- i0.ɵɵelementStart(85, "kendo-switch", 127);
736
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_kendo_switch_ngModelChange_85_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.includeLogProbs, $event) || (ctx_r1.advancedParams.includeLogProbs = $event); return i0.ɵɵresetView($event); });
731
+ i0.ɵɵelementStart(85, "mj-switch", 127);
732
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_mj_switch_ngModelChange_85_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.includeLogProbs, $event) || (ctx_r1.advancedParams.includeLogProbs = $event); return i0.ɵɵresetView($event); });
737
733
  i0.ɵɵelementEnd()();
738
734
  i0.ɵɵconditionalCreate(86, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template, 4, 5, "div", 100);
739
735
  i0.ɵɵelementEnd()()()();
@@ -741,48 +737,48 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
741
737
  const ctx_r1 = i0.ɵɵnextContext(3);
742
738
  i0.ɵɵadvance(12);
743
739
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedModelId);
744
- i0.ɵɵproperty("data", ctx_r1.availableModels)("valuePrimitive", true);
740
+ i0.ɵɵproperty("Data", ctx_r1.availableModels)("ValuePrimitive", true);
745
741
  i0.ɵɵadvance(4);
746
742
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedVendorId);
747
- i0.ɵɵproperty("data", ctx_r1.availableVendors)("valuePrimitive", true)("disabled", ctx_r1.availableVendors.length <= 1 || !ctx_r1.selectedModelId);
743
+ i0.ɵɵproperty("Data", ctx_r1.availableVendors)("ValuePrimitive", true)("Disabled", ctx_r1.availableVendors.length <= 1 || !ctx_r1.selectedModelId);
748
744
  i0.ɵɵadvance(2);
749
745
  i0.ɵɵconditional(!ctx_r1.selectedModelId ? 18 : ctx_r1.availableVendors.length <= 1 ? 19 : 20);
750
746
  i0.ɵɵadvance(6);
751
747
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedConfigurationId);
752
- i0.ɵɵproperty("data", ctx_r1.availableConfigurations)("valuePrimitive", true);
748
+ i0.ɵɵproperty("Data", ctx_r1.availableConfigurations)("ValuePrimitive", true);
753
749
  i0.ɵɵadvance(2);
754
750
  i0.ɵɵconditional(ctx_r1.selectedConfigurationId ? 26 : 27);
755
751
  i0.ɵɵadvance(5);
756
752
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedResponseFormat);
757
- i0.ɵɵproperty("data", ctx_r1.responseFormatOptions);
753
+ i0.ɵɵproperty("Data", ctx_r1.responseFormatOptions);
758
754
  i0.ɵɵadvance(6);
759
755
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.maxTokens);
760
- i0.ɵɵproperty("min", 100)("max", 8000)("step", 100);
756
+ i0.ɵɵproperty("Min", 100)("Max", 8000)("Step", 100);
761
757
  i0.ɵɵadvance(5);
762
758
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.skipValidation);
763
759
  i0.ɵɵadvance(4);
764
- i0.ɵɵproperty("expanded", ctx_r1.advancedParamsExpanded);
760
+ i0.ɵɵproperty("Title", "Advanced Parameters")("Expanded", ctx_r1.advancedParamsExpanded);
765
761
  i0.ɵɵadvance(5);
766
762
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.temperature);
767
- i0.ɵɵproperty("min", 0)("max", 2)("step", 0.1)("format", "n1");
763
+ i0.ɵɵproperty("Min", 0)("Max", 2)("Step", 0.1)("Format", "n1");
768
764
  i0.ɵɵadvance(4);
769
765
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.topP);
770
- i0.ɵɵproperty("min", 0)("max", 1)("step", 0.01)("format", "n2");
766
+ i0.ɵɵproperty("Min", 0)("Max", 1)("Step", 0.01)("Format", "n2");
771
767
  i0.ɵɵadvance(4);
772
768
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.topK);
773
- i0.ɵɵproperty("min", 1)("max", 100)("step", 1)("format", "n0");
769
+ i0.ɵɵproperty("Min", 1)("Max", 100)("Step", 1)("Format", "n0");
774
770
  i0.ɵɵadvance(4);
775
771
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.minP);
776
- i0.ɵɵproperty("min", 0)("max", 1)("step", 0.01)("format", "n2");
772
+ i0.ɵɵproperty("Min", 0)("Max", 1)("Step", 0.01)("Format", "n2");
777
773
  i0.ɵɵadvance(4);
778
774
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.frequencyPenalty);
779
- i0.ɵɵproperty("min", -2)("max", 2)("step", 0.1)("format", "n1");
775
+ i0.ɵɵproperty("Min", -2)("Max", 2)("Step", 0.1)("Format", "n1");
780
776
  i0.ɵɵadvance(4);
781
777
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.presencePenalty);
782
- i0.ɵɵproperty("min", -2)("max", 2)("step", 0.1)("format", "n1");
778
+ i0.ɵɵproperty("Min", -2)("Max", 2)("Step", 0.1)("Format", "n1");
783
779
  i0.ɵɵadvance(4);
784
780
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.seed);
785
- i0.ɵɵproperty("format", "n0");
781
+ i0.ɵɵproperty("Format", "n0");
786
782
  i0.ɵɵadvance(4);
787
783
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.stopSequencesText);
788
784
  i0.ɵɵproperty("rows", 2);
@@ -859,14 +855,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Templ
859
855
  } }
860
856
  function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
861
857
  const _r3 = i0.ɵɵgetCurrentView();
862
- i0.ɵɵelementStart(0, "kendo-splitter", 10)(1, "kendo-splitter-pane", 27)(2, "div", 11)(3, "div", 28, 1);
863
- i0.ɵɵconditionalCreate(5, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_5_Template, 6, 0, "div", 29);
864
- i0.ɵɵrepeaterCreate(6, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template, 17, 8, "div", 30, _forTrack0);
858
+ i0.ɵɵelementStart(0, "as-split", 11)(1, "as-split-area", 28)(2, "div", 12)(3, "div", 29, 1);
859
+ i0.ɵɵconditionalCreate(5, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_5_Template, 6, 0, "div", 30);
860
+ i0.ɵɵrepeaterCreate(6, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template, 17, 8, "div", 31, _forTrack0);
865
861
  i0.ɵɵelementEnd();
866
- i0.ɵɵelementStart(8, "div", 31);
867
- i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Template, 11, 2, "div", 32)(10, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template, 6, 5, "div", 33);
862
+ i0.ɵɵelementStart(8, "div", 32);
863
+ i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Template, 11, 2, "div", 33)(10, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template, 6, 5, "div", 34);
868
864
  i0.ɵɵelementEnd()()();
869
- i0.ɵɵelementStart(11, "kendo-splitter-pane", 34)(12, "div", 35)(13, "div", 36);
865
+ i0.ɵɵelementStart(11, "as-split-area", 28)(12, "div", 35)(13, "div", 36);
870
866
  i0.ɵɵconditionalCreate(14, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Template, 9, 8)(15, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_15_Template, 6, 4);
871
867
  i0.ɵɵelementStart(16, "button", 37);
872
868
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.selectTab("savedConversations")); });
@@ -879,13 +875,13 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) {
879
875
  i0.ɵɵconditionalCreate(22, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_22_Template, 2, 6, "div", 42);
880
876
  i0.ɵɵconditionalCreate(23, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Template, 14, 4, "div", 41);
881
877
  i0.ɵɵconditionalCreate(24, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_Template, 12, 0, "div", 41);
882
- i0.ɵɵconditionalCreate(25, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template, 87, 56, "div", 43);
878
+ i0.ɵɵconditionalCreate(25, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template, 87, 57, "div", 43);
883
879
  i0.ɵɵconditionalCreate(26, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Template, 11, 2, "div", 41);
884
880
  i0.ɵɵelementEnd()()()();
885
881
  } if (rf & 2) {
886
882
  const ctx_r1 = i0.ɵɵnextContext(2);
887
883
  i0.ɵɵadvance();
888
- i0.ɵɵproperty("collapsible", false)("resizable", true)("min", "400px");
884
+ i0.ɵɵproperty("size", 70);
889
885
  i0.ɵɵadvance(4);
890
886
  i0.ɵɵconditional(ctx_r1.conversationMessages.length === 0 ? 5 : -1);
891
887
  i0.ɵɵadvance();
@@ -893,7 +889,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) {
893
889
  i0.ɵɵadvance(3);
894
890
  i0.ɵɵconditional(ctx_r1.originalPromptRunId && ctx_r1.conversationMessages.length > 0 ? 9 : 10);
895
891
  i0.ɵɵadvance(2);
896
- i0.ɵɵproperty("collapsible", false)("resizable", true)("size", "30%")("min", "300px");
892
+ i0.ɵɵproperty("size", 30);
897
893
  i0.ɵɵadvance(3);
898
894
  i0.ɵɵconditional(ctx_r1.mode === "agent" ? 14 : 15);
899
895
  i0.ɵɵadvance(2);
@@ -915,7 +911,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) {
915
911
  i0.ɵɵconditional(ctx_r1.activeTab === "savedConversations" ? 26 : -1);
916
912
  } }
917
913
  function AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
918
- i0.ɵɵelementStart(0, "div", 29);
914
+ i0.ɵɵelementStart(0, "div", 30);
919
915
  i0.ɵɵelement(1, "i", 44);
920
916
  i0.ɵɵelementStart(2, "h4");
921
917
  i0.ɵɵtext(3, "Start a conversation");
@@ -1026,7 +1022,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18
1026
1022
  i0.ɵɵtext(4, " Payload ");
1027
1023
  i0.ɵɵelementEnd();
1028
1024
  i0.ɵɵelementStart(5, "button", 69);
1029
- i0.ɵɵelement(6, "i", 26);
1025
+ i0.ɵɵelement(6, "i", 27);
1030
1026
  i0.ɵɵelementEnd()();
1031
1027
  i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template, 3, 1, "div", 70);
1032
1028
  i0.ɵɵelementEnd();
@@ -1040,7 +1036,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18
1040
1036
  } }
1041
1037
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template(rf, ctx) { if (rf & 1) {
1042
1038
  const _r31 = i0.ɵɵgetCurrentView();
1043
- i0.ɵɵelementStart(0, "div", 30)(1, "div", 45)(2, "span", 46);
1039
+ i0.ɵɵelementStart(0, "div", 31)(1, "div", 45)(2, "span", 46);
1044
1040
  i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_3_Template, 2, 0)(4, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_4_Template, 2, 1);
1045
1041
  i0.ɵɵelementEnd();
1046
1042
  i0.ɵɵelementStart(5, "span", 47);
@@ -1090,13 +1086,13 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_12_Templ
1090
1086
  } }
1091
1087
  function AITestHarnessComponent_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
1092
1088
  const _r30 = i0.ɵɵgetCurrentView();
1093
- i0.ɵɵelementStart(0, "div", 11)(1, "div", 28, 1);
1094
- i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_3_Template, 6, 0, "div", 29);
1095
- i0.ɵɵrepeaterCreate(4, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template, 19, 10, "div", 30, _forTrack0);
1089
+ i0.ɵɵelementStart(0, "div", 12)(1, "div", 29, 1);
1090
+ i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_3_Template, 6, 0, "div", 30);
1091
+ i0.ɵɵrepeaterCreate(4, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template, 19, 10, "div", 31, _forTrack0);
1096
1092
  i0.ɵɵelementEnd();
1097
- i0.ɵɵelementStart(6, "div", 31)(7, "div", 33)(8, "kendo-textarea", 81, 2);
1098
- i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_5_Template_kendo_textarea_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.currentUserMessage, $event) || (ctx_r1.currentUserMessage = $event); return i0.ɵɵresetView($event); });
1099
- i0.ɵɵlistener("keypress", function AITestHarnessComponent_Conditional_0_Conditional_5_Template_kendo_textarea_keypress_8_listener($event) { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.handleKeyPress($event)); });
1093
+ i0.ɵɵelementStart(6, "div", 32)(7, "div", 34)(8, "textarea", 81, 2);
1094
+ i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_5_Template_textarea_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.currentUserMessage, $event) || (ctx_r1.currentUserMessage = $event); return i0.ɵɵresetView($event); });
1095
+ i0.ɵɵlistener("keypress", function AITestHarnessComponent_Conditional_0_Conditional_5_Template_textarea_keypress_8_listener($event) { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.handleKeyPress($event)); });
1100
1096
  i0.ɵɵelementEnd();
1101
1097
  i0.ɵɵelementStart(10, "button", 82);
1102
1098
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.sendMessage()); });
@@ -1117,11 +1113,11 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_Template(rf, ctx) {
1117
1113
  i0.ɵɵconditional(ctx_r1.isExecuting ? 11 : 12);
1118
1114
  } }
1119
1115
  function AITestHarnessComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
1120
- i0.ɵɵelementStart(0, "div", 4)(1, "div", 7);
1121
- i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_0_Conditional_2_Template, 25, 10, "div", 8);
1116
+ i0.ɵɵelementStart(0, "div", 4)(1, "div", 8);
1117
+ i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_0_Conditional_2_Template, 25, 10, "div", 9);
1122
1118
  i0.ɵɵelementEnd();
1123
- i0.ɵɵelementStart(3, "div", 9);
1124
- i0.ɵɵconditionalCreate(4, AITestHarnessComponent_Conditional_0_Conditional_4_Template, 27, 20, "kendo-splitter", 10)(5, AITestHarnessComponent_Conditional_0_Conditional_5_Template, 13, 6, "div", 11);
1119
+ i0.ɵɵelementStart(3, "div", 10);
1120
+ i0.ɵɵconditionalCreate(4, AITestHarnessComponent_Conditional_0_Conditional_4_Template, 27, 15, "as-split", 11)(5, AITestHarnessComponent_Conditional_0_Conditional_5_Template, 13, 6, "div", 12);
1125
1121
  i0.ɵɵelementEnd()();
1126
1122
  } if (rf & 2) {
1127
1123
  const ctx_r1 = i0.ɵɵnextContext();
@@ -1132,50 +1128,66 @@ function AITestHarnessComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
1132
1128
  } }
1133
1129
  function AITestHarnessComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
1134
1130
  const _r37 = i0.ɵɵgetCurrentView();
1135
- i0.ɵɵelementStart(0, "kendo-dialog", 148);
1136
- i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_1_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
1137
- i0.ɵɵelementStart(1, "div", 149)(2, "p");
1138
- i0.ɵɵtext(3, "Enter a name for this conversation:");
1131
+ i0.ɵɵelementStart(0, "mj-dialog", 148);
1132
+ i0.ɵɵlistener("Close", function AITestHarnessComponent_Conditional_1_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
1133
+ i0.ɵɵelementStart(1, "mj-dialog-titlebar");
1134
+ i0.ɵɵtext(2, "Save Conversation");
1139
1135
  i0.ɵɵelementEnd();
1140
- i0.ɵɵelementStart(4, "input", 150, 3);
1141
- i0.ɵɵlistener("keyup", function AITestHarnessComponent_Conditional_1_Template_input_keyup_4_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.updateTempConversation()); });
1136
+ i0.ɵɵelementStart(3, "div", 149)(4, "p");
1137
+ i0.ɵɵtext(5, "Enter a name for this conversation:");
1138
+ i0.ɵɵelementEnd();
1139
+ i0.ɵɵelementStart(6, "input", 150, 3);
1140
+ i0.ɵɵlistener("keyup", function AITestHarnessComponent_Conditional_1_Template_input_keyup_6_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.updateTempConversation()); });
1142
1141
  i0.ɵɵelementEnd()();
1143
- i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button", 151);
1144
- i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
1145
- i0.ɵɵtext(8, "Cancel");
1142
+ i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 151);
1143
+ i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
1144
+ i0.ɵɵtext(10, "Cancel");
1146
1145
  i0.ɵɵelementEnd();
1147
- i0.ɵɵelementStart(9, "button", 152);
1148
- i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmSaveConversation()); });
1149
- i0.ɵɵtext(10, " Save ");
1146
+ i0.ɵɵelementStart(11, "button", 152);
1147
+ i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r37); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmSaveConversation()); });
1148
+ i0.ɵɵtext(12, " Save ");
1150
1149
  i0.ɵɵelementEnd()()();
1151
1150
  } if (rf & 2) {
1152
1151
  const ctx_r1 = i0.ɵɵnextContext();
1153
- i0.ɵɵproperty("title", "Save Conversation")("width", 400);
1154
- i0.ɵɵadvance(9);
1155
- i0.ɵɵproperty("primary", true)("disabled", ctx_r1.tempConversationName === "");
1152
+ i0.ɵɵproperty("Visible", true)("Width", 400);
1153
+ i0.ɵɵadvance(11);
1154
+ i0.ɵɵproperty("disabled", ctx_r1.tempConversationName === "");
1156
1155
  } }
1157
1156
  function AITestHarnessComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1158
1157
  const _r38 = i0.ɵɵgetCurrentView();
1159
- i0.ɵɵelementStart(0, "kendo-dialog", 153);
1160
- i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_2_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
1161
- i0.ɵɵelementStart(1, "div", 149)(2, "p");
1162
- i0.ɵɵtext(3, "Loading this conversation will replace the current one. Any unsaved changes will be lost.");
1158
+ i0.ɵɵelementStart(0, "mj-dialog", 153);
1159
+ i0.ɵɵlistener("Close", function AITestHarnessComponent_Conditional_2_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
1160
+ i0.ɵɵelementStart(1, "mj-dialog-titlebar");
1161
+ i0.ɵɵtext(2, "Replace Current Conversation?");
1163
1162
  i0.ɵɵelementEnd();
1164
- i0.ɵɵelementStart(4, "p");
1165
- i0.ɵɵtext(5, "Do you want to continue?");
1163
+ i0.ɵɵelementStart(3, "div", 149)(4, "p");
1164
+ i0.ɵɵtext(5, "Loading this conversation will replace the current one. Any unsaved changes will be lost.");
1165
+ i0.ɵɵelementEnd();
1166
+ i0.ɵɵelementStart(6, "p");
1167
+ i0.ɵɵtext(7, "Do you want to continue?");
1166
1168
  i0.ɵɵelementEnd()();
1167
- i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button", 151);
1168
- i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
1169
- i0.ɵɵtext(8, "Cancel");
1169
+ i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 151);
1170
+ i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
1171
+ i0.ɵɵtext(10, "Cancel");
1170
1172
  i0.ɵɵelementEnd();
1171
- i0.ɵɵelementStart(9, "button", 154);
1172
- i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmLoadConversation()); });
1173
- i0.ɵɵtext(10, " Load Conversation ");
1173
+ i0.ɵɵelementStart(11, "button", 154);
1174
+ i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r38); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmLoadConversation()); });
1175
+ i0.ɵɵtext(12, " Load Conversation ");
1174
1176
  i0.ɵɵelementEnd()()();
1175
1177
  } if (rf & 2) {
1176
- i0.ɵɵproperty("title", "Replace Current Conversation?")("width", 400);
1177
- i0.ɵɵadvance(9);
1178
- i0.ɵɵproperty("primary", true);
1178
+ i0.ɵɵproperty("Visible", true)("Width", 400);
1179
+ } }
1180
+ function AITestHarnessComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
1181
+ const _r39 = i0.ɵɵgetCurrentView();
1182
+ i0.ɵɵelementStart(0, "mj-window", 155);
1183
+ i0.ɵɵlistener("Close", function AITestHarnessComponent_Conditional_3_Template_mj_window_Close_0_listener() { i0.ɵɵrestoreView(_r39); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.closeJsonWindow()); });
1184
+ i0.ɵɵelement(1, "mj-json-viewer-window", 156);
1185
+ i0.ɵɵelementEnd();
1186
+ } if (rf & 2) {
1187
+ const ctx_r1 = i0.ɵɵnextContext();
1188
+ i0.ɵɵproperty("Visible", true)("Width", 900)("Height", 700)("MinWidth", 600)("MinHeight", 400)("Draggable", true)("Resizable", true);
1189
+ i0.ɵɵadvance();
1190
+ i0.ɵɵproperty("jsonContent", ctx_r1.currentJsonContent);
1179
1191
  } }
1180
1192
  /**
1181
1193
  * Comprehensive test harness component for AI Agent development and testing.
@@ -1215,14 +1227,10 @@ export class AITestHarnessComponent {
1215
1227
  /**
1216
1228
  * Creates a new AI Test Harness component instance.
1217
1229
  * @param sanitizer - Angular DomSanitizer for safe HTML rendering of formatted content
1218
- * @param windowService - Kendo WindowService for creating modal windows
1219
- * @param viewContainerRef - Angular ViewContainerRef for window positioning
1220
1230
  * @param cdr - Angular ChangeDetectorRef for managing change detection
1221
1231
  */
1222
- constructor(sanitizer, windowService, viewContainerRef, cdr, router) {
1232
+ constructor(sanitizer, cdr, router) {
1223
1233
  this.sanitizer = sanitizer;
1224
- this.windowService = windowService;
1225
- this.viewContainerRef = viewContainerRef;
1226
1234
  this.cdr = cdr;
1227
1235
  this.router = router;
1228
1236
  /** The mode of operation - either 'agent' or 'prompt' */
@@ -1321,8 +1329,8 @@ export class AITestHarnessComponent {
1321
1329
  this.showJsonDialog = false;
1322
1330
  /** Current JSON content to display in the dialog */
1323
1331
  this.currentJsonContent = '';
1324
- /** Reference to the JSON window when open */
1325
- this.jsonWindowRef = null;
1332
+ /** Whether the JSON viewer window is visible */
1333
+ this.showJsonWindow = false;
1326
1334
  // === Execution Monitor Properties ===
1327
1335
  /** Mode for the execution monitor component */
1328
1336
  this.executionMonitorMode = 'historical';
@@ -1474,7 +1482,7 @@ export class AITestHarnessComponent {
1474
1482
  if (this.isVisible && !this._hasFocused && this.messageInput) {
1475
1483
  this._hasFocused = true;
1476
1484
  Promise.resolve().then(() => {
1477
- this.messageInput?.focus();
1485
+ this.messageInput?.nativeElement?.focus();
1478
1486
  });
1479
1487
  }
1480
1488
  }
@@ -3181,62 +3189,27 @@ export class AITestHarnessComponent {
3181
3189
  */
3182
3190
  showRawJsonDialog(message) {
3183
3191
  if (message.rawContent) {
3184
- // Close any existing window
3185
- if (this.jsonWindowRef) {
3186
- this.jsonWindowRef.close();
3187
- }
3188
3192
  try {
3189
- // Try to parse and format the JSON
3190
3193
  const parsed = JSON.parse(message.rawContent);
3191
- // If this is an agent result with execution tree, enhance the display
3192
3194
  if (parsed.agentRunID) {
3193
- // Add agent run ID for reference
3194
- const enhancedParsed = {
3195
- ...parsed,
3196
- _agentRunID: parsed.agentRunID
3197
- };
3195
+ const enhancedParsed = { ...parsed, _agentRunID: parsed.agentRunID };
3198
3196
  this.currentJsonContent = this.formatJson(enhancedParsed);
3199
3197
  }
3200
3198
  else {
3201
- // Apply recursive JSON parsing
3202
3199
  this.currentJsonContent = this.formatJson(parsed);
3203
3200
  }
3204
3201
  }
3205
3202
  catch {
3206
- // If not valid JSON, show as-is
3207
3203
  this.currentJsonContent = message.rawContent;
3208
3204
  }
3209
- // Import the JsonViewerWindowComponent dynamically
3210
- import('./json-viewer-window.component').then(({ JsonViewerWindowComponent }) => {
3211
- // Create the window using WindowService
3212
- // Calculate center position accounting for scroll
3213
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
3214
- const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
3215
- const centerTop = Math.max(50, (window.innerHeight - 700) / 2 + scrollTop);
3216
- const centerLeft = Math.max(50, (window.innerWidth - 900) / 2 + scrollLeft);
3217
- this.jsonWindowRef = this.windowService.open({
3218
- title: 'Raw JSON Response',
3219
- content: JsonViewerWindowComponent,
3220
- width: 900,
3221
- height: 700,
3222
- minWidth: 600,
3223
- minHeight: 400,
3224
- resizable: true,
3225
- draggable: true,
3226
- top: centerTop,
3227
- left: centerLeft
3228
- });
3229
- // Pass the JSON content to the component
3230
- const windowContent = this.jsonWindowRef.content.instance;
3231
- windowContent.jsonContent = this.currentJsonContent;
3232
- // Handle window close
3233
- this.jsonWindowRef.result.subscribe((result) => {
3234
- this.jsonWindowRef = null;
3235
- this.currentJsonContent = '';
3236
- });
3237
- });
3205
+ this.showJsonWindow = true;
3238
3206
  }
3239
3207
  }
3208
+ /** Closes the JSON viewer window */
3209
+ closeJsonWindow() {
3210
+ this.showJsonWindow = false;
3211
+ this.currentJsonContent = '';
3212
+ }
3240
3213
  /**
3241
3214
  * Get the last run ID from conversation messages
3242
3215
  */
@@ -3293,7 +3266,7 @@ export class AITestHarnessComponent {
3293
3266
  focusMessageInput() {
3294
3267
  if (this.messageInput) {
3295
3268
  setTimeout(() => {
3296
- this.messageInput.focus();
3269
+ this.messageInput.nativeElement.focus();
3297
3270
  }, 100);
3298
3271
  }
3299
3272
  }
@@ -3542,11 +3515,7 @@ export class AITestHarnessComponent {
3542
3515
  * Closes the JSON dialog
3543
3516
  */
3544
3517
  closeJsonDialog() {
3545
- if (this.jsonWindowRef) {
3546
- this.jsonWindowRef.close();
3547
- this.jsonWindowRef = null;
3548
- }
3549
- this.showJsonDialog = false;
3518
+ this.showJsonWindow = false;
3550
3519
  this.currentJsonContent = '';
3551
3520
  }
3552
3521
  /**
@@ -3873,7 +3842,7 @@ export class AITestHarnessComponent {
3873
3842
  IsConfigMatchById(config, id) {
3874
3843
  return UUIDsEqual(config.ID, id);
3875
3844
  }
3876
- static { this.ɵfac = function AITestHarnessComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AITestHarnessComponent)(i0.ɵɵdirectiveInject(i1.DomSanitizer), i0.ɵɵdirectiveInject(i2.WindowService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i3.Router)); }; }
3845
+ static { this.ɵfac = function AITestHarnessComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AITestHarnessComponent)(i0.ɵɵdirectiveInject(i1.DomSanitizer), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i2.Router)); }; }
3877
3846
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AITestHarnessComponent, selectors: [["mj-ai-test-harness"]], viewQuery: function AITestHarnessComponent_Query(rf, ctx) { if (rf & 1) {
3878
3847
  i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(_c2, 5)(_c3, 5);
3879
3848
  } if (rf & 2) {
@@ -3882,22 +3851,25 @@ export class AITestHarnessComponent {
3882
3851
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
3883
3852
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageInput = _t.first);
3884
3853
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.saveDialogInput = _t.first);
3885
- } }, inputs: { mode: "mode", entity: "entity", originalPromptRunId: "originalPromptRunId", systemPromptOverride: "systemPromptOverride", aiAgent: "aiAgent", isVisible: "isVisible" }, outputs: { visibilityChange: "visibilityChange", runOpened: "runOpened", minimizeRequested: "minimizeRequested" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 3, vars: 3, consts: [["fileInput", ""], ["messagesContainer", ""], ["messageInput", ""], ["saveDialogInput", ""], ["kendoWindowContainer", "", 1, "harness-container"], [1, "save-dialog", 3, "title", "width"], [1, "confirm-dialog", 3, "title", "width"], [1, "harness-header"], [1, "agent-info"], [1, "harness-body"], ["orientation", "horizontal", 2, "height", "100%", "width", "100%"], [1, "chat-area"], [1, "agent-details"], [1, "entity-logo", 3, "src", "alt"], [3, "class"], [1, "header-actions"], ["title", "Clear conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-broom"], ["title", "Save conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-save"], ["title", "Export conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-download"], ["title", "Import conversation", 1, "custom-button", 3, "click"], [1, "fa-solid", "fa-upload"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["title", "Toggle sidebar", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid"], [3, "collapsible", "resizable", "min"], [1, "messages-container"], [1, "empty-state"], [3, "ngClass"], [1, "input-area"], [1, "rerun-mode-container"], [1, "input-container"], [3, "collapsible", "resizable", "size", "min"], [1, "sidebar"], [1, "sidebar-tabs"], [1, "tab-button", 3, "click", "disabled"], [1, "fa-solid", "fa-history"], [1, "badge"], [1, "sidebar-content"], [1, "tab-content"], [1, "tab-content", 2, "padding", "0", "height", "100%"], [1, "tab-content", 2, "overflow-y", "auto"], [1, "fa-solid", "fa-comments"], [1, "message-header"], [1, "message-role"], [1, "message-time"], [1, "execution-time", "streaming"], [1, "execution-time", 3, "title"], ["title", "View raw JSON response", 1, "raw-toggle"], [1, "message-content"], ["title", "Copy message", 1, "copy-button-in-bubble", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "streaming-wrapper"], [3, "innerHTML"], [1, "error-details"], [1, "payload-section", 3, "collapsed"], [1, "fa-solid", "fa-user"], [1, "message-role-logo", 3, "src", "alt"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["title", "View raw JSON response", 1, "raw-toggle", 3, "click"], [1, "fa-solid", "fa-code"], [1, "streaming-content", 3, "innerHTML"], [1, "cursor"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "payload-section"], [1, "payload-header", 3, "click"], [1, "payload-label"], ["type", "button", 1, "payload-toggle"], [1, "payload-content"], [2, "height", "300px", "width", "100%", 3, "ngModel", "language", "readonly"], [1, "rerun-message"], [1, "fa-solid", "fa-rotate-right"], [1, "rerun-buttons"], ["title", "Re-run with loaded messages", 1, "send-button", "rerun-button", 3, "disabled"], ["title", "Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.", 1, "send-button", "reset-button", 3, "disabled"], ["title", "Re-run with loaded messages", 1, "send-button", "rerun-button", 3, "click", "disabled"], [1, "fa-solid", "fa-play"], ["title", "Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.", 1, "send-button", "reset-button", 3, "click", "disabled"], [1, "fa-solid", "fa-rotate-left"], ["placeholder", "Type your message here... (Press Enter to send, Shift+Enter for new line)", 1, "message-input", 3, "ngModelChange", "keypress", "ngModel", "rows", "disabled"], ["title", "Send message", 1, "send-button", 3, "click", "disabled"], [1, "fa-solid", "fa-paper-plane"], [1, "tab-button", 3, "click"], [1, "fa-solid", "fa-diagram-project"], [1, "fa-solid", "fa-sliders"], [1, "tab-header"], [1, "variables-list"], [1, "empty-variables"], [1, "variable-item"], [1, "add-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], ["placeholder", "Variable name", 1, "variable-name", 3, "ngModelChange", "ngModel", "disabled"], ["textField", "text", "valueField", "value", 1, "variable-type", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "disabled"], [1, "variable-value", 3, "ngModelChange", "ngModel", "placeholder", "disabled"], ["title", "Remove variable", 1, "remove-button", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [3, "viewRunClick", "mode", "agentRun", "liveSteps", "autoExpand", "runId", "runType"], [1, "model-settings"], [1, "setting-group"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a configuration...", 1, "configuration-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [1, "setting-help"], [1, "add-button", 3, "click"], ["title", "Remove variable", 1, "remove-button", 3, "click"], ["title", "Reset to Prompt Settings", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid", "fa-undo"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 1, "model-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a vendor...", 1, "vendor-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "disabled"], ["textField", "text", "valueField", "value", "placeholder", "Select format...", 1, "format-selector", 3, "ngModelChange", "ngModel", "data"], ["placeholder", "Max tokens...", 1, "max-tokens-input", 3, "ngModelChange", "ngModel", "min", "max", "step"], [1, "checkbox-label"], ["type", "checkbox", 1, "skip-validation-checkbox", 3, "ngModelChange", "ngModel"], ["title", "Advanced Parameters", 1, "advanced-params-panel", 3, "action", "expanded"], [1, "advanced-settings"], ["title", "Controls randomness: 0 = more focused and deterministic, 2 = more random and creative"], ["placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "min", "max", "step", "format"], ["title", "Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens"], ["title", "Only sample from the top K tokens. Lower values reduce randomness"], ["title", "Minimum probability for token selection. Filters out low-probability tokens"], ["title", "Penalizes tokens based on their frequency in the text. Positive values reduce repetition"], ["title", "Penalizes tokens that have appeared in the text. Positive values increase topic diversity"], ["title", "Random seed for deterministic generation. Same seed produces same output"], ["placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "format"], ["title", "Sequences that will stop generation when encountered. Enter comma-separated values"], ["placeholder", "Enter comma-separated sequences", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "rows"], ["title", "Include log probabilities of the output tokens in the response"], [1, "advanced-param-switch", 3, "ngModelChange", "ngModel"], ["title", "Number of top log probabilities to include for each token"], ["placeholder", "2", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "min", "max", "step", "format"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary"], [1, "saved-list"], [1, "empty-saved"], [1, "saved-item", 3, "current"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary", 3, "click"], [1, "fa-solid", "fa-folder-open"], [1, "saved-item", 3, "click"], [1, "saved-info"], [1, "saved-date"], ["title", "Delete conversation", 1, "delete-button", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "View execution details", 1, "execution-history-toggle"], ["title", "View full run details", 1, "execution-history-toggle"], [1, "fa-solid", "fa-robot"], ["title", "View execution details", 1, "execution-history-toggle", 3, "click"], ["title", "View full run details", 1, "execution-history-toggle", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "streaming-content"], [1, "save-dialog", 3, "close", "title", "width"], [1, "dialog-content"], ["type", "text", "placeholder", "Conversation name", 1, "k-textbox", "k-input", "k-input-md", "k-rounded-md", "k-input-solid", "full-width", 3, "keyup"], ["kendoButton", "", 3, "click"], ["kendoButton", "", 3, "click", "primary", "disabled"], [1, "confirm-dialog", 3, "close", "title", "width"], ["kendoButton", "", 3, "click", "primary"]], template: function AITestHarnessComponent_Template(rf, ctx) { if (rf & 1) {
3854
+ } }, inputs: { mode: "mode", entity: "entity", originalPromptRunId: "originalPromptRunId", systemPromptOverride: "systemPromptOverride", aiAgent: "aiAgent", isVisible: "isVisible" }, outputs: { visibilityChange: "visibilityChange", runOpened: "runOpened", minimizeRequested: "minimizeRequested" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 4, vars: 4, consts: [["fileInput", ""], ["messagesContainer", ""], ["messageInput", ""], ["saveDialogInput", ""], [1, "harness-container"], [1, "save-dialog", 3, "Visible", "Width"], [1, "confirm-dialog", 3, "Visible", "Width"], ["Title", "Raw JSON Response", 3, "Visible", "Width", "Height", "MinWidth", "MinHeight", "Draggable", "Resizable"], [1, "harness-header"], [1, "agent-info"], [1, "harness-body"], ["direction", "horizontal", 2, "height", "100%", "width", "100%"], [1, "chat-area"], [1, "agent-details"], [1, "entity-logo", 3, "src", "alt"], [3, "class"], [1, "header-actions"], ["title", "Clear conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-broom"], ["title", "Save conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-save"], ["title", "Export conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-download"], ["title", "Import conversation", 1, "custom-button", 3, "click"], [1, "fa-solid", "fa-upload"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["title", "Toggle sidebar", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid"], [3, "size"], [1, "messages-container"], [1, "empty-state"], [3, "ngClass"], [1, "input-area"], [1, "rerun-mode-container"], [1, "input-container"], [1, "sidebar"], [1, "sidebar-tabs"], [1, "tab-button", 3, "click", "disabled"], [1, "fa-solid", "fa-history"], [1, "badge"], [1, "sidebar-content"], [1, "tab-content"], [1, "tab-content", 2, "padding", "0", "height", "100%"], [1, "tab-content", 2, "overflow-y", "auto"], [1, "fa-solid", "fa-comments"], [1, "message-header"], [1, "message-role"], [1, "message-time"], [1, "execution-time", "streaming"], [1, "execution-time", 3, "title"], ["title", "View raw JSON response", 1, "raw-toggle"], [1, "message-content"], ["title", "Copy message", 1, "copy-button-in-bubble", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "streaming-wrapper"], [3, "innerHTML"], [1, "error-details"], [1, "payload-section", 3, "collapsed"], [1, "fa-solid", "fa-user"], [1, "message-role-logo", 3, "src", "alt"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["title", "View raw JSON response", 1, "raw-toggle", 3, "click"], [1, "fa-solid", "fa-code"], [1, "streaming-content", 3, "innerHTML"], [1, "cursor"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "payload-section"], [1, "payload-header", 3, "click"], [1, "payload-label"], ["type", "button", 1, "payload-toggle"], [1, "payload-content"], [2, "height", "300px", "width", "100%", 3, "ngModel", "language", "readonly"], [1, "rerun-message"], [1, "fa-solid", "fa-rotate-right"], [1, "rerun-buttons"], ["title", "Re-run with loaded messages", 1, "send-button", "rerun-button", 3, "disabled"], ["title", "Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.", 1, "send-button", "reset-button", 3, "disabled"], ["title", "Re-run with loaded messages", 1, "send-button", "rerun-button", 3, "click", "disabled"], [1, "fa-solid", "fa-play"], ["title", "Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.", 1, "send-button", "reset-button", 3, "click", "disabled"], [1, "fa-solid", "fa-rotate-left"], ["placeholder", "Type your message here... (Press Enter to send, Shift+Enter for new line)", 1, "mj-textarea", "message-input", 3, "ngModelChange", "keypress", "ngModel", "rows", "disabled"], ["title", "Send message", 1, "send-button", 3, "click", "disabled"], [1, "fa-solid", "fa-paper-plane"], [1, "tab-button", 3, "click"], [1, "fa-solid", "fa-diagram-project"], [1, "fa-solid", "fa-sliders"], [1, "tab-header"], [1, "variables-list"], [1, "empty-variables"], [1, "variable-item"], [1, "add-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], ["type", "text", "placeholder", "Variable name", 1, "mj-input", "variable-name", 3, "ngModelChange", "ngModel", "disabled"], ["TextField", "text", "ValueField", "value", 1, "variable-type", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive", "Disabled"], ["type", "text", 1, "mj-input", "variable-value", 3, "ngModelChange", "ngModel", "placeholder", "disabled"], ["title", "Remove variable", 1, "remove-button", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [3, "viewRunClick", "mode", "agentRun", "liveSteps", "autoExpand", "runId", "runType"], [1, "model-settings"], [1, "setting-group"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select a configuration...", 1, "configuration-selector", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], [1, "setting-help"], [1, "add-button", 3, "click"], ["title", "Remove variable", 1, "remove-button", 3, "click"], ["title", "Reset to Prompt Settings", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid", "fa-undo"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select a model...", 1, "model-selector", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select a vendor...", 1, "vendor-selector", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive", "Disabled"], ["TextField", "text", "ValueField", "value", "Placeholder", "Select format...", 1, "format-selector", 3, "ngModelChange", "ngModel", "Data"], ["Placeholder", "Max tokens...", 1, "max-tokens-input", 3, "ngModelChange", "ngModel", "Min", "Max", "Step"], [1, "checkbox-label"], ["type", "checkbox", 1, "skip-validation-checkbox", 3, "ngModelChange", "ngModel"], [1, "advanced-params-panel", 3, "Title", "Expanded"], [1, "advanced-settings"], ["title", "Controls randomness: 0 = more focused and deterministic, 2 = more random and creative"], ["Placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "Min", "Max", "Step", "Format"], ["title", "Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens"], ["title", "Only sample from the top K tokens. Lower values reduce randomness"], ["title", "Minimum probability for token selection. Filters out low-probability tokens"], ["title", "Penalizes tokens based on their frequency in the text. Positive values reduce repetition"], ["title", "Penalizes tokens that have appeared in the text. Positive values increase topic diversity"], ["title", "Random seed for deterministic generation. Same seed produces same output"], ["Placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "Format"], ["title", "Sequences that will stop generation when encountered. Enter comma-separated values"], ["placeholder", "Enter comma-separated sequences", 1, "mj-textarea", "advanced-param-input", 3, "ngModelChange", "ngModel", "rows"], ["title", "Include log probabilities of the output tokens in the response"], [1, "advanced-param-switch", 3, "ngModelChange", "ngModel"], ["title", "Number of top log probabilities to include for each token"], ["Placeholder", "2", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "Min", "Max", "Step", "Format"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary"], [1, "saved-list"], [1, "empty-saved"], [1, "saved-item", 3, "current"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary", 3, "click"], [1, "fa-solid", "fa-folder-open"], [1, "saved-item", 3, "click"], [1, "saved-info"], [1, "saved-date"], ["title", "Delete conversation", 1, "delete-button", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "View execution details", 1, "execution-history-toggle"], ["title", "View full run details", 1, "execution-history-toggle"], [1, "fa-solid", "fa-robot"], ["title", "View execution details", 1, "execution-history-toggle", 3, "click"], ["title", "View full run details", 1, "execution-history-toggle", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "streaming-content"], [1, "save-dialog", 3, "Close", "Visible", "Width"], [1, "dialog-content"], ["type", "text", "placeholder", "Conversation name", 1, "mj-input", "full-width", 3, "keyup"], ["mjButton", "", 3, "click"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], [1, "confirm-dialog", 3, "Close", "Visible", "Width"], ["mjButton", "", "variant", "primary", 3, "click"], ["Title", "Raw JSON Response", 3, "Close", "Visible", "Width", "Height", "MinWidth", "MinHeight", "Draggable", "Resizable"], [3, "jsonContent"]], template: function AITestHarnessComponent_Template(rf, ctx) { if (rf & 1) {
3886
3855
  i0.ɵɵconditionalCreate(0, AITestHarnessComponent_Conditional_0_Template, 6, 2, "div", 4);
3887
- i0.ɵɵconditionalCreate(1, AITestHarnessComponent_Conditional_1_Template, 11, 4, "kendo-dialog", 5);
3888
- i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_2_Template, 11, 3, "kendo-dialog", 6);
3856
+ i0.ɵɵconditionalCreate(1, AITestHarnessComponent_Conditional_1_Template, 13, 3, "mj-dialog", 5);
3857
+ i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_2_Template, 13, 2, "mj-dialog", 6);
3858
+ i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_3_Template, 2, 8, "mj-window", 7);
3889
3859
  } if (rf & 2) {
3890
3860
  i0.ɵɵconditional(ctx.isVisible ? 0 : -1);
3891
3861
  i0.ɵɵadvance();
3892
3862
  i0.ɵɵconditional(ctx.showSaveDialog ? 1 : -1);
3893
3863
  i0.ɵɵadvance();
3894
3864
  i0.ɵɵconditional(ctx.showLoadConfirmDialog ? 2 : -1);
3895
- } }, dependencies: [i4.NgClass, i5.CheckboxControlValueAccessor, i5.NgControlStatus, i5.NgModel, i6.ButtonComponent, i2.DialogComponent, i2.DialogActionsComponent, i2.WindowContainerDirective, i7.DropDownListComponent, i8.TextBoxComponent, i8.NumericTextBoxComponent, i8.TextAreaComponent, i8.SwitchComponent, i9.ExpansionPanelComponent, i9.SplitterComponent, i9.SplitterPaneComponent, i10.CodeEditorComponent, i11.AgentExecutionMonitorComponent, i4.DatePipe], styles: ["\n\n.harness-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-card);\n}\n\n\n\n.custom-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.custom-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.custom-button[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.custom-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.custom-button.icon-only[_ngcontent-%COMP%] {\n padding: 6px 8px;\n}\n\n.custom-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.send-button[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 44px;\n font-family: inherit;\n}\n\n.send-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.send-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n\n\n.add-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.add-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n\n\n.remove-button[_ngcontent-%COMP%], \n.delete-button[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n color: var(--mj-status-error);\n padding: 4px 8px;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s;\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.remove-button[_ngcontent-%COMP%]:hover, \n.delete-button[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-color-error-600);\n}\n\n\n\n.copy-button-in-bubble[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n background: transparent;\n border: none;\n padding: 6px;\n font-size: 14px;\n color: var(--mj-border-strong);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0;\n z-index: 10; \n\n}\n\n.message-content[_ngcontent-%COMP%]:hover .copy-button-in-bubble[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.copy-button-in-bubble[_ngcontent-%COMP%]:hover {\n background: rgba(0, 0, 0, 0.08);\n color: var(--mj-text-muted);\n}\n\n.copy-button-in-bubble[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.model-settings[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.setting-group[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.setting-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n}\n\n.model-selector[_ngcontent-%COMP%], \n.vendor-selector[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.temperature-slider[_ngcontent-%COMP%] {\n width: 100%;\n margin-top: 8px;\n}\n\n.max-tokens-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.setting-help[_ngcontent-%COMP%] {\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n cursor: pointer;\n}\n\n.skip-validation-checkbox[_ngcontent-%COMP%] {\n margin-right: 8px;\n cursor: pointer;\n width: 16px;\n height: 16px;\n}\n\n\n\n.harness-header[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.agent-info[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.agent-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.agent-details[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.agent-details[_ngcontent-%COMP%] .entity-logo[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n}\n\n.agent-details[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n\n\n.harness-body[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n\n\n.chat-area[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n height: 100%;\n min-height: 0; \n\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-in;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-user[_ngcontent-%COMP%] {\n margin-left: auto;\n max-width: 70%;\n}\n\n.message-assistant[_ngcontent-%COMP%] {\n margin-right: auto;\n max-width: 70%;\n}\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 13px;\n}\n\n.message-role[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.message-role[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.message-role[_ngcontent-%COMP%] .message-role-logo[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n object-fit: cover;\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.message-user[_ngcontent-%COMP%] .message-role[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.message-assistant[_ngcontent-%COMP%] .message-role[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.message-time[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.execution-time[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.raw-toggle[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n}\n\n.raw-toggle[_ngcontent-%COMP%]:hover {\n background: rgba(0, 0, 0, 0.05);\n color: var(--mj-text-secondary);\n}\n\n.raw-toggle[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n\n.message-user[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.message-assistant[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.message.streaming[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.streaming-content[_ngcontent-%COMP%] {\n display: inline;\n}\n\n.streaming-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.streaming-wrapper[_ngcontent-%COMP%] .cursor[_ngcontent-%COMP%] {\n display: inline;\n margin-left: 2px;\n}\n\n.cursor[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_blink 1s infinite;\n font-weight: 100;\n color: var(--mj-text-secondary);\n}\n\n@keyframes _ngcontent-%COMP%_blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n.error-details[_ngcontent-%COMP%] {\n margin-top: 8px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n border-radius: 6px;\n color: var(--mj-color-error-600);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.payload-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.payload-header[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.payload-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.payload-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.payload-content[_ngcontent-%COMP%] {\n max-height: 250px;\n overflow: auto;\n background: var(--mj-bg-surface-card);\n}\n\n.payload-content[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n background: transparent;\n}\n\n.payload-toggle[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.payload-toggle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.payload-toggle[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.payload-section.collapsed[_ngcontent-%COMP%] .payload-header[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n\n\n.save-dialog[_ngcontent-%COMP%], \n.confirm-dialog[_ngcontent-%COMP%] {\n .dialog-content {\n padding: 20px;\n\n p {\n margin: 0 0 16px 0;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.5;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .full-width {\n width: 100%;\n }\n\n input.k-textbox {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n\n &:focus {\n outline: none;\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--mj-status-error) 25%, transparent);\n }\n }\n }\n}\n\n\n\n.markdown-content[_ngcontent-%COMP%] {\n line-height: 1.6;\n word-wrap: break-word;\n overflow-wrap: break-word;\n max-width: 100%;\n}\n\n\n\n.inline-json-editor[_ngcontent-%COMP%] {\n margin: 8px 0;\n\n .json-editor-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 4px;\n overflow: hidden;\n position: relative;\n max-height: 400px;\n\n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 13px;\n line-height: 1.5;\n overflow: auto;\n height: 100%;\n background: transparent;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n }\n}\n\n.markdown-paragraph[_ngcontent-%COMP%] {\n margin: 8px 0;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.markdown-h1[_ngcontent-%COMP%] {\n font-size: 1.5em;\n font-weight: 600;\n margin: 16px 0 8px 0;\n color: var(--mj-text-primary);\n border-bottom: 2px solid var(--mj-bg-surface-sunken);\n padding-bottom: 4px;\n}\n\n.markdown-h2[_ngcontent-%COMP%] {\n font-size: 1.3em;\n font-weight: 600;\n margin: 14px 0 6px 0;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n padding-bottom: 2px;\n}\n\n.markdown-h3[_ngcontent-%COMP%] {\n font-size: 1.1em;\n font-weight: 600;\n margin: 12px 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.code-block[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 16px;\n margin: 12px 0;\n overflow-x: auto;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre;\n word-wrap: normal;\n max-width: 100%;\n}\n\n.code-block[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre;\n word-wrap: normal;\n}\n\n.language-json[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.inline-code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 0.9em;\n color: var(--mj-status-error);\n white-space: nowrap;\n}\n\n.markdown-list[_ngcontent-%COMP%] {\n margin: 8px 0;\n padding-left: 24px;\n}\n\n.markdown-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin: 4px 0;\n line-height: 1.5;\n}\n\n.markdown-link[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: none;\n}\n\n\n\n.message-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n padding: 12px 40px 12px 16px; \n\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n position: relative;\n overflow-wrap: break-word;\n hyphens: auto;\n max-width: 100%;\n overflow-x: hidden;\n}\n\n\n\n.json-content-wrapper[_ngcontent-%COMP%] {\n margin: 8px 0;\n}\n\n.json-main-content[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.json-raw-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n}\n\n.json-toggle-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.json-toggle-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.json-toggle-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.json-raw-section[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%] {\n margin: 8px 0 0 0;\n font-size: 12px;\n max-height: 300px;\n overflow-y: auto;\n}\n\n\n\n@media (max-width: 768px) {\n .json-raw-section[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%] {\n font-size: 11px;\n max-height: 200px;\n }\n}\n\n\n\n.json-raw-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n}\n\n\n\n.input-area[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0; \n\n margin-top: auto; \n\n}\n\n.input-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n align-items: center;\n}\n\n.rerun-mode-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 8px;\n gap: 16px;\n}\n\n.rerun-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.rerun-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.rerun-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-family: 'Fira Code', 'Consolas', monospace;\n}\n\n.rerun-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 100px;\n justify-content: center;\n}\n\n.rerun-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.rerun-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.reset-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 120px;\n justify-content: center;\n background-color: var(--mj-text-muted);\n}\n\n.reset-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-text-secondary);\n}\n\n.reset-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.message-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.message-input[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%] {\n resize: none;\n font-size: 14px;\n}\n\n.send-button[_ngcontent-%COMP%] {\n margin-bottom: 1px;\n}\n\n\n\n.sidebar[_ngcontent-%COMP%] {\n width: 100%; \n\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n\n\n.harness-body[_ngcontent-%COMP%] kendo-splitter[_ngcontent-%COMP%] {\n height: 100%;\n}\n\n.harness-body[_ngcontent-%COMP%] kendo-splitter-pane[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.sidebar-tabs[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.tab-button[_ngcontent-%COMP%] {\n flex: 1;\n padding: 12px 8px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.tab-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.tab-button.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.tab-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-button[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n margin-left: 4px;\n}\n\n.tab-button.active[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.tab-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n\n\n.sidebar-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n width: 100%; \n\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 20px;\n width: 100%; \n\n box-sizing: border-box; \n\n}\n\n.tab-header[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.icon-only[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.tab-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.tab-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.small[_ngcontent-%COMP%] {\n align-self: flex-start;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.small[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n}\n\n\n\n.variables-list[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n width: 100%;\n}\n\n.variable-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n align-items: center;\n width: 100%;\n}\n\n.variable-name[_ngcontent-%COMP%] {\n width: 30%; \n\n min-width: 100px;\n}\n\n.variable-type[_ngcontent-%COMP%] {\n width: 25%; \n\n min-width: 80px;\n}\n\n.variable-value[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0; \n\n}\n\n.remove-button[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.add-variable-button[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.empty-variables[_ngcontent-%COMP%] {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n\n\n.saved-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-saved[_ngcontent-%COMP%] {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-saved[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.saved-item[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.saved-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n}\n\n.saved-item.current[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.saved-info[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.saved-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.saved-date[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n\n\n@media (max-width: 1200px) {\n .sidebar[_ngcontent-%COMP%] {\n width: 320px;\n }\n}\n\n@media (max-width: 992px) {\n .message-user[_ngcontent-%COMP%], \n .message-assistant[_ngcontent-%COMP%] {\n max-width: 85%;\n }\n\n .sidebar[_ngcontent-%COMP%] {\n width: 280px;\n }\n}\n\n\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n .ai-agent-test-harness .k-dialog-wrapper {\n border-radius: 8px;\n overflow: hidden;\n}\n\n .ai-agent-test-harness .k-dialog-titlebar {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-inverse);\n}\n\n .ai-agent-test-harness .k-dialog-title {\n font-weight: 600;\n}\n\n .ai-agent-test-harness .k-dialog-titlebar-actions .k-button {\n color: var(--mj-text-inverse);\n}\n\n .ai-agent-test-harness .k-dialog-content {\n padding: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n\n\n\n\n.advanced-params-panel[_ngcontent-%COMP%] {\n margin-top: 24px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n}\n\n.advanced-params-panel[_ngcontent-%COMP%] .k-expander-title {\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.advanced-settings[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.advanced-param-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.advanced-param-switch[_ngcontent-%COMP%] {\n margin-top: 8px;\n}\n\n\n\n.format-selector[_ngcontent-%COMP%] {\n width: 100%;\n}"] }); }
3865
+ i0.ɵɵadvance();
3866
+ i0.ɵɵconditional(ctx.showJsonWindow ? 3 : -1);
3867
+ } }, dependencies: [i3.NgClass, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i5.MJWindowComponent, i5.MJButtonDirective, i5.MJDropdownComponent, i5.MJNumericInputComponent, i5.MJSwitchComponent, i5.MJAccordionPanelComponent, i5.MJDialogComponent, i5.MJDialogTitlebarComponent, i5.MJDialogActionsComponent, i6.SplitComponent, i6.SplitAreaComponent, i7.CodeEditorComponent, i8.JsonViewerWindowComponent, i9.AgentExecutionMonitorComponent, i3.DatePipe], styles: ["\n\n.harness-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-card);\n}\n\n\n\n.custom-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.custom-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.custom-button[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.custom-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.custom-button.icon-only[_ngcontent-%COMP%] {\n padding: 6px 8px;\n}\n\n.custom-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.send-button[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 44px;\n font-family: inherit;\n}\n\n.send-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.send-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n\n\n.add-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.add-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n\n\n.remove-button[_ngcontent-%COMP%], \n.delete-button[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n color: var(--mj-status-error);\n padding: 4px 8px;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s;\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.remove-button[_ngcontent-%COMP%]:hover, \n.delete-button[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-color-error-600);\n}\n\n\n\n.copy-button-in-bubble[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n background: transparent;\n border: none;\n padding: 6px;\n font-size: 14px;\n color: var(--mj-border-strong);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0;\n z-index: 10; \n\n}\n\n.message-content[_ngcontent-%COMP%]:hover .copy-button-in-bubble[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.copy-button-in-bubble[_ngcontent-%COMP%]:hover {\n background: rgba(0, 0, 0, 0.08);\n color: var(--mj-text-muted);\n}\n\n.copy-button-in-bubble[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.model-settings[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.setting-group[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.setting-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n}\n\n.model-selector[_ngcontent-%COMP%], \n.vendor-selector[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.temperature-slider[_ngcontent-%COMP%] {\n width: 100%;\n margin-top: 8px;\n}\n\n.max-tokens-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.setting-help[_ngcontent-%COMP%] {\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n cursor: pointer;\n}\n\n.skip-validation-checkbox[_ngcontent-%COMP%] {\n margin-right: 8px;\n cursor: pointer;\n width: 16px;\n height: 16px;\n}\n\n\n\n.harness-header[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.agent-info[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.agent-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.agent-details[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.agent-details[_ngcontent-%COMP%] .entity-logo[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n}\n\n.agent-details[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n\n\n.harness-body[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n\n\n.chat-area[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n height: 100%;\n min-height: 0; \n\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-in;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-user[_ngcontent-%COMP%] {\n margin-left: auto;\n max-width: 70%;\n}\n\n.message-assistant[_ngcontent-%COMP%] {\n margin-right: auto;\n max-width: 70%;\n}\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 13px;\n}\n\n.message-role[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.message-role[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.message-role[_ngcontent-%COMP%] .message-role-logo[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n object-fit: cover;\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.message-user[_ngcontent-%COMP%] .message-role[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.message-assistant[_ngcontent-%COMP%] .message-role[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.message-time[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.execution-time[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.raw-toggle[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n}\n\n.raw-toggle[_ngcontent-%COMP%]:hover {\n background: rgba(0, 0, 0, 0.05);\n color: var(--mj-text-secondary);\n}\n\n.raw-toggle[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n\n.message-user[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.message-assistant[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.message.streaming[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.streaming-content[_ngcontent-%COMP%] {\n display: inline;\n}\n\n.streaming-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.streaming-wrapper[_ngcontent-%COMP%] .cursor[_ngcontent-%COMP%] {\n display: inline;\n margin-left: 2px;\n}\n\n.cursor[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_blink 1s infinite;\n font-weight: 100;\n color: var(--mj-text-secondary);\n}\n\n@keyframes _ngcontent-%COMP%_blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n.error-details[_ngcontent-%COMP%] {\n margin-top: 8px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n border-radius: 6px;\n color: var(--mj-color-error-600);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.payload-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.payload-header[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.payload-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.payload-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.payload-content[_ngcontent-%COMP%] {\n max-height: 250px;\n overflow: auto;\n background: var(--mj-bg-surface-card);\n}\n\n.payload-content[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n background: transparent;\n}\n\n.payload-toggle[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.payload-toggle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.payload-toggle[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.payload-section.collapsed[_ngcontent-%COMP%] .payload-header[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n\n\n.save-dialog[_ngcontent-%COMP%], \n.confirm-dialog[_ngcontent-%COMP%] {\n .dialog-content {\n padding: 20px;\n\n p {\n margin: 0 0 16px 0;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.5;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .full-width {\n width: 100%;\n }\n\n input.k-textbox {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n\n &:focus {\n outline: none;\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--mj-status-error) 25%, transparent);\n }\n }\n }\n}\n\n\n\n.markdown-content[_ngcontent-%COMP%] {\n line-height: 1.6;\n word-wrap: break-word;\n overflow-wrap: break-word;\n max-width: 100%;\n}\n\n\n\n.inline-json-editor[_ngcontent-%COMP%] {\n margin: 8px 0;\n\n .json-editor-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 4px;\n overflow: hidden;\n position: relative;\n max-height: 400px;\n\n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 13px;\n line-height: 1.5;\n overflow: auto;\n height: 100%;\n background: transparent;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n }\n}\n\n.markdown-paragraph[_ngcontent-%COMP%] {\n margin: 8px 0;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.markdown-h1[_ngcontent-%COMP%] {\n font-size: 1.5em;\n font-weight: 600;\n margin: 16px 0 8px 0;\n color: var(--mj-text-primary);\n border-bottom: 2px solid var(--mj-bg-surface-sunken);\n padding-bottom: 4px;\n}\n\n.markdown-h2[_ngcontent-%COMP%] {\n font-size: 1.3em;\n font-weight: 600;\n margin: 14px 0 6px 0;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n padding-bottom: 2px;\n}\n\n.markdown-h3[_ngcontent-%COMP%] {\n font-size: 1.1em;\n font-weight: 600;\n margin: 12px 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.code-block[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 16px;\n margin: 12px 0;\n overflow-x: auto;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre;\n word-wrap: normal;\n max-width: 100%;\n}\n\n.code-block[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre;\n word-wrap: normal;\n}\n\n.language-json[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.inline-code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 0.9em;\n color: var(--mj-status-error);\n white-space: nowrap;\n}\n\n.markdown-list[_ngcontent-%COMP%] {\n margin: 8px 0;\n padding-left: 24px;\n}\n\n.markdown-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin: 4px 0;\n line-height: 1.5;\n}\n\n.markdown-link[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: none;\n}\n\n\n\n.message-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n padding: 12px 40px 12px 16px; \n\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n position: relative;\n overflow-wrap: break-word;\n hyphens: auto;\n max-width: 100%;\n overflow-x: hidden;\n}\n\n\n\n.json-content-wrapper[_ngcontent-%COMP%] {\n margin: 8px 0;\n}\n\n.json-main-content[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.json-raw-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n}\n\n.json-toggle-button[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.json-toggle-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.json-toggle-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.json-raw-section[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%] {\n margin: 8px 0 0 0;\n font-size: 12px;\n max-height: 300px;\n overflow-y: auto;\n}\n\n\n\n@media (max-width: 768px) {\n .json-raw-section[_ngcontent-%COMP%] .code-block[_ngcontent-%COMP%] {\n font-size: 11px;\n max-height: 200px;\n }\n}\n\n\n\n.json-raw-section[_ngcontent-%COMP%] {\n margin-top: 12px;\n}\n\n\n\n.input-area[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0; \n\n margin-top: auto; \n\n}\n\n.input-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n align-items: center;\n}\n\n.rerun-mode-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 8px;\n gap: 16px;\n}\n\n.rerun-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.rerun-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.rerun-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-family: 'Fira Code', 'Consolas', monospace;\n}\n\n.rerun-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 100px;\n justify-content: center;\n}\n\n.rerun-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.rerun-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.reset-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 120px;\n justify-content: center;\n background-color: var(--mj-text-muted);\n}\n\n.reset-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-text-secondary);\n}\n\n.reset-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.message-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.message-input[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%] {\n resize: none;\n font-size: 14px;\n}\n\n.send-button[_ngcontent-%COMP%] {\n margin-bottom: 1px;\n}\n\n\n\n.sidebar[_ngcontent-%COMP%] {\n width: 100%; \n\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n\n\n.sidebar-tabs[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.tab-button[_ngcontent-%COMP%] {\n flex: 1;\n padding: 12px 8px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.tab-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.tab-button.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.tab-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.tab-button[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n margin-left: 4px;\n}\n\n.tab-button.active[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.tab-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n\n\n.sidebar-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n width: 100%; \n\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 20px;\n width: 100%; \n\n box-sizing: border-box; \n\n}\n\n.tab-header[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.icon-only[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.tab-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.tab-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.small[_ngcontent-%COMP%] {\n align-self: flex-start;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n.tab-header[_ngcontent-%COMP%] .custom-button.small[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n}\n\n\n\n.variables-list[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n width: 100%;\n}\n\n.variable-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n align-items: center;\n width: 100%;\n}\n\n.variable-name[_ngcontent-%COMP%] {\n width: 30%; \n\n min-width: 100px;\n}\n\n.variable-type[_ngcontent-%COMP%] {\n width: 25%; \n\n min-width: 80px;\n}\n\n.variable-value[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0; \n\n}\n\n.remove-button[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.add-variable-button[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.empty-variables[_ngcontent-%COMP%] {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n\n\n.saved-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-saved[_ngcontent-%COMP%] {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-saved[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.saved-item[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.saved-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n}\n\n.saved-item.current[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.saved-info[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.saved-info[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.saved-date[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n\n\n@media (max-width: 1200px) {\n .sidebar[_ngcontent-%COMP%] {\n width: 320px;\n }\n}\n\n@media (max-width: 992px) {\n .message-user[_ngcontent-%COMP%], \n .message-assistant[_ngcontent-%COMP%] {\n max-width: 85%;\n }\n\n .sidebar[_ngcontent-%COMP%] {\n width: 280px;\n }\n}\n\n\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.messages-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.sidebar-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n .ai-agent-test-harness .k-dialog-wrapper {\n border-radius: 8px;\n overflow: hidden;\n}\n\n .ai-agent-test-harness .k-dialog-titlebar {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-inverse);\n}\n\n .ai-agent-test-harness .k-dialog-title {\n font-weight: 600;\n}\n\n .ai-agent-test-harness .k-dialog-titlebar-actions .k-button {\n color: var(--mj-text-inverse);\n}\n\n .ai-agent-test-harness .k-dialog-content {\n padding: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n\n\n\n\n.advanced-params-panel[_ngcontent-%COMP%] {\n margin-top: 24px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n}\n\n.advanced-params-panel[_ngcontent-%COMP%] .k-expander-title {\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.advanced-settings[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.advanced-param-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.advanced-param-switch[_ngcontent-%COMP%] {\n margin-top: 8px;\n}\n\n\n\n.format-selector[_ngcontent-%COMP%] {\n width: 100%;\n}"] }); }
3896
3868
  }
3897
3869
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AITestHarnessComponent, [{
3898
3870
  type: Component,
3899
- args: [{ standalone: false, selector: 'mj-ai-test-harness', template: "@if (isVisible) {\n <div class=\"harness-container\" kendoWindowContainer>\n <!-- Header -->\n <div class=\"harness-header\">\n @if (entity) {\n <div class=\"agent-info\">\n <div class=\"agent-details\">\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"entity-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n <div>\n <h3>{{ getEntityName() }}</h3>\n @if (entity.Description) {\n <p>{{ entity.Description }}</p>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n <button\n class=\"custom-button\"\n (click)=\"clearConversation()\"\n [disabled]=\"isExecuting || conversationMessages.length === 0\"\n title=\"Clear conversation\">\n <i class=\"fa-solid fa-broom\"></i>\n Clear\n </button>\n <button\n class=\"custom-button\"\n (click)=\"saveConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Save conversation\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n <button\n class=\"custom-button\"\n (click)=\"exportConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Export conversation\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button\n class=\"custom-button\"\n (click)=\"importConversation()\"\n title=\"Import conversation\">\n <i class=\"fa-solid fa-upload\"></i>\n Import\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".json\"\n style=\"display: none\"\n (change)=\"onFileSelected($event)\">\n <button\n class=\"custom-button icon-only\"\n (click)=\"toggleSidebar()\"\n title=\"Toggle sidebar\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!showSidebar\" [class.fa-chevron-left]=\"showSidebar\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n <!-- Main Content Area with Splitter -->\n <div class=\"harness-body\">\n @if (showSidebar) {\n <kendo-splitter\n orientation=\"horizontal\"\n style=\"height: 100%; width: 100%;\">\n <!-- Chat Area (Left Pane) -->\n <kendo-splitter-pane\n [collapsible]=\"false\"\n [resizable]=\"true\"\n [min]=\"'400px'\">\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n @for (message of conversationMessages; track message.id) {\n <div [ngClass]=\"getMessageClass(message)\">\n <div class=\"message-header\">\n <span class=\"message-role\">\n @if (message.role === 'user') {\n <i class=\"fa-solid fa-user\"></i> You\n } @else {\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"message-role-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n {{ getEntityName() || 'Assistant' }}\n }\n </span>\n <span class=\"message-time\">{{ formatTimestamp(message.timestamp) }}</span>\n @if (message.isStreaming && message.elapsedTime !== undefined) {\n <span class=\"execution-time streaming\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> {{ formatElapsedTime(message.elapsedTime) }}\n </span>\n } @else if (message.executionTime) {\n <span class=\"execution-time\" [title]=\"getExecutionSummary(message)\">{{ formatExecutionTime(message.executionTime) }}</span>\n }\n @if (showRawToggle(message)) {\n <button class=\"raw-toggle\" (click)=\"showRawJsonDialog(message)\" title=\"View raw JSON response\">\n <i class=\"fa-solid fa-code\"></i>\n </button>\n }\n </div>\n <div class=\"message-content\">\n <button class=\"copy-button-in-bubble\" (click)=\"copyMessage(message)\" title=\"Copy message\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (message.isStreaming) {\n <div class=\"streaming-wrapper\">\n <span class=\"streaming-content\" [innerHTML]=\"getFormattedStreamingContent(message)\"></span>\n <span class=\"cursor\">|</span>\n </div>\n } @else {\n <div [innerHTML]=\"getFormattedContent(message)\"></div>\n }\n @if (message.error) {\n <div class=\"error-details\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ message.error }}\n </div>\n }\n @if (hasPayload(message.payload) && mode === 'agent' && message.role === 'assistant') {\n <div class=\"payload-section\" [class.collapsed]=\"message.payloadCollapsed\">\n <div class=\"payload-header\" (click)=\"togglePayloadCollapse(message)\">\n <span class=\"payload-label\">\n <i class=\"fa-solid fa-code\"></i> Payload\n </span>\n <button class=\"payload-toggle\" type=\"button\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!message.payloadCollapsed\" [class.fa-chevron-right]=\"message.payloadCollapsed\"></i>\n </button>\n </div>\n @if (!message.payloadCollapsed) {\n <div class=\"payload-content\">\n <mj-code-editor\n [ngModel]=\"formatJson(message.payload)\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <!-- Input Area -->\n <div class=\"input-area\">\n @if (originalPromptRunId && conversationMessages.length > 0) {\n <!-- Re-run mode - show loaded message -->\n <div class=\"rerun-mode-container\">\n <div class=\"rerun-message\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n <span>Messages from Prompt Run <strong>{{ originalPromptRunId.substring(0, 8) }}</strong> loaded above</span>\n </div>\n <div class=\"rerun-buttons\">\n @if (!hasExecutedRerun) {\n <!-- Show Re-Run button if we haven't executed yet -->\n <button\n class=\"send-button rerun-button\"\n (click)=\"executeRerun()\"\n [disabled]=\"isExecuting\"\n title=\"Re-run with loaded messages\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Running...</span>\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n <span>Re-Run</span>\n }\n </button>\n } @else {\n <!-- Show only Reset button after execution -->\n <button\n class=\"send-button reset-button\"\n (click)=\"resetToOriginalMessages()\"\n [disabled]=\"isExecuting\"\n title=\"Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.\">\n <i class=\"fa-solid fa-rotate-left\"></i>\n <span>Reset Messages</span>\n </button>\n }\n </div>\n </div>\n } @else {\n <!-- Normal mode - show text input -->\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n }\n </div>\n </div>\n </kendo-splitter-pane>\n <!-- Sidebar (Right Pane) -->\n <kendo-splitter-pane\n [collapsible]=\"false\"\n [resizable]=\"true\"\n [size]=\"'30%'\"\n [min]=\"'300px'\">\n <div class=\"sidebar\">\n <!-- Tab Navigation -->\n <div class=\"sidebar-tabs\">\n @if (mode === 'agent') {\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentVariables'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentVariables'\"\n (click)=\"selectTab('agentVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Agent Variables\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'executionMonitor'\"\n (click)=\"selectTab('executionMonitor')\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n Execution Monitor\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentSettings'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentSettings'\"\n (click)=\"selectTab('agentSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Settings\n </button>\n } @else {\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'templateVariables'\"\n (click)=\"selectTab('templateVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Template Variables\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'modelSettings'\"\n (click)=\"selectTab('modelSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Model Settings\n </button>\n }\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'savedConversations'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'savedConversations'\"\n (click)=\"selectTab('savedConversations')\">\n <i class=\"fa-solid fa-history\"></i>\n Saved\n @if (savedConversations.length > 0) {\n <span class=\"badge\">{{ savedConversations.length }}</span>\n }\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"sidebar-content\">\n <!-- Agent Variables Tab (Unified) -->\n @if (activeTab === 'agentVariables') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Agent Variables</h4>\n <p>Variables available during agent execution and template rendering</p>\n </div>\n <div class=\"variables-list\">\n @if (agentVariables.length === 0) {\n <div class=\"empty-variables\">\n <p>No variables defined. Click \"Add Variable\" to get started.</p>\n </div>\n }\n @for (variable of agentVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox\n [(ngModel)]=\"variable.name\"\n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n <kendo-dropdownlist\n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n <kendo-textbox\n [(ngModel)]=\"variable.value\"\n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n <button\n class=\"remove-button\"\n (click)=\"removeAgentVariable($index)\"\n [disabled]=\"isExecuting\"\n title=\"Remove variable\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n <button\n class=\"add-button\"\n (click)=\"addAgentVariable()\"\n [disabled]=\"isExecuting\">\n <i class=\"fa-solid fa-plus\"></i> Add Variable\n </button>\n </div>\n }\n <!-- Execution Monitor Tab -->\n @if (activeTab === 'executionMonitor') {\n <div class=\"tab-content\" style=\"padding: 0; height: 100%;\">\n <mj-agent-execution-monitor\n [mode]=\"executionMonitorMode\"\n [agentRun]=\"currentAgentRun\"\n [liveSteps]=\"liveAgentSteps\"\n [autoExpand]=\"true\"\n (viewRunClick)=\"navigateToAgentRun($event)\"\n [runId]=\"getLastRunId()\"\n [runType]=\"mode\">\n </mj-agent-execution-monitor>\n </div>\n }\n <!-- Agent Settings Tab -->\n @if (activeTab === 'agentSettings') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Agent Settings</h4>\n <p>Configure agent execution parameters</p>\n </div>\n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <kendo-dropdownlist\n [(ngModel)]=\"agentConfigurationId\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (agentConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (IsConfigMatchById(config, agentConfigurationId) && config.Description) {\n {{ config.Description }}\n }\n }\n } @else {\n Using default configuration\n }\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Template Variables Tab (Prompt Mode) -->\n @if (activeTab === 'templateVariables') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Template Variables</h4>\n <p>Variables for prompt template rendering</p>\n </div>\n <div class=\"variables-list\">\n @for (variable of templateVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox\n [(ngModel)]=\"variable.name\"\n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n <kendo-dropdownlist\n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n <kendo-textbox\n [(ngModel)]=\"variable.value\"\n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n <button\n class=\"remove-button\"\n (click)=\"removeTemplateVariable($index)\"\n title=\"Remove variable\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n <button\n class=\"add-button\"\n (click)=\"addTemplateVariable()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add Variable\n </button>\n </div>\n }\n <!-- Model Settings Tab (Prompt Mode) -->\n @if (activeTab === 'modelSettings') {\n <div class=\"tab-content\" style=\"overflow-y: auto;\">\n <div class=\"tab-header\">\n <h4>Model Settings</h4>\n <p>Configure AI model parameters</p>\n <button class=\"custom-button icon-only\" (click)=\"resetToPromptDefaults()\" title=\"Reset to Prompt Settings\">\n <i class=\"fa-solid fa-undo\"></i>\n </button>\n </div>\n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Model</label>\n <kendo-dropdownlist\n [(ngModel)]=\"selectedModelId\"\n (ngModelChange)=\"onModelSelectionChange()\"\n [data]=\"availableModels\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a model...\"\n class=\"model-selector\">\n </kendo-dropdownlist>\n </div>\n <div class=\"setting-group\">\n <label>AI Vendor</label>\n <kendo-dropdownlist\n [(ngModel)]=\"selectedVendorId\"\n [data]=\"availableVendors\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [disabled]=\"availableVendors.length <= 1 || !selectedModelId\"\n placeholder=\"Select a vendor...\"\n class=\"vendor-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (!selectedModelId) {\n Using default vendor for the default model\n } @else if (availableVendors.length <= 1) {\n Only one vendor available for this model\n } @else {\n Select the inference provider for this model\n }\n </div>\n </div>\n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <kendo-dropdownlist\n [(ngModel)]=\"selectedConfigurationId\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (selectedConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (IsConfigMatchById(config, selectedConfigurationId) && config.Description) {\n {{ config.Description }}\n }\n }\n } @else {\n Using default configuration\n }\n </div>\n </div>\n <div class=\"setting-group\">\n <label>Response Format</label>\n <kendo-dropdownlist\n [(ngModel)]=\"selectedResponseFormat\"\n [data]=\"responseFormatOptions\"\n textField=\"text\"\n valueField=\"value\"\n placeholder=\"Select format...\"\n class=\"format-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n Expected format for AI response (defaults to prompt setting)\n </div>\n </div>\n <div class=\"setting-group\">\n <label>Max Tokens</label>\n <kendo-numerictextbox\n [(ngModel)]=\"maxTokens\"\n [min]=\"100\"\n [max]=\"8000\"\n [step]=\"100\"\n placeholder=\"Max tokens...\"\n class=\"max-tokens-input\">\n </kendo-numerictextbox>\n <div class=\"setting-help\">\n Maximum length of generated response\n </div>\n </div>\n <div class=\"setting-group\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\"\n [(ngModel)]=\"skipValidation\"\n class=\"skip-validation-checkbox\">\n Skip Validation\n </label>\n <div class=\"setting-help\">\n Skip output validation during testing\n </div>\n </div>\n <!-- Advanced Parameters Expansion Panel -->\n <kendo-expansionpanel\n [expanded]=\"advancedParamsExpanded\"\n (action)=\"toggleAdvancedParams()\"\n title=\"Advanced Parameters\"\n class=\"advanced-params-panel\">\n <div class=\"advanced-settings\">\n <div class=\"setting-group\">\n <label title=\"Controls randomness: 0 = more focused and deterministic, 2 = more random and creative\">\n Temperature\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.temperature\"\n [min]=\"0\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens\">\n Top P\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.topP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Only sample from the top K tokens. Lower values reduce randomness\">\n Top K\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.topK\"\n [min]=\"1\"\n [max]=\"100\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Minimum probability for token selection. Filters out low-probability tokens\">\n Min P\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.minP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Penalizes tokens based on their frequency in the text. Positive values reduce repetition\">\n Frequency Penalty\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.frequencyPenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Penalizes tokens that have appeared in the text. Positive values increase topic diversity\">\n Presence Penalty\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.presencePenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Random seed for deterministic generation. Same seed produces same output\">\n Seed\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.seed\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n <div class=\"setting-group\">\n <label title=\"Sequences that will stop generation when encountered. Enter comma-separated values\">\n Stop Sequences\n </label>\n <kendo-textarea\n [(ngModel)]=\"stopSequencesText\"\n (ngModelChange)=\"updateStopSequences()\"\n [rows]=\"2\"\n placeholder=\"Enter comma-separated sequences\"\n class=\"advanced-param-input\">\n </kendo-textarea>\n <div class=\"setting-help\">\n Separate multiple sequences with commas\n </div>\n </div>\n <div class=\"setting-group\">\n <label title=\"Include log probabilities of the output tokens in the response\">\n Include Log Probs\n </label>\n <kendo-switch\n [(ngModel)]=\"advancedParams.includeLogProbs\"\n class=\"advanced-param-switch\">\n </kendo-switch>\n </div>\n @if (advancedParams.includeLogProbs) {\n <div class=\"setting-group\">\n <label title=\"Number of top log probabilities to include for each token\">\n Top Log Probs\n </label>\n <kendo-numerictextbox\n [(ngModel)]=\"advancedParams.topLogProbs\"\n [min]=\"2\"\n [max]=\"20\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"2\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n </div>\n </div>\n }\n <!-- Saved Conversations Tab -->\n @if (activeTab === 'savedConversations') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Saved Conversations</h4>\n <p>Previously saved test sessions</p>\n @if (currentConversationId) {\n <button class=\"custom-button small primary\" (click)=\"newConversation()\" title=\"Start a new conversation\">\n <i class=\"fa-solid fa-plus\"></i>\n New\n </button>\n }\n </div>\n <div class=\"saved-list\">\n @if (savedConversations.length === 0) {\n <div class=\"empty-saved\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <p>No saved conversations</p>\n </div>\n }\n @for (conv of savedConversations; track conv.id) {\n <div class=\"saved-item\"\n [class.current]=\"conv.id === currentConversationId\"\n (click)=\"loadConversation(conv)\">\n <div class=\"saved-info\">\n <h5>{{ conv.name }}</h5>\n <p>{{ conv.messages.length }} messages</p>\n <span class=\"saved-date\">{{ conv.updatedAt | date:'short' }}</span>\n </div>\n <button\n class=\"delete-button\"\n (click)=\"deleteConversation(conv, $event)\"\n title=\"Delete conversation\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n } @else {\n <!-- No sidebar - full width chat -->\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n @for (message of conversationMessages; track message.id) {\n <div [ngClass]=\"getMessageClass(message)\">\n <div class=\"message-header\">\n <span class=\"message-role\">\n @if (message.role === 'user') {\n <i class=\"fa-solid fa-user\"></i> You\n } @else {\n <i class=\"fa-solid fa-robot\"></i> {{ getEntityName() || 'Assistant' }}\n }\n </span>\n <span class=\"message-time\">{{ formatTimestamp(message.timestamp) }}</span>\n @if (message.isStreaming && message.elapsedTime !== undefined) {\n <span class=\"execution-time streaming\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> {{ formatElapsedTime(message.elapsedTime) }}\n </span>\n } @else if (message.executionTime) {\n <span class=\"execution-time\" [title]=\"getExecutionSummary(message)\">{{ formatExecutionTime(message.executionTime) }}</span>\n }\n @if (showRawToggle(message)) {\n <button class=\"raw-toggle\" (click)=\"showRawJsonDialog(message)\" title=\"View raw JSON response\">\n <i class=\"fa-solid fa-code\"></i>\n </button>\n }\n @if (message.executionData && mode === 'agent' && message.role === 'assistant') {\n <button class=\"execution-history-toggle\" (click)=\"showMessageExecutionHistory(message)\" title=\"View execution details\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n </button>\n }\n @if (message.agentRunId && mode === 'agent' && message.role === 'assistant') {\n <button class=\"execution-history-toggle\" (click)=\"navigateToAgentRun({runId: message.agentRunId, runType: 'agent'})\" title=\"View full run details\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n <div class=\"message-content\">\n <button class=\"copy-button-in-bubble\" (click)=\"copyMessage(message)\" title=\"Copy message\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (message.isStreaming) {\n <div class=\"streaming-wrapper\">\n <span class=\"streaming-content\">{{ message.streamingContent }}<span class=\"cursor\">|</span></span>\n </div>\n } @else {\n <div [innerHTML]=\"getFormattedContent(message)\"></div>\n }\n @if (message.error) {\n <div class=\"error-details\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ message.error }}\n </div>\n }\n @if (hasPayload(message.payload) && mode === 'agent' && message.role === 'assistant') {\n <div class=\"payload-section\" [class.collapsed]=\"message.payloadCollapsed\">\n <div class=\"payload-header\" (click)=\"togglePayloadCollapse(message)\">\n <span class=\"payload-label\">\n <i class=\"fa-solid fa-code\"></i> Payload\n </span>\n <button class=\"payload-toggle\" type=\"button\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!message.payloadCollapsed\" [class.fa-chevron-right]=\"message.payloadCollapsed\"></i>\n </button>\n </div>\n @if (!message.payloadCollapsed) {\n <div class=\"payload-content\">\n <pre>{{ formatJson(message.payload) }}</pre>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- Save Conversation Dialog -->\n@if (showSaveDialog) {\n <kendo-dialog\n [title]=\"'Save Conversation'\"\n [width]=\"400\"\n (close)=\"cancelSaveDialog()\"\n class=\"save-dialog\">\n <div class=\"dialog-content\">\n <p>Enter a name for this conversation:</p>\n <input\n #saveDialogInput\n type=\"text\"\n (keyup)=\"updateTempConversation()\"\n placeholder=\"Conversation name\"\n class=\"k-textbox k-input k-input-md k-rounded-md k-input-solid full-width\" />\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelSaveDialog()\">Cancel</button>\n <button kendoButton\n [primary]=\"true\"\n (click)=\"confirmSaveConversation()\"\n [disabled]=\"tempConversationName === ''\">\n Save\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n}\n\n<!-- Load Confirmation Dialog -->\n@if (showLoadConfirmDialog) {\n <kendo-dialog\n [title]=\"'Replace Current Conversation?'\"\n [width]=\"400\"\n (close)=\"cancelLoadConversation()\"\n class=\"confirm-dialog\">\n <div class=\"dialog-content\">\n <p>Loading this conversation will replace the current one. Any unsaved changes will be lost.</p>\n <p>Do you want to continue?</p>\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelLoadConversation()\">Cancel</button>\n <button kendoButton\n [primary]=\"true\"\n (click)=\"confirmLoadConversation()\">\n Load Conversation\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n}\n\n", styles: ["/* Container Styles */\n.harness-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-card);\n}\n\n/* Custom Button Styles */\n.custom-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.custom-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.custom-button:active:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.custom-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.custom-button.icon-only {\n padding: 6px 8px;\n}\n\n.custom-button i {\n font-size: 14px;\n}\n\n/* Send Button - Primary Style */\n.send-button {\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 44px;\n font-family: inherit;\n}\n\n.send-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button:active:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.send-button i {\n font-size: 16px;\n}\n\n/* Add Button */\n.add-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.add-button:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n/* Remove/Delete Buttons */\n.remove-button,\n.delete-button {\n background: transparent;\n border: none;\n color: var(--mj-status-error);\n padding: 4px 8px;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s;\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.remove-button:hover,\n.delete-button:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-color-error-600);\n}\n\n/* Copy Button in Message Bubble */\n.copy-button-in-bubble {\n position: absolute;\n top: 8px;\n right: 8px;\n background: transparent;\n border: none;\n padding: 6px;\n font-size: 14px;\n color: var(--mj-border-strong);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0;\n z-index: 10; /* Ensure it's above content */\n}\n\n.message-content:hover .copy-button-in-bubble {\n opacity: 1;\n}\n\n.copy-button-in-bubble:hover {\n background: rgba(0, 0, 0, 0.08);\n color: var(--mj-text-muted);\n}\n\n.copy-button-in-bubble i {\n font-size: 14px;\n}\n\n/* Model Settings Styles (Prompt Mode) */\n.model-settings {\n padding: 16px;\n}\n\n.setting-group {\n margin-bottom: 24px;\n}\n\n.setting-group label {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n}\n\n.model-selector,\n.vendor-selector {\n width: 100%;\n}\n\n.temperature-slider {\n width: 100%;\n margin-top: 8px;\n}\n\n.max-tokens-input {\n width: 100%;\n}\n\n.setting-help {\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* Checkbox Styles */\n.checkbox-label {\n display: flex;\n align-items: center;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n cursor: pointer;\n}\n\n.skip-validation-checkbox {\n margin-right: 8px;\n cursor: pointer;\n width: 16px;\n height: 16px;\n}\n\n/* Header Styles */\n.harness-header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.agent-info {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.agent-details {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.agent-details i {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.agent-details .entity-logo {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n}\n\n.agent-details h3 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-details p {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n/* Body Layout */\n.harness-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n/* Chat Area */\n.chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n height: 100%;\n min-height: 0; /* Important for flexbox children */\n}\n\n/* Messages Container */\n.messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 500;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Message Styles */\n.message {\n margin-bottom: 20px;\n animation: fadeIn 0.3s ease-in;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-user {\n margin-left: auto;\n max-width: 70%;\n}\n\n.message-assistant {\n margin-right: auto;\n max-width: 70%;\n}\n\n.message-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 13px;\n}\n\n.message-role {\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.message-role i {\n font-size: 14px;\n}\n\n.message-role .message-role-logo {\n width: 16px;\n height: 16px;\n object-fit: cover;\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.message-user .message-role {\n color: var(--mj-brand-primary);\n}\n\n.message-assistant .message-role {\n color: var(--mj-brand-primary);\n}\n\n.message-time {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.execution-time {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.raw-toggle {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n}\n\n.raw-toggle:hover {\n background: rgba(0, 0, 0, 0.05);\n color: var(--mj-text-secondary);\n}\n\n.raw-toggle i {\n font-size: 12px;\n}\n\n/* Message content styles are now defined above in enhanced content formatting section */\n\n.message-user .message-content {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.message-assistant .message-content {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.message.streaming .message-content {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.streaming-content {\n display: inline;\n}\n\n.streaming-wrapper {\n position: relative;\n}\n\n.streaming-wrapper .cursor {\n display: inline;\n margin-left: 2px;\n}\n\n.cursor {\n animation: blink 1s infinite;\n font-weight: 100;\n color: var(--mj-text-secondary);\n}\n\n@keyframes blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n.error-details {\n margin-top: 8px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n border-radius: 6px;\n color: var(--mj-color-error-600);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details i {\n color: var(--mj-status-error);\n}\n\n/* Payload Section Styles */\n.payload-section {\n margin-top: 12px;\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.payload-header {\n background: var(--mj-bg-surface-card);\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.payload-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.payload-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label i {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.payload-content {\n max-height: 250px;\n overflow: auto;\n background: var(--mj-bg-surface-card);\n}\n\n.payload-content pre {\n margin: 0;\n padding: 12px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n background: transparent;\n}\n\n.payload-toggle {\n background: transparent;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.payload-toggle:hover {\n color: var(--mj-text-secondary);\n}\n\n.payload-toggle i {\n font-size: 12px;\n}\n\n.payload-section.collapsed .payload-header {\n border-bottom: none;\n}\n\n/* Dialog styles */\n.save-dialog,\n.confirm-dialog {\n .dialog-content {\n padding: 20px;\n\n p {\n margin: 0 0 16px 0;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.5;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .full-width {\n width: 100%;\n }\n\n input.k-textbox {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n\n &:focus {\n outline: none;\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--mj-status-error) 25%, transparent);\n }\n }\n }\n}\n\n/* Enhanced content formatting styles */\n.markdown-content {\n line-height: 1.6;\n word-wrap: break-word;\n overflow-wrap: break-word;\n max-width: 100%;\n}\n\n/* Inline JSON editor styles */\n.inline-json-editor {\n margin: 8px 0;\n\n .json-editor-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 4px;\n overflow: hidden;\n position: relative;\n max-height: 400px;\n\n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 13px;\n line-height: 1.5;\n overflow: auto;\n height: 100%;\n background: transparent;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n }\n}\n\n.markdown-paragraph {\n margin: 8px 0;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.markdown-h1 {\n font-size: 1.5em;\n font-weight: 600;\n margin: 16px 0 8px 0;\n color: var(--mj-text-primary);\n border-bottom: 2px solid var(--mj-bg-surface-sunken);\n padding-bottom: 4px;\n}\n\n.markdown-h2 {\n font-size: 1.3em;\n font-weight: 600;\n margin: 14px 0 6px 0;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n padding-bottom: 2px;\n}\n\n.markdown-h3 {\n font-size: 1.1em;\n font-weight: 600;\n margin: 12px 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.code-block {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 16px;\n margin: 12px 0;\n overflow-x: auto;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre;\n word-wrap: normal;\n max-width: 100%;\n}\n\n.code-block code {\n background: none;\n border: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre;\n word-wrap: normal;\n}\n\n.language-json {\n color: var(--mj-status-error);\n}\n\n.inline-code {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 0.9em;\n color: var(--mj-status-error);\n white-space: nowrap;\n}\n\n.markdown-list {\n margin: 8px 0;\n padding-left: 24px;\n}\n\n.markdown-list li {\n margin: 4px 0;\n line-height: 1.5;\n}\n\n.markdown-link {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: none;\n}\n\n/* Ensure proper text wrapping in message content */\n.message-content {\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n padding: 12px 40px 12px 16px; /* Extra right padding for copy button */\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n position: relative;\n overflow-wrap: break-word;\n hyphens: auto;\n max-width: 100%;\n overflow-x: hidden;\n}\n\n/* Enhanced JSON content display */\n.json-content-wrapper {\n margin: 8px 0;\n}\n\n.json-main-content {\n margin-bottom: 12px;\n}\n\n.json-raw-section {\n margin-top: 12px;\n}\n\n.json-toggle-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.json-toggle-button:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.json-toggle-button i {\n font-size: 12px;\n}\n\n/* Compact code block for JSON in collapsible sections */\n.json-raw-section .code-block {\n margin: 8px 0 0 0;\n font-size: 12px;\n max-height: 300px;\n overflow-y: auto;\n}\n\n/* Better mobile responsiveness for JSON content */\n@media (max-width: 768px) {\n .json-raw-section .code-block {\n font-size: 11px;\n max-height: 200px;\n }\n}\n\n/* JSON raw section styling - simplified since we use code editor in dialog */\n.json-raw-section {\n margin-top: 12px;\n}\n\n/* Input Area */\n.input-area {\n padding: 16px;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0; /* Prevent input area from shrinking */\n margin-top: auto; /* Push to bottom */\n}\n\n.input-container {\n display: flex;\n gap: 12px;\n align-items: center;\n}\n\n.rerun-mode-container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 8px;\n gap: 16px;\n}\n\n.rerun-message {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.rerun-message i {\n font-size: 16px;\n}\n\n.rerun-message strong {\n font-family: 'Fira Code', 'Consolas', monospace;\n}\n\n.rerun-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 100px;\n justify-content: center;\n}\n\n.rerun-button span {\n font-weight: 500;\n}\n\n.rerun-buttons {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.reset-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 120px;\n justify-content: center;\n background-color: var(--mj-text-muted);\n}\n\n.reset-button:hover:not(:disabled) {\n background-color: var(--mj-text-secondary);\n}\n\n.reset-button span {\n font-weight: 500;\n}\n\n.message-input {\n flex: 1;\n}\n\n.message-input textarea {\n resize: none;\n font-size: 14px;\n}\n\n.send-button {\n margin-bottom: 1px;\n}\n\n/* Sidebar */\n.sidebar {\n width: 100%; /* Changed from fixed 360px to 100% */\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* Kendo Splitter Specific Styles */\n.harness-body kendo-splitter {\n height: 100%;\n}\n\n.harness-body kendo-splitter-pane {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Sidebar Tabs */\n.sidebar-tabs {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.tab-button {\n flex: 1;\n padding: 12px 8px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.tab-button:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.tab-button.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.tab-button i {\n font-size: 14px;\n}\n\n.tab-button .badge {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n margin-left: 4px;\n}\n\n.tab-button.active .badge {\n background: var(--mj-brand-primary);\n}\n\n.tab-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* Sidebar Content */\n.sidebar-content {\n flex: 1;\n overflow-y: auto;\n width: 100%; /* Ensure content takes full width */\n}\n\n.tab-content {\n padding: 20px;\n width: 100%; /* Ensure content takes full width */\n box-sizing: border-box; /* Include padding in width calculation */\n}\n\n.tab-header {\n margin-bottom: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.tab-header .custom-button.icon-only {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.tab-header h4 {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.tab-header p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.tab-header .custom-button.small {\n align-self: flex-start;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n.tab-header .custom-button.small i {\n margin-right: 4px;\n}\n\n/* Variables */\n.variables-list {\n margin-bottom: 16px;\n width: 100%;\n}\n\n.variable-item {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n align-items: center;\n width: 100%;\n}\n\n.variable-name {\n width: 30%; /* Changed from fixed width to percentage */\n min-width: 100px;\n}\n\n.variable-type {\n width: 25%; /* Changed from fixed width to percentage */\n min-width: 80px;\n}\n\n.variable-value {\n flex: 1;\n min-width: 0; /* Allow flex item to shrink below content size */\n}\n\n.remove-button {\n width: 32px;\n height: 32px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.add-variable-button {\n width: 100%;\n}\n\n.empty-variables {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n/* Saved Conversations */\n.saved-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-saved {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-saved i {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.saved-item {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.saved-item:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n}\n\n.saved-item.current {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.saved-info h5 {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.saved-info p {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.saved-date {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Responsive adjustments */\n@media (max-width: 1200px) {\n .sidebar {\n width: 320px;\n }\n}\n\n@media (max-width: 992px) {\n .message-user,\n .message-assistant {\n max-width: 85%;\n }\n\n .sidebar {\n width: 280px;\n }\n}\n\n/* Custom scrollbar */\n.messages-container::-webkit-scrollbar,\n.sidebar-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.messages-container::-webkit-scrollbar-track,\n.sidebar-content::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n}\n\n.messages-container::-webkit-scrollbar-thumb,\n.sidebar-content::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.messages-container::-webkit-scrollbar-thumb:hover,\n.sidebar-content::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Dialog customization */\n::ng-deep .ai-agent-test-harness .k-dialog-wrapper {\n border-radius: 8px;\n overflow: hidden;\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-titlebar {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-inverse);\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-title {\n font-weight: 600;\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-titlebar-actions .k-button {\n color: var(--mj-text-inverse);\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-content {\n padding: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n/* JSON Dialog Styles - removed since we're using WindowService */\n\n/* Advanced Parameters Styles */\n.advanced-params-panel {\n margin-top: 24px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n}\n\n.advanced-params-panel ::ng-deep .k-expander-title {\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.advanced-settings {\n padding: 16px;\n}\n\n.advanced-param-input {\n width: 100%;\n}\n\n.advanced-param-switch {\n margin-top: 8px;\n}\n\n/* Format selector dropdown */\n.format-selector {\n width: 100%;\n}\n"] }]
3900
- }], () => [{ type: i1.DomSanitizer }, { type: i2.WindowService }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }, { type: i3.Router }], { mode: [{
3871
+ args: [{ standalone: false, selector: 'mj-ai-test-harness', template: "@if (isVisible) {\n <div class=\"harness-container\">\n <!-- Header -->\n <div class=\"harness-header\">\n @if (entity) {\n <div class=\"agent-info\">\n <div class=\"agent-details\">\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"entity-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n <div>\n <h3>{{ getEntityName() }}</h3>\n @if (entity.Description) {\n <p>{{ entity.Description }}</p>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n <button\n class=\"custom-button\"\n (click)=\"clearConversation()\"\n [disabled]=\"isExecuting || conversationMessages.length === 0\"\n title=\"Clear conversation\">\n <i class=\"fa-solid fa-broom\"></i>\n Clear\n </button>\n <button\n class=\"custom-button\"\n (click)=\"saveConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Save conversation\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n <button\n class=\"custom-button\"\n (click)=\"exportConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Export conversation\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button\n class=\"custom-button\"\n (click)=\"importConversation()\"\n title=\"Import conversation\">\n <i class=\"fa-solid fa-upload\"></i>\n Import\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".json\"\n style=\"display: none\"\n (change)=\"onFileSelected($event)\">\n <button\n class=\"custom-button icon-only\"\n (click)=\"toggleSidebar()\"\n title=\"Toggle sidebar\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!showSidebar\" [class.fa-chevron-left]=\"showSidebar\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n <!-- Main Content Area with Splitter -->\n <div class=\"harness-body\">\n @if (showSidebar) {\n <as-split\n direction=\"horizontal\"\n style=\"height: 100%; width: 100%;\">\n <!-- Chat Area (Left Pane) -->\n <as-split-area\n [size]=\"70\">\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n @for (message of conversationMessages; track message.id) {\n <div [ngClass]=\"getMessageClass(message)\">\n <div class=\"message-header\">\n <span class=\"message-role\">\n @if (message.role === 'user') {\n <i class=\"fa-solid fa-user\"></i> You\n } @else {\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"message-role-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n {{ getEntityName() || 'Assistant' }}\n }\n </span>\n <span class=\"message-time\">{{ formatTimestamp(message.timestamp) }}</span>\n @if (message.isStreaming && message.elapsedTime !== undefined) {\n <span class=\"execution-time streaming\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> {{ formatElapsedTime(message.elapsedTime) }}\n </span>\n } @else if (message.executionTime) {\n <span class=\"execution-time\" [title]=\"getExecutionSummary(message)\">{{ formatExecutionTime(message.executionTime) }}</span>\n }\n @if (showRawToggle(message)) {\n <button class=\"raw-toggle\" (click)=\"showRawJsonDialog(message)\" title=\"View raw JSON response\">\n <i class=\"fa-solid fa-code\"></i>\n </button>\n }\n </div>\n <div class=\"message-content\">\n <button class=\"copy-button-in-bubble\" (click)=\"copyMessage(message)\" title=\"Copy message\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (message.isStreaming) {\n <div class=\"streaming-wrapper\">\n <span class=\"streaming-content\" [innerHTML]=\"getFormattedStreamingContent(message)\"></span>\n <span class=\"cursor\">|</span>\n </div>\n } @else {\n <div [innerHTML]=\"getFormattedContent(message)\"></div>\n }\n @if (message.error) {\n <div class=\"error-details\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ message.error }}\n </div>\n }\n @if (hasPayload(message.payload) && mode === 'agent' && message.role === 'assistant') {\n <div class=\"payload-section\" [class.collapsed]=\"message.payloadCollapsed\">\n <div class=\"payload-header\" (click)=\"togglePayloadCollapse(message)\">\n <span class=\"payload-label\">\n <i class=\"fa-solid fa-code\"></i> Payload\n </span>\n <button class=\"payload-toggle\" type=\"button\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!message.payloadCollapsed\" [class.fa-chevron-right]=\"message.payloadCollapsed\"></i>\n </button>\n </div>\n @if (!message.payloadCollapsed) {\n <div class=\"payload-content\">\n <mj-code-editor\n [ngModel]=\"formatJson(message.payload)\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <!-- Input Area -->\n <div class=\"input-area\">\n @if (originalPromptRunId && conversationMessages.length > 0) {\n <!-- Re-run mode - show loaded message -->\n <div class=\"rerun-mode-container\">\n <div class=\"rerun-message\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n <span>Messages from Prompt Run <strong>{{ originalPromptRunId.substring(0, 8) }}</strong> loaded above</span>\n </div>\n <div class=\"rerun-buttons\">\n @if (!hasExecutedRerun) {\n <!-- Show Re-Run button if we haven't executed yet -->\n <button\n class=\"send-button rerun-button\"\n (click)=\"executeRerun()\"\n [disabled]=\"isExecuting\"\n title=\"Re-run with loaded messages\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Running...</span>\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n <span>Re-Run</span>\n }\n </button>\n } @else {\n <!-- Show only Reset button after execution -->\n <button\n class=\"send-button reset-button\"\n (click)=\"resetToOriginalMessages()\"\n [disabled]=\"isExecuting\"\n title=\"Reset conversation messages to the original state from the prompt run. Model settings and parameters will be preserved.\">\n <i class=\"fa-solid fa-rotate-left\"></i>\n <span>Reset Messages</span>\n </button>\n }\n </div>\n </div>\n } @else {\n <!-- Normal mode - show text input -->\n <div class=\"input-container\">\n <textarea\n #messageInput\n class=\"mj-textarea message-input\"\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"></textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n }\n </div>\n </div>\n </as-split-area>\n <!-- Sidebar (Right Pane) -->\n <as-split-area\n [size]=\"30\">\n <div class=\"sidebar\">\n <!-- Tab Navigation -->\n <div class=\"sidebar-tabs\">\n @if (mode === 'agent') {\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentVariables'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentVariables'\"\n (click)=\"selectTab('agentVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Agent Variables\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'executionMonitor'\"\n (click)=\"selectTab('executionMonitor')\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n Execution Monitor\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentSettings'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentSettings'\"\n (click)=\"selectTab('agentSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Settings\n </button>\n } @else {\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'templateVariables'\"\n (click)=\"selectTab('templateVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Template Variables\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'modelSettings'\"\n (click)=\"selectTab('modelSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Model Settings\n </button>\n }\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'savedConversations'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'savedConversations'\"\n (click)=\"selectTab('savedConversations')\">\n <i class=\"fa-solid fa-history\"></i>\n Saved\n @if (savedConversations.length > 0) {\n <span class=\"badge\">{{ savedConversations.length }}</span>\n }\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"sidebar-content\">\n <!-- Agent Variables Tab (Unified) -->\n @if (activeTab === 'agentVariables') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Agent Variables</h4>\n <p>Variables available during agent execution and template rendering</p>\n </div>\n <div class=\"variables-list\">\n @if (agentVariables.length === 0) {\n <div class=\"empty-variables\">\n <p>No variables defined. Click \"Add Variable\" to get started.</p>\n </div>\n }\n @for (variable of agentVariables; track $index) {\n <div class=\"variable-item\">\n <input type=\"text\"\n class=\"mj-input variable-name\"\n [(ngModel)]=\"variable.name\"\n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\" />\n <mj-dropdown\n [(ngModel)]=\"variable.type\"\n [Data]=\"[\n {text: 'String', value: 'string'},\n {text: 'Number', value: 'number'},\n {text: 'Boolean', value: 'boolean'},\n {text: 'Object', value: 'object'}\n ]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Disabled]=\"isExecuting\"\n class=\"variable-type\">\n </mj-dropdown>\n <input type=\"text\"\n class=\"mj-input variable-value\"\n [(ngModel)]=\"variable.value\"\n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\" />\n <button\n class=\"remove-button\"\n (click)=\"removeAgentVariable($index)\"\n [disabled]=\"isExecuting\"\n title=\"Remove variable\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n <button\n class=\"add-button\"\n (click)=\"addAgentVariable()\"\n [disabled]=\"isExecuting\">\n <i class=\"fa-solid fa-plus\"></i> Add Variable\n </button>\n </div>\n }\n <!-- Execution Monitor Tab -->\n @if (activeTab === 'executionMonitor') {\n <div class=\"tab-content\" style=\"padding: 0; height: 100%;\">\n <mj-agent-execution-monitor\n [mode]=\"executionMonitorMode\"\n [agentRun]=\"currentAgentRun\"\n [liveSteps]=\"liveAgentSteps\"\n [autoExpand]=\"true\"\n (viewRunClick)=\"navigateToAgentRun($event)\"\n [runId]=\"getLastRunId()\"\n [runType]=\"mode\">\n </mj-agent-execution-monitor>\n </div>\n }\n <!-- Agent Settings Tab -->\n @if (activeTab === 'agentSettings') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Agent Settings</h4>\n <p>Configure agent execution parameters</p>\n </div>\n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <mj-dropdown\n [(ngModel)]=\"agentConfigurationId\"\n [Data]=\"availableConfigurations\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </mj-dropdown>\n <div class=\"setting-help\">\n @if (agentConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (IsConfigMatchById(config, agentConfigurationId) && config.Description) {\n {{ config.Description }}\n }\n }\n } @else {\n Using default configuration\n }\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Template Variables Tab (Prompt Mode) -->\n @if (activeTab === 'templateVariables') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Template Variables</h4>\n <p>Variables for prompt template rendering</p>\n </div>\n <div class=\"variables-list\">\n @for (variable of templateVariables; track $index) {\n <div class=\"variable-item\">\n <input type=\"text\"\n class=\"mj-input variable-name\"\n [(ngModel)]=\"variable.name\"\n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\" />\n <mj-dropdown\n [(ngModel)]=\"variable.type\"\n [Data]=\"[\n {text: 'String', value: 'string'},\n {text: 'Number', value: 'number'},\n {text: 'Boolean', value: 'boolean'},\n {text: 'Object', value: 'object'}\n ]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Disabled]=\"isExecuting\"\n class=\"variable-type\">\n </mj-dropdown>\n <input type=\"text\"\n class=\"mj-input variable-value\"\n [(ngModel)]=\"variable.value\"\n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\" />\n <button\n class=\"remove-button\"\n (click)=\"removeTemplateVariable($index)\"\n title=\"Remove variable\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n <button\n class=\"add-button\"\n (click)=\"addTemplateVariable()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add Variable\n </button>\n </div>\n }\n <!-- Model Settings Tab (Prompt Mode) -->\n @if (activeTab === 'modelSettings') {\n <div class=\"tab-content\" style=\"overflow-y: auto;\">\n <div class=\"tab-header\">\n <h4>Model Settings</h4>\n <p>Configure AI model parameters</p>\n <button class=\"custom-button icon-only\" (click)=\"resetToPromptDefaults()\" title=\"Reset to Prompt Settings\">\n <i class=\"fa-solid fa-undo\"></i>\n </button>\n </div>\n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Model</label>\n <mj-dropdown\n [(ngModel)]=\"selectedModelId\"\n (ngModelChange)=\"onModelSelectionChange()\"\n [Data]=\"availableModels\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select a model...\"\n class=\"model-selector\">\n </mj-dropdown>\n </div>\n <div class=\"setting-group\">\n <label>AI Vendor</label>\n <mj-dropdown\n [(ngModel)]=\"selectedVendorId\"\n [Data]=\"availableVendors\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [Disabled]=\"availableVendors.length <= 1 || !selectedModelId\"\n Placeholder=\"Select a vendor...\"\n class=\"vendor-selector\">\n </mj-dropdown>\n <div class=\"setting-help\">\n @if (!selectedModelId) {\n Using default vendor for the default model\n } @else if (availableVendors.length <= 1) {\n Only one vendor available for this model\n } @else {\n Select the inference provider for this model\n }\n </div>\n </div>\n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <mj-dropdown\n [(ngModel)]=\"selectedConfigurationId\"\n [Data]=\"availableConfigurations\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </mj-dropdown>\n <div class=\"setting-help\">\n @if (selectedConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (IsConfigMatchById(config, selectedConfigurationId) && config.Description) {\n {{ config.Description }}\n }\n }\n } @else {\n Using default configuration\n }\n </div>\n </div>\n <div class=\"setting-group\">\n <label>Response Format</label>\n <mj-dropdown\n [(ngModel)]=\"selectedResponseFormat\"\n [Data]=\"responseFormatOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n Placeholder=\"Select format...\"\n class=\"format-selector\">\n </mj-dropdown>\n <div class=\"setting-help\">\n Expected format for AI response (defaults to prompt setting)\n </div>\n </div>\n <div class=\"setting-group\">\n <label>Max Tokens</label>\n <mj-numeric-input\n [(ngModel)]=\"maxTokens\"\n [Min]=\"100\"\n [Max]=\"8000\"\n [Step]=\"100\"\n Placeholder=\"Max tokens...\"\n class=\"max-tokens-input\">\n </mj-numeric-input>\n <div class=\"setting-help\">\n Maximum length of generated response\n </div>\n </div>\n <div class=\"setting-group\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\"\n [(ngModel)]=\"skipValidation\"\n class=\"skip-validation-checkbox\">\n Skip Validation\n </label>\n <div class=\"setting-help\">\n Skip output validation during testing\n </div>\n </div>\n <!-- Advanced Parameters Expansion Panel -->\n <mj-accordion-panel\n [Title]=\"'Advanced Parameters'\"\n [Expanded]=\"advancedParamsExpanded\"\n class=\"advanced-params-panel\">\n <div class=\"advanced-settings\">\n <div class=\"setting-group\">\n <label title=\"Controls randomness: 0 = more focused and deterministic, 2 = more random and creative\">\n Temperature\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.temperature\"\n [Min]=\"0\"\n [Max]=\"2\"\n [Step]=\"0.1\"\n [Format]=\"'n1'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens\">\n Top P\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.topP\"\n [Min]=\"0\"\n [Max]=\"1\"\n [Step]=\"0.01\"\n [Format]=\"'n2'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Only sample from the top K tokens. Lower values reduce randomness\">\n Top K\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.topK\"\n [Min]=\"1\"\n [Max]=\"100\"\n [Step]=\"1\"\n [Format]=\"'n0'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Minimum probability for token selection. Filters out low-probability tokens\">\n Min P\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.minP\"\n [Min]=\"0\"\n [Max]=\"1\"\n [Step]=\"0.01\"\n [Format]=\"'n2'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Penalizes tokens based on their frequency in the text. Positive values reduce repetition\">\n Frequency Penalty\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.frequencyPenalty\"\n [Min]=\"-2\"\n [Max]=\"2\"\n [Step]=\"0.1\"\n [Format]=\"'n1'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Penalizes tokens that have appeared in the text. Positive values increase topic diversity\">\n Presence Penalty\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.presencePenalty\"\n [Min]=\"-2\"\n [Max]=\"2\"\n [Step]=\"0.1\"\n [Format]=\"'n1'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Random seed for deterministic generation. Same seed produces same output\">\n Seed\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.seed\"\n [Format]=\"'n0'\"\n Placeholder=\"None\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n <div class=\"setting-group\">\n <label title=\"Sequences that will stop generation when encountered. Enter comma-separated values\">\n Stop Sequences\n </label>\n <textarea\n class=\"mj-textarea advanced-param-input\"\n [(ngModel)]=\"stopSequencesText\"\n (ngModelChange)=\"updateStopSequences()\"\n [rows]=\"2\"\n placeholder=\"Enter comma-separated sequences\"></textarea>\n <div class=\"setting-help\">\n Separate multiple sequences with commas\n </div>\n </div>\n <div class=\"setting-group\">\n <label title=\"Include log probabilities of the output tokens in the response\">\n Include Log Probs\n </label>\n <mj-switch\n [(ngModel)]=\"advancedParams.includeLogProbs\"\n class=\"advanced-param-switch\">\n </mj-switch>\n </div>\n @if (advancedParams.includeLogProbs) {\n <div class=\"setting-group\">\n <label title=\"Number of top log probabilities to include for each token\">\n Top Log Probs\n </label>\n <mj-numeric-input\n [(ngModel)]=\"advancedParams.topLogProbs\"\n [Min]=\"2\"\n [Max]=\"20\"\n [Step]=\"1\"\n [Format]=\"'n0'\"\n Placeholder=\"2\"\n class=\"advanced-param-input\">\n </mj-numeric-input>\n </div>\n }\n </div>\n </mj-accordion-panel>\n </div>\n </div>\n }\n <!-- Saved Conversations Tab -->\n @if (activeTab === 'savedConversations') {\n <div class=\"tab-content\">\n <div class=\"tab-header\">\n <h4>Saved Conversations</h4>\n <p>Previously saved test sessions</p>\n @if (currentConversationId) {\n <button class=\"custom-button small primary\" (click)=\"newConversation()\" title=\"Start a new conversation\">\n <i class=\"fa-solid fa-plus\"></i>\n New\n </button>\n }\n </div>\n <div class=\"saved-list\">\n @if (savedConversations.length === 0) {\n <div class=\"empty-saved\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <p>No saved conversations</p>\n </div>\n }\n @for (conv of savedConversations; track conv.id) {\n <div class=\"saved-item\"\n [class.current]=\"conv.id === currentConversationId\"\n (click)=\"loadConversation(conv)\">\n <div class=\"saved-info\">\n <h5>{{ conv.name }}</h5>\n <p>{{ conv.messages.length }} messages</p>\n <span class=\"saved-date\">{{ conv.updatedAt | date:'short' }}</span>\n </div>\n <button\n class=\"delete-button\"\n (click)=\"deleteConversation(conv, $event)\"\n title=\"Delete conversation\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </as-split-area>\n </as-split>\n } @else {\n <!-- No sidebar - full width chat -->\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n @for (message of conversationMessages; track message.id) {\n <div [ngClass]=\"getMessageClass(message)\">\n <div class=\"message-header\">\n <span class=\"message-role\">\n @if (message.role === 'user') {\n <i class=\"fa-solid fa-user\"></i> You\n } @else {\n <i class=\"fa-solid fa-robot\"></i> {{ getEntityName() || 'Assistant' }}\n }\n </span>\n <span class=\"message-time\">{{ formatTimestamp(message.timestamp) }}</span>\n @if (message.isStreaming && message.elapsedTime !== undefined) {\n <span class=\"execution-time streaming\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> {{ formatElapsedTime(message.elapsedTime) }}\n </span>\n } @else if (message.executionTime) {\n <span class=\"execution-time\" [title]=\"getExecutionSummary(message)\">{{ formatExecutionTime(message.executionTime) }}</span>\n }\n @if (showRawToggle(message)) {\n <button class=\"raw-toggle\" (click)=\"showRawJsonDialog(message)\" title=\"View raw JSON response\">\n <i class=\"fa-solid fa-code\"></i>\n </button>\n }\n @if (message.executionData && mode === 'agent' && message.role === 'assistant') {\n <button class=\"execution-history-toggle\" (click)=\"showMessageExecutionHistory(message)\" title=\"View execution details\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n </button>\n }\n @if (message.agentRunId && mode === 'agent' && message.role === 'assistant') {\n <button class=\"execution-history-toggle\" (click)=\"navigateToAgentRun({runId: message.agentRunId, runType: 'agent'})\" title=\"View full run details\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n <div class=\"message-content\">\n <button class=\"copy-button-in-bubble\" (click)=\"copyMessage(message)\" title=\"Copy message\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (message.isStreaming) {\n <div class=\"streaming-wrapper\">\n <span class=\"streaming-content\">{{ message.streamingContent }}<span class=\"cursor\">|</span></span>\n </div>\n } @else {\n <div [innerHTML]=\"getFormattedContent(message)\"></div>\n }\n @if (message.error) {\n <div class=\"error-details\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ message.error }}\n </div>\n }\n @if (hasPayload(message.payload) && mode === 'agent' && message.role === 'assistant') {\n <div class=\"payload-section\" [class.collapsed]=\"message.payloadCollapsed\">\n <div class=\"payload-header\" (click)=\"togglePayloadCollapse(message)\">\n <span class=\"payload-label\">\n <i class=\"fa-solid fa-code\"></i> Payload\n </span>\n <button class=\"payload-toggle\" type=\"button\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!message.payloadCollapsed\" [class.fa-chevron-right]=\"message.payloadCollapsed\"></i>\n </button>\n </div>\n @if (!message.payloadCollapsed) {\n <div class=\"payload-content\">\n <pre>{{ formatJson(message.payload) }}</pre>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <textarea\n #messageInput\n class=\"mj-textarea message-input\"\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"></textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- Save Conversation Dialog -->\n@if (showSaveDialog) {\n <mj-dialog\n [Visible]=\"true\"\n [Width]=\"400\"\n (Close)=\"cancelSaveDialog()\"\n class=\"save-dialog\">\n <mj-dialog-titlebar>Save Conversation</mj-dialog-titlebar>\n <div class=\"dialog-content\">\n <p>Enter a name for this conversation:</p>\n <input\n #saveDialogInput\n type=\"text\"\n (keyup)=\"updateTempConversation()\"\n placeholder=\"Conversation name\"\n class=\"mj-input full-width\" />\n </div>\n <mj-dialog-actions>\n <button mjButton (click)=\"cancelSaveDialog()\">Cancel</button>\n <button mjButton\n variant=\"primary\"\n (click)=\"confirmSaveConversation()\"\n [disabled]=\"tempConversationName === ''\">\n Save\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Load Confirmation Dialog -->\n@if (showLoadConfirmDialog) {\n <mj-dialog\n [Visible]=\"true\"\n [Width]=\"400\"\n (Close)=\"cancelLoadConversation()\"\n class=\"confirm-dialog\">\n <mj-dialog-titlebar>Replace Current Conversation?</mj-dialog-titlebar>\n <div class=\"dialog-content\">\n <p>Loading this conversation will replace the current one. Any unsaved changes will be lost.</p>\n <p>Do you want to continue?</p>\n </div>\n <mj-dialog-actions>\n <button mjButton (click)=\"cancelLoadConversation()\">Cancel</button>\n <button mjButton\n variant=\"primary\"\n (click)=\"confirmLoadConversation()\">\n Load Conversation\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- JSON Viewer Window -->\n@if (showJsonWindow) {\n <mj-window\n [Visible]=\"true\"\n Title=\"Raw JSON Response\"\n [Width]=\"900\"\n [Height]=\"700\"\n [MinWidth]=\"600\"\n [MinHeight]=\"400\"\n [Draggable]=\"true\"\n [Resizable]=\"true\"\n (Close)=\"closeJsonWindow()\">\n <mj-json-viewer-window [jsonContent]=\"currentJsonContent\"></mj-json-viewer-window>\n </mj-window>\n}\n\n", styles: ["/* Container Styles */\n.harness-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-card);\n}\n\n/* Custom Button Styles */\n.custom-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.custom-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.custom-button:active:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.custom-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.custom-button.icon-only {\n padding: 6px 8px;\n}\n\n.custom-button i {\n font-size: 14px;\n}\n\n/* Send Button - Primary Style */\n.send-button {\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 4px;\n padding: 8px 16px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 44px;\n font-family: inherit;\n}\n\n.send-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button:active:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.send-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.send-button i {\n font-size: 16px;\n}\n\n/* Add Button */\n.add-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.add-button:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n/* Remove/Delete Buttons */\n.remove-button,\n.delete-button {\n background: transparent;\n border: none;\n color: var(--mj-status-error);\n padding: 4px 8px;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s;\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.remove-button:hover,\n.delete-button:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n color: var(--mj-color-error-600);\n}\n\n/* Copy Button in Message Bubble */\n.copy-button-in-bubble {\n position: absolute;\n top: 8px;\n right: 8px;\n background: transparent;\n border: none;\n padding: 6px;\n font-size: 14px;\n color: var(--mj-border-strong);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0;\n z-index: 10; /* Ensure it's above content */\n}\n\n.message-content:hover .copy-button-in-bubble {\n opacity: 1;\n}\n\n.copy-button-in-bubble:hover {\n background: rgba(0, 0, 0, 0.08);\n color: var(--mj-text-muted);\n}\n\n.copy-button-in-bubble i {\n font-size: 14px;\n}\n\n/* Model Settings Styles (Prompt Mode) */\n.model-settings {\n padding: 16px;\n}\n\n.setting-group {\n margin-bottom: 24px;\n}\n\n.setting-group label {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n}\n\n.model-selector,\n.vendor-selector {\n width: 100%;\n}\n\n.temperature-slider {\n width: 100%;\n margin-top: 8px;\n}\n\n.max-tokens-input {\n width: 100%;\n}\n\n.setting-help {\n margin-top: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* Checkbox Styles */\n.checkbox-label {\n display: flex;\n align-items: center;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 14px;\n cursor: pointer;\n}\n\n.skip-validation-checkbox {\n margin-right: 8px;\n cursor: pointer;\n width: 16px;\n height: 16px;\n}\n\n/* Header Styles */\n.harness-header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.agent-info {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.agent-details {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.agent-details i {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.agent-details .entity-logo {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n}\n\n.agent-details h3 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-details p {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n/* Body Layout */\n.harness-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n/* Chat Area */\n.chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n height: 100%;\n min-height: 0; /* Important for flexbox children */\n}\n\n/* Messages Container */\n.messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 500;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Message Styles */\n.message {\n margin-bottom: 20px;\n animation: fadeIn 0.3s ease-in;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-user {\n margin-left: auto;\n max-width: 70%;\n}\n\n.message-assistant {\n margin-right: auto;\n max-width: 70%;\n}\n\n.message-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 13px;\n}\n\n.message-role {\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.message-role i {\n font-size: 14px;\n}\n\n.message-role .message-role-logo {\n width: 16px;\n height: 16px;\n object-fit: cover;\n border-radius: 3px;\n display: inline-block;\n vertical-align: middle;\n}\n\n.message-user .message-role {\n color: var(--mj-brand-primary);\n}\n\n.message-assistant .message-role {\n color: var(--mj-brand-primary);\n}\n\n.message-time {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.execution-time {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.raw-toggle {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n}\n\n.raw-toggle:hover {\n background: rgba(0, 0, 0, 0.05);\n color: var(--mj-text-secondary);\n}\n\n.raw-toggle i {\n font-size: 12px;\n}\n\n/* Message content styles are now defined above in enhanced content formatting section */\n\n.message-user .message-content {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.message-assistant .message-content {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.message.streaming .message-content {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--mj-bg-surface));\n}\n\n.streaming-content {\n display: inline;\n}\n\n.streaming-wrapper {\n position: relative;\n}\n\n.streaming-wrapper .cursor {\n display: inline;\n margin-left: 2px;\n}\n\n.cursor {\n animation: blink 1s infinite;\n font-weight: 100;\n color: var(--mj-text-secondary);\n}\n\n@keyframes blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n.error-details {\n margin-top: 8px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n border-radius: 6px;\n color: var(--mj-color-error-600);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details i {\n color: var(--mj-status-error);\n}\n\n/* Payload Section Styles */\n.payload-section {\n margin-top: 12px;\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.payload-header {\n background: var(--mj-bg-surface-card);\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n transition: background-color 0.2s;\n}\n\n.payload-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.payload-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label i {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.payload-content {\n max-height: 250px;\n overflow: auto;\n background: var(--mj-bg-surface-card);\n}\n\n.payload-content pre {\n margin: 0;\n padding: 12px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n background: transparent;\n}\n\n.payload-toggle {\n background: transparent;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.payload-toggle:hover {\n color: var(--mj-text-secondary);\n}\n\n.payload-toggle i {\n font-size: 12px;\n}\n\n.payload-section.collapsed .payload-header {\n border-bottom: none;\n}\n\n/* Dialog styles */\n.save-dialog,\n.confirm-dialog {\n .dialog-content {\n padding: 20px;\n\n p {\n margin: 0 0 16px 0;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.5;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .full-width {\n width: 100%;\n }\n\n input.k-textbox {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n\n &:focus {\n outline: none;\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--mj-status-error) 25%, transparent);\n }\n }\n }\n}\n\n/* Enhanced content formatting styles */\n.markdown-content {\n line-height: 1.6;\n word-wrap: break-word;\n overflow-wrap: break-word;\n max-width: 100%;\n}\n\n/* Inline JSON editor styles */\n.inline-json-editor {\n margin: 8px 0;\n\n .json-editor-container {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 4px;\n overflow: hidden;\n position: relative;\n max-height: 400px;\n\n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 13px;\n line-height: 1.5;\n overflow: auto;\n height: 100%;\n background: transparent;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n }\n}\n\n.markdown-paragraph {\n margin: 8px 0;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.markdown-h1 {\n font-size: 1.5em;\n font-weight: 600;\n margin: 16px 0 8px 0;\n color: var(--mj-text-primary);\n border-bottom: 2px solid var(--mj-bg-surface-sunken);\n padding-bottom: 4px;\n}\n\n.markdown-h2 {\n font-size: 1.3em;\n font-weight: 600;\n margin: 14px 0 6px 0;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n padding-bottom: 2px;\n}\n\n.markdown-h3 {\n font-size: 1.1em;\n font-weight: 600;\n margin: 12px 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.code-block {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-bg-surface-sunken);\n border-radius: 6px;\n padding: 16px;\n margin: 12px 0;\n overflow-x: auto;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.5;\n color: var(--mj-text-primary);\n white-space: pre;\n word-wrap: normal;\n max-width: 100%;\n}\n\n.code-block code {\n background: none;\n border: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre;\n word-wrap: normal;\n}\n\n.language-json {\n color: var(--mj-status-error);\n}\n\n.inline-code {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 2px 6px;\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\n font-size: 0.9em;\n color: var(--mj-status-error);\n white-space: nowrap;\n}\n\n.markdown-list {\n margin: 8px 0;\n padding-left: 24px;\n}\n\n.markdown-list li {\n margin: 4px 0;\n line-height: 1.5;\n}\n\n.markdown-link {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: none;\n}\n\n/* Ensure proper text wrapping in message content */\n.message-content {\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n padding: 12px 40px 12px 16px; /* Extra right padding for copy button */\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n position: relative;\n overflow-wrap: break-word;\n hyphens: auto;\n max-width: 100%;\n overflow-x: hidden;\n}\n\n/* Enhanced JSON content display */\n.json-content-wrapper {\n margin: 8px 0;\n}\n\n.json-main-content {\n margin-bottom: 12px;\n}\n\n.json-raw-section {\n margin-top: 12px;\n}\n\n.json-toggle-button {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: inherit;\n}\n\n.json-toggle-button:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.json-toggle-button i {\n font-size: 12px;\n}\n\n/* Compact code block for JSON in collapsible sections */\n.json-raw-section .code-block {\n margin: 8px 0 0 0;\n font-size: 12px;\n max-height: 300px;\n overflow-y: auto;\n}\n\n/* Better mobile responsiveness for JSON content */\n@media (max-width: 768px) {\n .json-raw-section .code-block {\n font-size: 11px;\n max-height: 200px;\n }\n}\n\n/* JSON raw section styling - simplified since we use code editor in dialog */\n.json-raw-section {\n margin-top: 12px;\n}\n\n/* Input Area */\n.input-area {\n padding: 16px;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0; /* Prevent input area from shrinking */\n margin-top: auto; /* Push to bottom */\n}\n\n.input-container {\n display: flex;\n gap: 12px;\n align-items: center;\n}\n\n.rerun-mode-container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 8px;\n gap: 16px;\n}\n\n.rerun-message {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.rerun-message i {\n font-size: 16px;\n}\n\n.rerun-message strong {\n font-family: 'Fira Code', 'Consolas', monospace;\n}\n\n.rerun-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 100px;\n justify-content: center;\n}\n\n.rerun-button span {\n font-weight: 500;\n}\n\n.rerun-buttons {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.reset-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n min-width: 120px;\n justify-content: center;\n background-color: var(--mj-text-muted);\n}\n\n.reset-button:hover:not(:disabled) {\n background-color: var(--mj-text-secondary);\n}\n\n.reset-button span {\n font-weight: 500;\n}\n\n.message-input {\n flex: 1;\n}\n\n.message-input textarea {\n resize: none;\n font-size: 14px;\n}\n\n.send-button {\n margin-bottom: 1px;\n}\n\n/* Sidebar */\n.sidebar {\n width: 100%; /* Changed from fixed 360px to 100% */\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* Sidebar Tabs */\n.sidebar-tabs {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.tab-button {\n flex: 1;\n padding: 12px 8px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.tab-button:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.tab-button.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.tab-button i {\n font-size: 14px;\n}\n\n.tab-button .badge {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n margin-left: 4px;\n}\n\n.tab-button.active .badge {\n background: var(--mj-brand-primary);\n}\n\n.tab-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* Sidebar Content */\n.sidebar-content {\n flex: 1;\n overflow-y: auto;\n width: 100%; /* Ensure content takes full width */\n}\n\n.tab-content {\n padding: 20px;\n width: 100%; /* Ensure content takes full width */\n box-sizing: border-box; /* Include padding in width calculation */\n}\n\n.tab-header {\n margin-bottom: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.tab-header .custom-button.icon-only {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.tab-header h4 {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.tab-header p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.tab-header .custom-button.small {\n align-self: flex-start;\n padding: 6px 12px;\n font-size: 13px;\n}\n\n.tab-header .custom-button.small i {\n margin-right: 4px;\n}\n\n/* Variables */\n.variables-list {\n margin-bottom: 16px;\n width: 100%;\n}\n\n.variable-item {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n align-items: center;\n width: 100%;\n}\n\n.variable-name {\n width: 30%; /* Changed from fixed width to percentage */\n min-width: 100px;\n}\n\n.variable-type {\n width: 25%; /* Changed from fixed width to percentage */\n min-width: 80px;\n}\n\n.variable-value {\n flex: 1;\n min-width: 0; /* Allow flex item to shrink below content size */\n}\n\n.remove-button {\n width: 32px;\n height: 32px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.add-variable-button {\n width: 100%;\n}\n\n.empty-variables {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n/* Saved Conversations */\n.saved-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-saved {\n text-align: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-saved i {\n font-size: 36px;\n margin-bottom: 12px;\n opacity: 0.5;\n}\n\n.saved-item {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.saved-item:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-strong);\n}\n\n.saved-item.current {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.saved-info h5 {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.saved-info p {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.saved-date {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Responsive adjustments */\n@media (max-width: 1200px) {\n .sidebar {\n width: 320px;\n }\n}\n\n@media (max-width: 992px) {\n .message-user,\n .message-assistant {\n max-width: 85%;\n }\n\n .sidebar {\n width: 280px;\n }\n}\n\n/* Custom scrollbar */\n.messages-container::-webkit-scrollbar,\n.sidebar-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.messages-container::-webkit-scrollbar-track,\n.sidebar-content::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n}\n\n.messages-container::-webkit-scrollbar-thumb,\n.sidebar-content::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.messages-container::-webkit-scrollbar-thumb:hover,\n.sidebar-content::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Dialog customization */\n::ng-deep .ai-agent-test-harness .k-dialog-wrapper {\n border-radius: 8px;\n overflow: hidden;\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-titlebar {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-inverse);\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-title {\n font-weight: 600;\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-titlebar-actions .k-button {\n color: var(--mj-text-inverse);\n}\n\n::ng-deep .ai-agent-test-harness .k-dialog-content {\n padding: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n/* JSON Dialog Styles - removed since we're using WindowService */\n\n/* Advanced Parameters Styles */\n.advanced-params-panel {\n margin-top: 24px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n}\n\n.advanced-params-panel ::ng-deep .k-expander-title {\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.advanced-settings {\n padding: 16px;\n}\n\n.advanced-param-input {\n width: 100%;\n}\n\n.advanced-param-switch {\n margin-top: 8px;\n}\n\n/* Format selector dropdown */\n.format-selector {\n width: 100%;\n}\n"] }]
3872
+ }], () => [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }, { type: i2.Router }], { mode: [{
3901
3873
  type: Input
3902
3874
  }], entity: [{
3903
3875
  type: Input
@@ -3928,5 +3900,5 @@ export class AITestHarnessComponent {
3928
3900
  type: ViewChild,
3929
3901
  args: ['saveDialogInput']
3930
3902
  }] }); })();
3931
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber: 156 }); })();
3903
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber: 154 }); })();
3932
3904
  //# sourceMappingURL=ai-test-harness.component.js.map