@memberjunction/ng-ai-test-harness 5.42.0 → 5.44.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.
@@ -101,21 +101,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_2_Template(rf, ctx) {
101
101
  i0.ɵɵclassProp("fa-chevron-right", !ctx_r1.showSidebar)("fa-chevron-left", ctx_r1.showSidebar);
102
102
  } }
103
103
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
104
- i0.ɵɵelementStart(0, "div", 30);
105
- i0.ɵɵelement(1, "i", 44);
106
- i0.ɵɵelementStart(2, "h4");
107
- i0.ɵɵtext(3, "Start a conversation");
108
- i0.ɵɵelementEnd();
109
- i0.ɵɵelementStart(4, "p");
110
- i0.ɵɵtext(5, "Send a message to begin testing the AI agent");
111
- i0.ɵɵelementEnd()();
104
+ i0.ɵɵelement(0, "mj-empty-state", 30);
112
105
  } }
113
106
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
114
- i0.ɵɵelement(0, "i", 58);
107
+ i0.ɵɵelement(0, "i", 57);
115
108
  i0.ɵɵtext(1, " You ");
116
109
  } }
117
110
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_0_Template(rf, ctx) { if (rf & 1) {
118
- i0.ɵɵelement(0, "img", 59);
111
+ i0.ɵɵelement(0, "img", 58);
119
112
  } if (rf & 2) {
120
113
  const ctx_r1 = i0.ɵɵnextContext(5);
121
114
  i0.ɵɵproperty("src", ctx_r1.getEntityLogoURL(), i0.ɵɵsanitizeUrl)("alt", ctx_r1.getEntityName() + " logo");
@@ -127,7 +120,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_
127
120
  i0.ɵɵclassMap(ctx_r1.getEntityIconClass());
128
121
  } }
129
122
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Template(rf, ctx) { if (rf & 1) {
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);
123
+ i0.ɵɵconditionalCreate(0, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_0_Template, 1, 2, "img", 58)(1, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_Conditional_1_Template, 1, 2, "i", 15);
131
124
  i0.ɵɵtext(2);
132
125
  } if (rf & 2) {
133
126
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -136,8 +129,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_4_
136
129
  i0.ɵɵtextInterpolate1(" ", ctx_r1.getEntityName() || "Assistant", " ");
137
130
  } }
138
131
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_7_Template(rf, ctx) { if (rf & 1) {
139
- i0.ɵɵelementStart(0, "span", 48);
140
- i0.ɵɵelement(1, "i", 60);
132
+ i0.ɵɵelementStart(0, "span", 47);
133
+ i0.ɵɵelement(1, "i", 59);
141
134
  i0.ɵɵtext(2);
142
135
  i0.ɵɵelementEnd();
143
136
  } if (rf & 2) {
@@ -147,7 +140,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_7_
147
140
  i0.ɵɵtextInterpolate1(" ", ctx_r1.formatElapsedTime(message_r5.elapsedTime), " ");
148
141
  } }
149
142
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_8_Template(rf, ctx) { if (rf & 1) {
150
- i0.ɵɵelementStart(0, "span", 49);
143
+ i0.ɵɵelementStart(0, "span", 48);
151
144
  i0.ɵɵtext(1);
152
145
  i0.ɵɵelementEnd();
153
146
  } if (rf & 2) {
@@ -159,15 +152,15 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_8_
159
152
  } }
160
153
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_9_Template(rf, ctx) { if (rf & 1) {
161
154
  const _r6 = i0.ɵɵgetCurrentView();
162
- i0.ɵɵelementStart(0, "button", 61);
155
+ i0.ɵɵelementStart(0, "button", 60);
163
156
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const message_r5 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showRawJsonDialog(message_r5)); });
164
- i0.ɵɵelement(1, "i", 62);
157
+ i0.ɵɵelement(1, "i", 61);
165
158
  i0.ɵɵelementEnd();
166
159
  } }
167
160
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_13_Template(rf, ctx) { if (rf & 1) {
168
- i0.ɵɵelementStart(0, "div", 54);
169
- i0.ɵɵelement(1, "span", 63);
170
- i0.ɵɵelementStart(2, "span", 64);
161
+ i0.ɵɵelementStart(0, "div", 53);
162
+ i0.ɵɵelement(1, "span", 62);
163
+ i0.ɵɵelementStart(2, "span", 63);
171
164
  i0.ɵɵtext(3, "|");
172
165
  i0.ɵɵelementEnd()();
173
166
  } if (rf & 2) {
@@ -177,15 +170,15 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_13
177
170
  i0.ɵɵproperty("innerHTML", ctx_r1.getFormattedStreamingContent(message_r5), i0.ɵɵsanitizeHtml);
178
171
  } }
179
172
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_14_Template(rf, ctx) { if (rf & 1) {
180
- i0.ɵɵelement(0, "div", 55);
173
+ i0.ɵɵelement(0, "div", 54);
181
174
  } if (rf & 2) {
182
175
  const message_r5 = i0.ɵɵnextContext().$implicit;
183
176
  const ctx_r1 = i0.ɵɵnextContext(3);
184
177
  i0.ɵɵproperty("innerHTML", ctx_r1.getFormattedContent(message_r5), i0.ɵɵsanitizeHtml);
185
178
  } }
186
179
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_15_Template(rf, ctx) { if (rf & 1) {
187
- i0.ɵɵelementStart(0, "div", 56);
188
- i0.ɵɵelement(1, "i", 65);
180
+ i0.ɵɵelementStart(0, "div", 55);
181
+ i0.ɵɵelement(1, "i", 64);
189
182
  i0.ɵɵtext(2);
190
183
  i0.ɵɵelementEnd();
191
184
  } if (rf & 2) {
@@ -194,8 +187,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_15
194
187
  i0.ɵɵtextInterpolate1(" ", message_r5.error, " ");
195
188
  } }
196
189
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Conditional_7_Template(rf, ctx) { if (rf & 1) {
197
- i0.ɵɵelementStart(0, "div", 70);
198
- i0.ɵɵelement(1, "mj-code-editor", 71);
190
+ i0.ɵɵelementStart(0, "div", 69);
191
+ i0.ɵɵelement(1, "mj-code-editor", 70);
199
192
  i0.ɵɵelementEnd();
200
193
  } if (rf & 2) {
201
194
  const message_r5 = i0.ɵɵnextContext(2).$implicit;
@@ -205,16 +198,16 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16
205
198
  } }
206
199
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Template(rf, ctx) { if (rf & 1) {
207
200
  const _r7 = i0.ɵɵgetCurrentView();
208
- i0.ɵɵelementStart(0, "div", 66)(1, "div", 67);
201
+ i0.ɵɵelementStart(0, "div", 65)(1, "div", 66);
209
202
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r7); const message_r5 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.togglePayloadCollapse(message_r5)); });
210
- i0.ɵɵelementStart(2, "span", 68);
211
- i0.ɵɵelement(3, "i", 62);
203
+ i0.ɵɵelementStart(2, "span", 67);
204
+ i0.ɵɵelement(3, "i", 61);
212
205
  i0.ɵɵtext(4, " Payload ");
213
206
  i0.ɵɵelementEnd();
214
- i0.ɵɵelementStart(5, "button", 69);
207
+ i0.ɵɵelementStart(5, "button", 68);
215
208
  i0.ɵɵelement(6, "i", 27);
216
209
  i0.ɵɵelementEnd()();
217
- i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Conditional_7_Template, 2, 3, "div", 70);
210
+ i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Conditional_7_Template, 2, 3, "div", 69);
218
211
  i0.ɵɵelementEnd();
219
212
  } if (rf & 2) {
220
213
  const message_r5 = i0.ɵɵnextContext().$implicit;
@@ -226,22 +219,22 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16
226
219
  } }
227
220
  function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template(rf, ctx) { if (rf & 1) {
228
221
  const _r4 = i0.ɵɵgetCurrentView();
229
- i0.ɵɵelementStart(0, "div", 31)(1, "div", 45)(2, "span", 46);
222
+ i0.ɵɵelementStart(0, "div", 31)(1, "div", 44)(2, "span", 45);
230
223
  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);
231
224
  i0.ɵɵelementEnd();
232
- i0.ɵɵelementStart(5, "span", 47);
225
+ i0.ɵɵelementStart(5, "span", 46);
233
226
  i0.ɵɵtext(6);
234
227
  i0.ɵɵelementEnd();
235
- i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_7_Template, 3, 1, "span", 48)(8, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_8_Template, 2, 2, "span", 49);
236
- i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_9_Template, 2, 0, "button", 50);
228
+ i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_7_Template, 3, 1, "span", 47)(8, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_8_Template, 2, 2, "span", 48);
229
+ i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_9_Template, 2, 0, "button", 49);
237
230
  i0.ɵɵelementEnd();
238
- i0.ɵɵelementStart(10, "div", 51)(11, "button", 52);
231
+ i0.ɵɵelementStart(10, "div", 50)(11, "button", 51);
239
232
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template_button_click_11_listener() { const message_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.copyMessage(message_r5)); });
240
- i0.ɵɵelement(12, "i", 53);
233
+ i0.ɵɵelement(12, "i", 52);
241
234
  i0.ɵɵelementEnd();
242
- i0.ɵɵconditionalCreate(13, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_13_Template, 4, 1, "div", 54)(14, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_14_Template, 1, 1, "div", 55);
243
- i0.ɵɵconditionalCreate(15, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_15_Template, 3, 1, "div", 56);
244
- i0.ɵɵconditionalCreate(16, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Template, 8, 7, "div", 57);
235
+ i0.ɵɵconditionalCreate(13, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_13_Template, 4, 1, "div", 53)(14, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_14_Template, 1, 1, "div", 54);
236
+ i0.ɵɵconditionalCreate(15, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_15_Template, 3, 1, "div", 55);
237
+ i0.ɵɵconditionalCreate(16, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Conditional_16_Template, 8, 7, "div", 56);
245
238
  i0.ɵɵelementEnd()();
246
239
  } if (rf & 2) {
247
240
  const message_r5 = ctx.$implicit;
@@ -263,20 +256,20 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template(rf, c
263
256
  i0.ɵɵconditional(ctx_r1.hasPayload(message_r5.payload) && ctx_r1.mode === "agent" && message_r5.role === "assistant" ? 16 : -1);
264
257
  } }
265
258
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
266
- i0.ɵɵelement(0, "i", 60);
259
+ i0.ɵɵelement(0, "i", 59);
267
260
  i0.ɵɵelementStart(1, "span");
268
261
  i0.ɵɵtext(2, "Running...");
269
262
  i0.ɵɵelementEnd();
270
263
  } }
271
264
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
272
- i0.ɵɵelement(0, "i", 78);
265
+ i0.ɵɵelement(0, "i", 77);
273
266
  i0.ɵɵelementStart(1, "span");
274
267
  i0.ɵɵtext(2, "Re-Run");
275
268
  i0.ɵɵelementEnd();
276
269
  } }
277
270
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Template(rf, ctx) { if (rf & 1) {
278
271
  const _r8 = i0.ɵɵgetCurrentView();
279
- i0.ɵɵelementStart(0, "button", 77);
272
+ i0.ɵɵelementStart(0, "button", 76);
280
273
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.executeRerun()); });
281
274
  i0.ɵɵconditionalCreate(1, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Conditional_1_Template, 3, 0)(2, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Conditional_2_Template, 3, 0);
282
275
  i0.ɵɵelementEnd();
@@ -288,9 +281,9 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Condit
288
281
  } }
289
282
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_10_Template(rf, ctx) { if (rf & 1) {
290
283
  const _r9 = i0.ɵɵgetCurrentView();
291
- i0.ɵɵelementStart(0, "button", 79);
284
+ i0.ɵɵelementStart(0, "button", 78);
292
285
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.resetToOriginalMessages()); });
293
- i0.ɵɵelement(1, "i", 80);
286
+ i0.ɵɵelement(1, "i", 79);
294
287
  i0.ɵɵelementStart(2, "span");
295
288
  i0.ɵɵtext(3, "Reset Messages");
296
289
  i0.ɵɵelementEnd()();
@@ -299,8 +292,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Condit
299
292
  i0.ɵɵproperty("disabled", ctx_r1.isExecuting);
300
293
  } }
301
294
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Template(rf, ctx) { if (rf & 1) {
302
- i0.ɵɵelementStart(0, "div", 33)(1, "div", 72);
303
- i0.ɵɵelement(2, "i", 73);
295
+ i0.ɵɵelementStart(0, "div", 33)(1, "div", 71);
296
+ i0.ɵɵelement(2, "i", 72);
304
297
  i0.ɵɵelementStart(3, "span");
305
298
  i0.ɵɵtext(4, "Messages from Prompt Run ");
306
299
  i0.ɵɵelementStart(5, "strong");
@@ -308,8 +301,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Templa
308
301
  i0.ɵɵelementEnd();
309
302
  i0.ɵɵtext(7, " loaded above");
310
303
  i0.ɵɵelementEnd()();
311
- i0.ɵɵelementStart(8, "div", 74);
312
- i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Template, 3, 2, "button", 75)(10, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_10_Template, 4, 1, "button", 76);
304
+ i0.ɵɵelementStart(8, "div", 73);
305
+ i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_9_Template, 3, 2, "button", 74)(10, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Conditional_10_Template, 4, 1, "button", 75);
313
306
  i0.ɵɵelementEnd()();
314
307
  } if (rf & 2) {
315
308
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -319,20 +312,20 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_9_Templa
319
312
  i0.ɵɵconditional(!ctx_r1.hasExecutedRerun ? 9 : 10);
320
313
  } }
321
314
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
322
- i0.ɵɵelement(0, "i", 60);
315
+ i0.ɵɵelement(0, "i", 59);
323
316
  } }
324
317
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_5_Template(rf, ctx) { if (rf & 1) {
325
- i0.ɵɵelement(0, "i", 83);
318
+ i0.ɵɵelement(0, "i", 82);
326
319
  } }
327
320
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
328
321
  const _r10 = i0.ɵɵgetCurrentView();
329
- i0.ɵɵelementStart(0, "div", 34)(1, "textarea", 81, 2);
322
+ i0.ɵɵelementStart(0, "div", 34)(1, "textarea", 80, 2);
330
323
  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
324
  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)); });
332
325
  i0.ɵɵelementEnd();
333
- i0.ɵɵelementStart(3, "button", 82);
326
+ i0.ɵɵelementStart(3, "button", 81);
334
327
  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()); });
335
- i0.ɵɵconditionalCreate(4, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_4_Template, 1, 0, "i", 60)(5, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_5_Template, 1, 0, "i", 83);
328
+ i0.ɵɵconditionalCreate(4, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_4_Template, 1, 0, "i", 59)(5, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_10_Conditional_5_Template, 1, 0, "i", 82);
336
329
  i0.ɵɵelementEnd()();
337
330
  } if (rf & 2) {
338
331
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -348,17 +341,17 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Templ
348
341
  const _r11 = i0.ɵɵgetCurrentView();
349
342
  i0.ɵɵelementStart(0, "button", 37);
350
343
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("agentVariables")); });
351
- i0.ɵɵelement(1, "i", 62);
344
+ i0.ɵɵelement(1, "i", 61);
352
345
  i0.ɵɵtext(2, " Agent Variables ");
353
346
  i0.ɵɵelementEnd();
354
- i0.ɵɵelementStart(3, "button", 84);
347
+ i0.ɵɵelementStart(3, "button", 83);
355
348
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("executionMonitor")); });
356
- i0.ɵɵelement(4, "i", 85);
349
+ i0.ɵɵelement(4, "i", 84);
357
350
  i0.ɵɵtext(5, " Execution Monitor ");
358
351
  i0.ɵɵelementEnd();
359
352
  i0.ɵɵelementStart(6, "button", 37);
360
353
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("agentSettings")); });
361
- i0.ɵɵelement(7, "i", 86);
354
+ i0.ɵɵelement(7, "i", 85);
362
355
  i0.ɵɵtext(8, " Settings ");
363
356
  i0.ɵɵelementEnd();
364
357
  } if (rf & 2) {
@@ -373,14 +366,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_14_Templ
373
366
  } }
374
367
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_15_Template(rf, ctx) { if (rf & 1) {
375
368
  const _r12 = i0.ɵɵgetCurrentView();
376
- i0.ɵɵelementStart(0, "button", 84);
369
+ i0.ɵɵelementStart(0, "button", 83);
377
370
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_15_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("templateVariables")); });
378
- i0.ɵɵelement(1, "i", 62);
371
+ i0.ɵɵelement(1, "i", 61);
379
372
  i0.ɵɵtext(2, " Template Variables ");
380
373
  i0.ɵɵelementEnd();
381
- i0.ɵɵelementStart(3, "button", 84);
374
+ i0.ɵɵelementStart(3, "button", 83);
382
375
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_15_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("modelSettings")); });
383
- i0.ɵɵelement(4, "i", 86);
376
+ i0.ɵɵelement(4, "i", 85);
384
377
  i0.ɵɵtext(5, " Model Settings ");
385
378
  i0.ɵɵelementEnd();
386
379
  } if (rf & 2) {
@@ -399,24 +392,22 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_19_Templ
399
392
  i0.ɵɵtextInterpolate(ctx_r1.savedConversations.length);
400
393
  } }
401
394
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Conditional_7_Template(rf, ctx) { if (rf & 1) {
402
- i0.ɵɵelementStart(0, "div", 89)(1, "p");
403
- i0.ɵɵtext(2, "No variables defined. Click \"Add Variable\" to get started.");
404
- i0.ɵɵelementEnd()();
395
+ i0.ɵɵelement(0, "mj-empty-state", 88);
405
396
  } }
406
397
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template(rf, ctx) { if (rf & 1) {
407
398
  const _r14 = i0.ɵɵgetCurrentView();
408
- i0.ɵɵelementStart(0, "div", 90)(1, "input", 93);
399
+ i0.ɵɵelementStart(0, "div", 89)(1, "input", 92);
409
400
  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); });
410
401
  i0.ɵɵelementEnd();
411
- i0.ɵɵelementStart(2, "mj-dropdown", 94);
402
+ i0.ɵɵelementStart(2, "mj-dropdown", 93);
412
403
  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); });
413
404
  i0.ɵɵelementEnd();
414
- i0.ɵɵelementStart(3, "input", 95);
405
+ i0.ɵɵelementStart(3, "input", 94);
415
406
  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); });
416
407
  i0.ɵɵelementEnd();
417
- i0.ɵɵelementStart(4, "button", 96);
408
+ i0.ɵɵelementStart(4, "button", 95);
418
409
  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)); });
419
- i0.ɵɵelement(5, "i", 97);
410
+ i0.ɵɵelement(5, "i", 96);
420
411
  i0.ɵɵelementEnd()();
421
412
  } if (rf & 2) {
422
413
  const variable_r15 = ctx.$implicit;
@@ -435,19 +426,19 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9
435
426
  } }
436
427
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Template(rf, ctx) { if (rf & 1) {
437
428
  const _r13 = i0.ɵɵgetCurrentView();
438
- i0.ɵɵelementStart(0, "div", 41)(1, "div", 87)(2, "h4");
429
+ i0.ɵɵelementStart(0, "div", 41)(1, "div", 86)(2, "h4");
439
430
  i0.ɵɵtext(3, "Agent Variables");
440
431
  i0.ɵɵelementEnd();
441
432
  i0.ɵɵelementStart(4, "p");
442
433
  i0.ɵɵtext(5, "Variables available during agent execution and template rendering");
443
434
  i0.ɵɵelementEnd()();
444
- i0.ɵɵelementStart(6, "div", 88);
445
- i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Conditional_7_Template, 3, 0, "div", 89);
446
- i0.ɵɵrepeaterCreate(8, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template, 6, 19, "div", 90, i0.ɵɵrepeaterTrackByIndex);
435
+ i0.ɵɵelementStart(6, "div", 87);
436
+ i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Conditional_7_Template, 1, 0, "mj-empty-state", 88);
437
+ i0.ɵɵrepeaterCreate(8, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_For_9_Template, 6, 19, "div", 89, i0.ɵɵrepeaterTrackByIndex);
447
438
  i0.ɵɵelementEnd();
448
- i0.ɵɵelementStart(10, "button", 91);
439
+ i0.ɵɵelementStart(10, "button", 90);
449
440
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.addAgentVariable()); });
450
- i0.ɵɵelement(11, "i", 92);
441
+ i0.ɵɵelement(11, "i", 91);
451
442
  i0.ɵɵtext(12, " Add Variable ");
452
443
  i0.ɵɵelementEnd()();
453
444
  } if (rf & 2) {
@@ -461,7 +452,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_21_Templ
461
452
  } }
462
453
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_22_Template(rf, ctx) { if (rf & 1) {
463
454
  const _r17 = i0.ɵɵgetCurrentView();
464
- i0.ɵɵelementStart(0, "div", 42)(1, "mj-agent-execution-monitor", 98);
455
+ i0.ɵɵelementStart(0, "div", 42)(1, "mj-agent-execution-monitor", 97);
465
456
  i0.ɵɵlistener("viewRunClick", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_22_Template_mj_agent_execution_monitor_viewRunClick_1_listener($event) { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.navigateToAgentRun($event)); });
466
457
  i0.ɵɵelementEnd()();
467
458
  } if (rf & 2) {
@@ -493,19 +484,19 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Condi
493
484
  } }
494
485
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Template(rf, ctx) { if (rf & 1) {
495
486
  const _r18 = i0.ɵɵgetCurrentView();
496
- i0.ɵɵelementStart(0, "div", 41)(1, "div", 87)(2, "h4");
487
+ i0.ɵɵelementStart(0, "div", 41)(1, "div", 86)(2, "h4");
497
488
  i0.ɵɵtext(3, "Agent Settings");
498
489
  i0.ɵɵelementEnd();
499
490
  i0.ɵɵelementStart(4, "p");
500
491
  i0.ɵɵtext(5, "Configure agent execution parameters");
501
492
  i0.ɵɵelementEnd()();
502
- i0.ɵɵelementStart(6, "div", 99)(7, "div", 100)(8, "label");
493
+ i0.ɵɵelementStart(6, "div", 98)(7, "div", 99)(8, "label");
503
494
  i0.ɵɵtext(9, "AI Configuration");
504
495
  i0.ɵɵelementEnd();
505
- i0.ɵɵelementStart(10, "mj-dropdown", 101);
496
+ i0.ɵɵelementStart(10, "mj-dropdown", 100);
506
497
  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); });
507
498
  i0.ɵɵelementEnd();
508
- i0.ɵɵelementStart(11, "div", 102);
499
+ i0.ɵɵelementStart(11, "div", 101);
509
500
  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);
510
501
  i0.ɵɵelementEnd()()()();
511
502
  } if (rf & 2) {
@@ -518,18 +509,18 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_23_Templ
518
509
  } }
519
510
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template(rf, ctx) { if (rf & 1) {
520
511
  const _r21 = i0.ɵɵgetCurrentView();
521
- i0.ɵɵelementStart(0, "div", 90)(1, "input", 93);
512
+ i0.ɵɵelementStart(0, "div", 89)(1, "input", 92);
522
513
  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); });
523
514
  i0.ɵɵelementEnd();
524
- i0.ɵɵelementStart(2, "mj-dropdown", 94);
515
+ i0.ɵɵelementStart(2, "mj-dropdown", 93);
525
516
  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); });
526
517
  i0.ɵɵelementEnd();
527
- i0.ɵɵelementStart(3, "input", 95);
518
+ i0.ɵɵelementStart(3, "input", 94);
528
519
  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); });
529
520
  i0.ɵɵelementEnd();
530
- i0.ɵɵelementStart(4, "button", 104);
521
+ i0.ɵɵelementStart(4, "button", 103);
531
522
  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)); });
532
- i0.ɵɵelement(5, "i", 97);
523
+ i0.ɵɵelement(5, "i", 96);
533
524
  i0.ɵɵelementEnd()();
534
525
  } if (rf & 2) {
535
526
  const variable_r22 = ctx.$implicit;
@@ -546,18 +537,18 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8
546
537
  } }
547
538
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_Template(rf, ctx) { if (rf & 1) {
548
539
  const _r20 = i0.ɵɵgetCurrentView();
549
- i0.ɵɵelementStart(0, "div", 41)(1, "div", 87)(2, "h4");
540
+ i0.ɵɵelementStart(0, "div", 41)(1, "div", 86)(2, "h4");
550
541
  i0.ɵɵtext(3, "Template Variables");
551
542
  i0.ɵɵelementEnd();
552
543
  i0.ɵɵelementStart(4, "p");
553
544
  i0.ɵɵtext(5, "Variables for prompt template rendering");
554
545
  i0.ɵɵelementEnd()();
555
- i0.ɵɵelementStart(6, "div", 88);
556
- i0.ɵɵrepeaterCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template, 6, 18, "div", 90, i0.ɵɵrepeaterTrackByIndex);
546
+ i0.ɵɵelementStart(6, "div", 87);
547
+ i0.ɵɵrepeaterCreate(7, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_For_8_Template, 6, 18, "div", 89, i0.ɵɵrepeaterTrackByIndex);
557
548
  i0.ɵɵelementEnd();
558
- i0.ɵɵelementStart(9, "button", 103);
549
+ i0.ɵɵelementStart(9, "button", 102);
559
550
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_24_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.addTemplateVariable()); });
560
- i0.ɵɵelement(10, "i", 92);
551
+ i0.ɵɵelement(10, "i", 91);
561
552
  i0.ɵɵtext(11, " Add Variable ");
562
553
  i0.ɵɵelementEnd()();
563
554
  } if (rf & 2) {
@@ -598,10 +589,10 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Condi
598
589
  } }
599
590
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template(rf, ctx) { if (rf & 1) {
600
591
  const _r26 = i0.ɵɵgetCurrentView();
601
- i0.ɵɵelementStart(0, "div", 100)(1, "label", 128);
592
+ i0.ɵɵelementStart(0, "div", 99)(1, "label", 127);
602
593
  i0.ɵɵtext(2, " Top Log Probs ");
603
594
  i0.ɵɵelementEnd();
604
- i0.ɵɵelementStart(3, "mj-numeric-input", 129);
595
+ i0.ɵɵelementStart(3, "mj-numeric-input", 128);
605
596
  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); });
606
597
  i0.ɵɵelementEnd()();
607
598
  } if (rf & 2) {
@@ -612,126 +603,126 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Condi
612
603
  } }
613
604
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template(rf, ctx) { if (rf & 1) {
614
605
  const _r24 = i0.ɵɵgetCurrentView();
615
- i0.ɵɵelementStart(0, "div", 43)(1, "div", 87)(2, "h4");
606
+ i0.ɵɵelementStart(0, "div", 43)(1, "div", 86)(2, "h4");
616
607
  i0.ɵɵtext(3, "Model Settings");
617
608
  i0.ɵɵelementEnd();
618
609
  i0.ɵɵelementStart(4, "p");
619
610
  i0.ɵɵtext(5, "Configure AI model parameters");
620
611
  i0.ɵɵelementEnd();
621
- i0.ɵɵelementStart(6, "button", 105);
612
+ i0.ɵɵelementStart(6, "button", 104);
622
613
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.resetToPromptDefaults()); });
623
- i0.ɵɵelement(7, "i", 106);
614
+ i0.ɵɵelement(7, "i", 105);
624
615
  i0.ɵɵelementEnd()();
625
- i0.ɵɵelementStart(8, "div", 99)(9, "div", 100)(10, "label");
616
+ i0.ɵɵelementStart(8, "div", 98)(9, "div", 99)(10, "label");
626
617
  i0.ɵɵtext(11, "AI Model");
627
618
  i0.ɵɵelementEnd();
628
- i0.ɵɵelementStart(12, "mj-dropdown", 107);
619
+ i0.ɵɵelementStart(12, "mj-dropdown", 106);
629
620
  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
621
  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()); });
631
622
  i0.ɵɵelementEnd()();
632
- i0.ɵɵelementStart(13, "div", 100)(14, "label");
623
+ i0.ɵɵelementStart(13, "div", 99)(14, "label");
633
624
  i0.ɵɵtext(15, "AI Vendor");
634
625
  i0.ɵɵelementEnd();
635
- i0.ɵɵelementStart(16, "mj-dropdown", 108);
626
+ i0.ɵɵelementStart(16, "mj-dropdown", 107);
636
627
  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); });
637
628
  i0.ɵɵelementEnd();
638
- i0.ɵɵelementStart(17, "div", 102);
629
+ i0.ɵɵelementStart(17, "div", 101);
639
630
  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);
640
631
  i0.ɵɵelementEnd()();
641
- i0.ɵɵelementStart(21, "div", 100)(22, "label");
632
+ i0.ɵɵelementStart(21, "div", 99)(22, "label");
642
633
  i0.ɵɵtext(23, "AI Configuration");
643
634
  i0.ɵɵelementEnd();
644
- i0.ɵɵelementStart(24, "mj-dropdown", 101);
635
+ i0.ɵɵelementStart(24, "mj-dropdown", 100);
645
636
  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); });
646
637
  i0.ɵɵelementEnd();
647
- i0.ɵɵelementStart(25, "div", 102);
638
+ i0.ɵɵelementStart(25, "div", 101);
648
639
  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);
649
640
  i0.ɵɵelementEnd()();
650
- i0.ɵɵelementStart(28, "div", 100)(29, "label");
641
+ i0.ɵɵelementStart(28, "div", 99)(29, "label");
651
642
  i0.ɵɵtext(30, "Response Format");
652
643
  i0.ɵɵelementEnd();
653
- i0.ɵɵelementStart(31, "mj-dropdown", 109);
644
+ i0.ɵɵelementStart(31, "mj-dropdown", 108);
654
645
  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); });
655
646
  i0.ɵɵelementEnd();
656
- i0.ɵɵelementStart(32, "div", 102);
647
+ i0.ɵɵelementStart(32, "div", 101);
657
648
  i0.ɵɵtext(33, " Expected format for AI response (defaults to prompt setting) ");
658
649
  i0.ɵɵelementEnd()();
659
- i0.ɵɵelementStart(34, "div", 100)(35, "label");
650
+ i0.ɵɵelementStart(34, "div", 99)(35, "label");
660
651
  i0.ɵɵtext(36, "Max Tokens");
661
652
  i0.ɵɵelementEnd();
662
- i0.ɵɵelementStart(37, "mj-numeric-input", 110);
653
+ i0.ɵɵelementStart(37, "mj-numeric-input", 109);
663
654
  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); });
664
655
  i0.ɵɵelementEnd();
665
- i0.ɵɵelementStart(38, "div", 102);
656
+ i0.ɵɵelementStart(38, "div", 101);
666
657
  i0.ɵɵtext(39, " Maximum length of generated response ");
667
658
  i0.ɵɵelementEnd()();
668
- i0.ɵɵelementStart(40, "div", 100)(41, "label", 111)(42, "input", 112);
659
+ i0.ɵɵelementStart(40, "div", 99)(41, "label", 110)(42, "input", 111);
669
660
  i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Template_input_ngModelChange_42_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.skipValidation, $event) || (ctx_r1.skipValidation = $event); return i0.ɵɵresetView($event); });
670
661
  i0.ɵɵelementEnd();
671
662
  i0.ɵɵtext(43, " Skip Validation ");
672
663
  i0.ɵɵelementEnd();
673
- i0.ɵɵelementStart(44, "div", 102);
664
+ i0.ɵɵelementStart(44, "div", 101);
674
665
  i0.ɵɵtext(45, " Skip output validation during testing ");
675
666
  i0.ɵɵelementEnd()();
676
- i0.ɵɵelementStart(46, "mj-accordion-panel", 113)(47, "div", 114)(48, "div", 100)(49, "label", 115);
667
+ i0.ɵɵelementStart(46, "mj-accordion-panel", 112)(47, "div", 113)(48, "div", 99)(49, "label", 114);
677
668
  i0.ɵɵtext(50, " Temperature ");
678
669
  i0.ɵɵelementEnd();
679
- i0.ɵɵelementStart(51, "mj-numeric-input", 116);
670
+ i0.ɵɵelementStart(51, "mj-numeric-input", 115);
680
671
  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); });
681
672
  i0.ɵɵelementEnd()();
682
- i0.ɵɵelementStart(52, "div", 100)(53, "label", 117);
673
+ i0.ɵɵelementStart(52, "div", 99)(53, "label", 116);
683
674
  i0.ɵɵtext(54, " Top P ");
684
675
  i0.ɵɵelementEnd();
685
- i0.ɵɵelementStart(55, "mj-numeric-input", 116);
676
+ i0.ɵɵelementStart(55, "mj-numeric-input", 115);
686
677
  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); });
687
678
  i0.ɵɵelementEnd()();
688
- i0.ɵɵelementStart(56, "div", 100)(57, "label", 118);
679
+ i0.ɵɵelementStart(56, "div", 99)(57, "label", 117);
689
680
  i0.ɵɵtext(58, " Top K ");
690
681
  i0.ɵɵelementEnd();
691
- i0.ɵɵelementStart(59, "mj-numeric-input", 116);
682
+ i0.ɵɵelementStart(59, "mj-numeric-input", 115);
692
683
  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); });
693
684
  i0.ɵɵelementEnd()();
694
- i0.ɵɵelementStart(60, "div", 100)(61, "label", 119);
685
+ i0.ɵɵelementStart(60, "div", 99)(61, "label", 118);
695
686
  i0.ɵɵtext(62, " Min P ");
696
687
  i0.ɵɵelementEnd();
697
- i0.ɵɵelementStart(63, "mj-numeric-input", 116);
688
+ i0.ɵɵelementStart(63, "mj-numeric-input", 115);
698
689
  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); });
699
690
  i0.ɵɵelementEnd()();
700
- i0.ɵɵelementStart(64, "div", 100)(65, "label", 120);
691
+ i0.ɵɵelementStart(64, "div", 99)(65, "label", 119);
701
692
  i0.ɵɵtext(66, " Frequency Penalty ");
702
693
  i0.ɵɵelementEnd();
703
- i0.ɵɵelementStart(67, "mj-numeric-input", 116);
694
+ i0.ɵɵelementStart(67, "mj-numeric-input", 115);
704
695
  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); });
705
696
  i0.ɵɵelementEnd()();
706
- i0.ɵɵelementStart(68, "div", 100)(69, "label", 121);
697
+ i0.ɵɵelementStart(68, "div", 99)(69, "label", 120);
707
698
  i0.ɵɵtext(70, " Presence Penalty ");
708
699
  i0.ɵɵelementEnd();
709
- i0.ɵɵelementStart(71, "mj-numeric-input", 116);
700
+ i0.ɵɵelementStart(71, "mj-numeric-input", 115);
710
701
  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); });
711
702
  i0.ɵɵelementEnd()();
712
- i0.ɵɵelementStart(72, "div", 100)(73, "label", 122);
703
+ i0.ɵɵelementStart(72, "div", 99)(73, "label", 121);
713
704
  i0.ɵɵtext(74, " Seed ");
714
705
  i0.ɵɵelementEnd();
715
- i0.ɵɵelementStart(75, "mj-numeric-input", 123);
706
+ i0.ɵɵelementStart(75, "mj-numeric-input", 122);
716
707
  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); });
717
708
  i0.ɵɵelementEnd()();
718
- i0.ɵɵelementStart(76, "div", 100)(77, "label", 124);
709
+ i0.ɵɵelementStart(76, "div", 99)(77, "label", 123);
719
710
  i0.ɵɵtext(78, " Stop Sequences ");
720
711
  i0.ɵɵelementEnd();
721
- i0.ɵɵelementStart(79, "textarea", 125);
712
+ i0.ɵɵelementStart(79, "textarea", 124);
722
713
  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
714
  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()); });
724
715
  i0.ɵɵelementEnd();
725
- i0.ɵɵelementStart(80, "div", 102);
716
+ i0.ɵɵelementStart(80, "div", 101);
726
717
  i0.ɵɵtext(81, " Separate multiple sequences with commas ");
727
718
  i0.ɵɵelementEnd()();
728
- i0.ɵɵelementStart(82, "div", 100)(83, "label", 126);
719
+ i0.ɵɵelementStart(82, "div", 99)(83, "label", 125);
729
720
  i0.ɵɵtext(84, " Include Log Probs ");
730
721
  i0.ɵɵelementEnd();
731
- i0.ɵɵelementStart(85, "mj-switch", 127);
722
+ i0.ɵɵelementStart(85, "mj-switch", 126);
732
723
  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); });
733
724
  i0.ɵɵelementEnd()();
734
- i0.ɵɵconditionalCreate(86, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template, 4, 5, "div", 100);
725
+ i0.ɵɵconditionalCreate(86, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Conditional_86_Template, 4, 5, "div", 99);
735
726
  i0.ɵɵelementEnd()()()();
736
727
  } if (rf & 2) {
737
728
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -789,36 +780,32 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_25_Templ
789
780
  } }
790
781
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_6_Template(rf, ctx) { if (rf & 1) {
791
782
  const _r27 = i0.ɵɵgetCurrentView();
792
- i0.ɵɵelementStart(0, "button", 134);
783
+ i0.ɵɵelementStart(0, "button", 133);
793
784
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.newConversation()); });
794
- i0.ɵɵelement(1, "i", 92);
785
+ i0.ɵɵelement(1, "i", 91);
795
786
  i0.ɵɵtext(2, " New ");
796
787
  i0.ɵɵelementEnd();
797
788
  } }
798
789
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_8_Template(rf, ctx) { if (rf & 1) {
799
- i0.ɵɵelementStart(0, "div", 132);
800
- i0.ɵɵelement(1, "i", 135);
801
- i0.ɵɵelementStart(2, "p");
802
- i0.ɵɵtext(3, "No saved conversations");
803
- i0.ɵɵelementEnd()();
790
+ i0.ɵɵelement(0, "mj-empty-state", 131);
804
791
  } }
805
792
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_10_Template(rf, ctx) { if (rf & 1) {
806
793
  const _r28 = i0.ɵɵgetCurrentView();
807
- i0.ɵɵelementStart(0, "div", 136);
794
+ i0.ɵɵelementStart(0, "div", 134);
808
795
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_10_Template_div_click_0_listener() { const conv_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.loadConversation(conv_r29)); });
809
- i0.ɵɵelementStart(1, "div", 137)(2, "h5");
796
+ i0.ɵɵelementStart(1, "div", 135)(2, "h5");
810
797
  i0.ɵɵtext(3);
811
798
  i0.ɵɵelementEnd();
812
799
  i0.ɵɵelementStart(4, "p");
813
800
  i0.ɵɵtext(5);
814
801
  i0.ɵɵelementEnd();
815
- i0.ɵɵelementStart(6, "span", 138);
802
+ i0.ɵɵelementStart(6, "span", 136);
816
803
  i0.ɵɵtext(7);
817
804
  i0.ɵɵpipe(8, "date");
818
805
  i0.ɵɵelementEnd()();
819
- i0.ɵɵelementStart(9, "button", 139);
806
+ i0.ɵɵelementStart(9, "button", 137);
820
807
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_10_Template_button_click_9_listener($event) { const conv_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.deleteConversation(conv_r29, $event)); });
821
- i0.ɵɵelement(10, "i", 140);
808
+ i0.ɵɵelement(10, "i", 138);
822
809
  i0.ɵɵelementEnd()();
823
810
  } if (rf & 2) {
824
811
  const conv_r29 = ctx.$implicit;
@@ -832,17 +819,17 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_1
832
819
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(8, 5, conv_r29.updatedAt, "short"));
833
820
  } }
834
821
  function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Template(rf, ctx) { if (rf & 1) {
835
- i0.ɵɵelementStart(0, "div", 41)(1, "div", 87)(2, "h4");
822
+ i0.ɵɵelementStart(0, "div", 41)(1, "div", 86)(2, "h4");
836
823
  i0.ɵɵtext(3, "Saved Conversations");
837
824
  i0.ɵɵelementEnd();
838
825
  i0.ɵɵelementStart(4, "p");
839
826
  i0.ɵɵtext(5, "Previously saved test sessions");
840
827
  i0.ɵɵelementEnd();
841
- i0.ɵɵconditionalCreate(6, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_6_Template, 3, 0, "button", 130);
828
+ i0.ɵɵconditionalCreate(6, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_6_Template, 3, 0, "button", 129);
842
829
  i0.ɵɵelementEnd();
843
- i0.ɵɵelementStart(7, "div", 131);
844
- i0.ɵɵconditionalCreate(8, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_8_Template, 4, 0, "div", 132);
845
- i0.ɵɵrepeaterCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_10_Template, 11, 8, "div", 133, _forTrack0);
830
+ i0.ɵɵelementStart(7, "div", 130);
831
+ i0.ɵɵconditionalCreate(8, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Conditional_8_Template, 1, 0, "mj-empty-state", 131);
832
+ i0.ɵɵrepeaterCreate(9, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_For_10_Template, 11, 8, "div", 132, _forTrack0);
846
833
  i0.ɵɵelementEnd()();
847
834
  } if (rf & 2) {
848
835
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -856,7 +843,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_26_Templ
856
843
  function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
857
844
  const _r3 = i0.ɵɵgetCurrentView();
858
845
  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);
846
+ i0.ɵɵconditionalCreate(5, AITestHarnessComponent_Conditional_0_Conditional_4_Conditional_5_Template, 1, 0, "mj-empty-state", 30);
860
847
  i0.ɵɵrepeaterCreate(6, AITestHarnessComponent_Conditional_0_Conditional_4_For_7_Template, 17, 8, "div", 31, _forTrack0);
861
848
  i0.ɵɵelementEnd();
862
849
  i0.ɵɵelementStart(8, "div", 32);
@@ -911,21 +898,14 @@ function AITestHarnessComponent_Conditional_0_Conditional_4_Template(rf, ctx) {
911
898
  i0.ɵɵconditional(ctx_r1.activeTab === "savedConversations" ? 26 : -1);
912
899
  } }
913
900
  function AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
914
- i0.ɵɵelementStart(0, "div", 30);
915
- i0.ɵɵelement(1, "i", 44);
916
- i0.ɵɵelementStart(2, "h4");
917
- i0.ɵɵtext(3, "Start a conversation");
918
- i0.ɵɵelementEnd();
919
- i0.ɵɵelementStart(4, "p");
920
- i0.ɵɵtext(5, "Send a message to begin testing the AI agent");
921
- i0.ɵɵelementEnd()();
901
+ i0.ɵɵelement(0, "mj-empty-state", 30);
922
902
  } }
923
903
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
924
- i0.ɵɵelement(0, "i", 58);
904
+ i0.ɵɵelement(0, "i", 57);
925
905
  i0.ɵɵtext(1, " You ");
926
906
  } }
927
907
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
928
- i0.ɵɵelement(0, "i", 143);
908
+ i0.ɵɵelement(0, "i", 141);
929
909
  i0.ɵɵtext(1);
930
910
  } if (rf & 2) {
931
911
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -933,8 +913,8 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_4_
933
913
  i0.ɵɵtextInterpolate1(" ", ctx_r1.getEntityName() || "Assistant", " ");
934
914
  } }
935
915
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_7_Template(rf, ctx) { if (rf & 1) {
936
- i0.ɵɵelementStart(0, "span", 48);
937
- i0.ɵɵelement(1, "i", 60);
916
+ i0.ɵɵelementStart(0, "span", 47);
917
+ i0.ɵɵelement(1, "i", 59);
938
918
  i0.ɵɵtext(2);
939
919
  i0.ɵɵelementEnd();
940
920
  } if (rf & 2) {
@@ -944,7 +924,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_7_
944
924
  i0.ɵɵtextInterpolate1(" ", ctx_r1.formatElapsedTime(message_r32.elapsedTime), " ");
945
925
  } }
946
926
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_8_Template(rf, ctx) { if (rf & 1) {
947
- i0.ɵɵelementStart(0, "span", 49);
927
+ i0.ɵɵelementStart(0, "span", 48);
948
928
  i0.ɵɵtext(1);
949
929
  i0.ɵɵelementEnd();
950
930
  } if (rf & 2) {
@@ -956,29 +936,29 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_8_
956
936
  } }
957
937
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_9_Template(rf, ctx) { if (rf & 1) {
958
938
  const _r33 = i0.ɵɵgetCurrentView();
959
- i0.ɵɵelementStart(0, "button", 61);
939
+ i0.ɵɵelementStart(0, "button", 60);
960
940
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r33); const message_r32 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showRawJsonDialog(message_r32)); });
961
- i0.ɵɵelement(1, "i", 62);
941
+ i0.ɵɵelement(1, "i", 61);
962
942
  i0.ɵɵelementEnd();
963
943
  } }
964
944
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_10_Template(rf, ctx) { if (rf & 1) {
965
945
  const _r34 = i0.ɵɵgetCurrentView();
966
- i0.ɵɵelementStart(0, "button", 144);
946
+ i0.ɵɵelementStart(0, "button", 142);
967
947
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r34); const message_r32 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showMessageExecutionHistory(message_r32)); });
968
- i0.ɵɵelement(1, "i", 85);
948
+ i0.ɵɵelement(1, "i", 84);
969
949
  i0.ɵɵelementEnd();
970
950
  } }
971
951
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_11_Template(rf, ctx) { if (rf & 1) {
972
952
  const _r35 = i0.ɵɵgetCurrentView();
973
- i0.ɵɵelementStart(0, "button", 145);
953
+ i0.ɵɵelementStart(0, "button", 143);
974
954
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r35); const message_r32 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.navigateToAgentRun({ runId: message_r32.agentRunId, runType: "agent" })); });
975
- i0.ɵɵelement(1, "i", 146);
955
+ i0.ɵɵelement(1, "i", 144);
976
956
  i0.ɵɵelementEnd();
977
957
  } }
978
958
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_15_Template(rf, ctx) { if (rf & 1) {
979
- i0.ɵɵelementStart(0, "div", 54)(1, "span", 147);
959
+ i0.ɵɵelementStart(0, "div", 53)(1, "span", 145);
980
960
  i0.ɵɵtext(2);
981
- i0.ɵɵelementStart(3, "span", 64);
961
+ i0.ɵɵelementStart(3, "span", 63);
982
962
  i0.ɵɵtext(4, "|");
983
963
  i0.ɵɵelementEnd()()();
984
964
  } if (rf & 2) {
@@ -987,15 +967,15 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_15
987
967
  i0.ɵɵtextInterpolate(message_r32.streamingContent);
988
968
  } }
989
969
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_16_Template(rf, ctx) { if (rf & 1) {
990
- i0.ɵɵelement(0, "div", 55);
970
+ i0.ɵɵelement(0, "div", 54);
991
971
  } if (rf & 2) {
992
972
  const message_r32 = i0.ɵɵnextContext().$implicit;
993
973
  const ctx_r1 = i0.ɵɵnextContext(3);
994
974
  i0.ɵɵproperty("innerHTML", ctx_r1.getFormattedContent(message_r32), i0.ɵɵsanitizeHtml);
995
975
  } }
996
976
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_17_Template(rf, ctx) { if (rf & 1) {
997
- i0.ɵɵelementStart(0, "div", 56);
998
- i0.ɵɵelement(1, "i", 65);
977
+ i0.ɵɵelementStart(0, "div", 55);
978
+ i0.ɵɵelement(1, "i", 64);
999
979
  i0.ɵɵtext(2);
1000
980
  i0.ɵɵelementEnd();
1001
981
  } if (rf & 2) {
@@ -1004,7 +984,7 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_17
1004
984
  i0.ɵɵtextInterpolate1(" ", message_r32.error, " ");
1005
985
  } }
1006
986
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template(rf, ctx) { if (rf & 1) {
1007
- i0.ɵɵelementStart(0, "div", 70)(1, "pre");
987
+ i0.ɵɵelementStart(0, "div", 69)(1, "pre");
1008
988
  i0.ɵɵtext(2);
1009
989
  i0.ɵɵelementEnd()();
1010
990
  } if (rf & 2) {
@@ -1015,16 +995,16 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18
1015
995
  } }
1016
996
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Template(rf, ctx) { if (rf & 1) {
1017
997
  const _r36 = i0.ɵɵgetCurrentView();
1018
- i0.ɵɵelementStart(0, "div", 66)(1, "div", 67);
998
+ i0.ɵɵelementStart(0, "div", 65)(1, "div", 66);
1019
999
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r36); const message_r32 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.togglePayloadCollapse(message_r32)); });
1020
- i0.ɵɵelementStart(2, "span", 68);
1021
- i0.ɵɵelement(3, "i", 62);
1000
+ i0.ɵɵelementStart(2, "span", 67);
1001
+ i0.ɵɵelement(3, "i", 61);
1022
1002
  i0.ɵɵtext(4, " Payload ");
1023
1003
  i0.ɵɵelementEnd();
1024
- i0.ɵɵelementStart(5, "button", 69);
1004
+ i0.ɵɵelementStart(5, "button", 68);
1025
1005
  i0.ɵɵelement(6, "i", 27);
1026
1006
  i0.ɵɵelementEnd()();
1027
- i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template, 3, 1, "div", 70);
1007
+ i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template, 3, 1, "div", 69);
1028
1008
  i0.ɵɵelementEnd();
1029
1009
  } if (rf & 2) {
1030
1010
  const message_r32 = i0.ɵɵnextContext().$implicit;
@@ -1036,24 +1016,24 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18
1036
1016
  } }
1037
1017
  function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template(rf, ctx) { if (rf & 1) {
1038
1018
  const _r31 = i0.ɵɵgetCurrentView();
1039
- i0.ɵɵelementStart(0, "div", 31)(1, "div", 45)(2, "span", 46);
1019
+ i0.ɵɵelementStart(0, "div", 31)(1, "div", 44)(2, "span", 45);
1040
1020
  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);
1041
1021
  i0.ɵɵelementEnd();
1042
- i0.ɵɵelementStart(5, "span", 47);
1022
+ i0.ɵɵelementStart(5, "span", 46);
1043
1023
  i0.ɵɵtext(6);
1044
1024
  i0.ɵɵelementEnd();
1045
- i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_7_Template, 3, 1, "span", 48)(8, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_8_Template, 2, 2, "span", 49);
1046
- i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_9_Template, 2, 0, "button", 50);
1047
- i0.ɵɵconditionalCreate(10, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_10_Template, 2, 0, "button", 141);
1048
- i0.ɵɵconditionalCreate(11, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_11_Template, 2, 0, "button", 142);
1025
+ i0.ɵɵconditionalCreate(7, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_7_Template, 3, 1, "span", 47)(8, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_8_Template, 2, 2, "span", 48);
1026
+ i0.ɵɵconditionalCreate(9, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_9_Template, 2, 0, "button", 49);
1027
+ i0.ɵɵconditionalCreate(10, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_10_Template, 2, 0, "button", 139);
1028
+ i0.ɵɵconditionalCreate(11, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_11_Template, 2, 0, "button", 140);
1049
1029
  i0.ɵɵelementEnd();
1050
- i0.ɵɵelementStart(12, "div", 51)(13, "button", 52);
1030
+ i0.ɵɵelementStart(12, "div", 50)(13, "button", 51);
1051
1031
  i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template_button_click_13_listener() { const message_r32 = i0.ɵɵrestoreView(_r31).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.copyMessage(message_r32)); });
1052
- i0.ɵɵelement(14, "i", 53);
1032
+ i0.ɵɵelement(14, "i", 52);
1053
1033
  i0.ɵɵelementEnd();
1054
- i0.ɵɵconditionalCreate(15, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_15_Template, 5, 1, "div", 54)(16, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_16_Template, 1, 1, "div", 55);
1055
- i0.ɵɵconditionalCreate(17, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_17_Template, 3, 1, "div", 56);
1056
- i0.ɵɵconditionalCreate(18, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Template, 8, 7, "div", 57);
1034
+ i0.ɵɵconditionalCreate(15, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_15_Template, 5, 1, "div", 53)(16, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_16_Template, 1, 1, "div", 54);
1035
+ i0.ɵɵconditionalCreate(17, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_17_Template, 3, 1, "div", 55);
1036
+ i0.ɵɵconditionalCreate(18, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Conditional_18_Template, 8, 7, "div", 56);
1057
1037
  i0.ɵɵelementEnd()();
1058
1038
  } if (rf & 2) {
1059
1039
  const message_r32 = ctx.$implicit;
@@ -1079,24 +1059,24 @@ function AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template(rf, c
1079
1059
  i0.ɵɵconditional(ctx_r1.hasPayload(message_r32.payload) && ctx_r1.mode === "agent" && message_r32.role === "assistant" ? 18 : -1);
1080
1060
  } }
1081
1061
  function AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_11_Template(rf, ctx) { if (rf & 1) {
1082
- i0.ɵɵelement(0, "i", 60);
1062
+ i0.ɵɵelement(0, "i", 59);
1083
1063
  } }
1084
1064
  function AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_12_Template(rf, ctx) { if (rf & 1) {
1085
- i0.ɵɵelement(0, "i", 83);
1065
+ i0.ɵɵelement(0, "i", 82);
1086
1066
  } }
1087
1067
  function AITestHarnessComponent_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
1088
1068
  const _r30 = i0.ɵɵgetCurrentView();
1089
1069
  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);
1070
+ i0.ɵɵconditionalCreate(3, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_3_Template, 1, 0, "mj-empty-state", 30);
1091
1071
  i0.ɵɵrepeaterCreate(4, AITestHarnessComponent_Conditional_0_Conditional_5_For_5_Template, 19, 10, "div", 31, _forTrack0);
1092
1072
  i0.ɵɵelementEnd();
1093
- i0.ɵɵelementStart(6, "div", 32)(7, "div", 34)(8, "textarea", 81, 2);
1073
+ i0.ɵɵelementStart(6, "div", 32)(7, "div", 34)(8, "textarea", 80, 2);
1094
1074
  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
1075
  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)); });
1096
1076
  i0.ɵɵelementEnd();
1097
- i0.ɵɵelementStart(10, "button", 82);
1077
+ i0.ɵɵelementStart(10, "button", 81);
1098
1078
  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()); });
1099
- i0.ɵɵconditionalCreate(11, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_11_Template, 1, 0, "i", 60)(12, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_12_Template, 1, 0, "i", 83);
1079
+ i0.ɵɵconditionalCreate(11, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_11_Template, 1, 0, "i", 59)(12, AITestHarnessComponent_Conditional_0_Conditional_5_Conditional_12_Template, 1, 0, "i", 82);
1100
1080
  i0.ɵɵelementEnd()()()();
1101
1081
  } if (rf & 2) {
1102
1082
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -1128,22 +1108,22 @@ function AITestHarnessComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
1128
1108
  } }
1129
1109
  function AITestHarnessComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
1130
1110
  const _r37 = i0.ɵɵgetCurrentView();
1131
- i0.ɵɵelementStart(0, "mj-dialog", 148);
1111
+ i0.ɵɵelementStart(0, "mj-dialog", 146);
1132
1112
  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
1113
  i0.ɵɵelementStart(1, "mj-dialog-titlebar");
1134
1114
  i0.ɵɵtext(2, "Save Conversation");
1135
1115
  i0.ɵɵelementEnd();
1136
- i0.ɵɵelementStart(3, "div", 149)(4, "p");
1116
+ i0.ɵɵelementStart(3, "div", 147)(4, "p");
1137
1117
  i0.ɵɵtext(5, "Enter a name for this conversation:");
1138
1118
  i0.ɵɵelementEnd();
1139
- i0.ɵɵelementStart(6, "input", 150, 3);
1119
+ i0.ɵɵelementStart(6, "input", 148, 3);
1140
1120
  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()); });
1141
1121
  i0.ɵɵelementEnd()();
1142
- i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 151);
1122
+ i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 149);
1143
1123
  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
1124
  i0.ɵɵtext(10, "Cancel");
1145
1125
  i0.ɵɵelementEnd();
1146
- i0.ɵɵelementStart(11, "button", 152);
1126
+ i0.ɵɵelementStart(11, "button", 150);
1147
1127
  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
1128
  i0.ɵɵtext(12, " Save ");
1149
1129
  i0.ɵɵelementEnd()()();
@@ -1155,22 +1135,22 @@ function AITestHarnessComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
1155
1135
  } }
1156
1136
  function AITestHarnessComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1157
1137
  const _r38 = i0.ɵɵgetCurrentView();
1158
- i0.ɵɵelementStart(0, "mj-dialog", 153);
1138
+ i0.ɵɵelementStart(0, "mj-dialog", 151);
1159
1139
  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
1140
  i0.ɵɵelementStart(1, "mj-dialog-titlebar");
1161
1141
  i0.ɵɵtext(2, "Replace Current Conversation?");
1162
1142
  i0.ɵɵelementEnd();
1163
- i0.ɵɵelementStart(3, "div", 149)(4, "p");
1143
+ i0.ɵɵelementStart(3, "div", 147)(4, "p");
1164
1144
  i0.ɵɵtext(5, "Loading this conversation will replace the current one. Any unsaved changes will be lost.");
1165
1145
  i0.ɵɵelementEnd();
1166
1146
  i0.ɵɵelementStart(6, "p");
1167
1147
  i0.ɵɵtext(7, "Do you want to continue?");
1168
1148
  i0.ɵɵelementEnd()();
1169
- i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 151);
1149
+ i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 149);
1170
1150
  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
1151
  i0.ɵɵtext(10, "Cancel");
1172
1152
  i0.ɵɵelementEnd();
1173
- i0.ɵɵelementStart(11, "button", 154);
1153
+ i0.ɵɵelementStart(11, "button", 152);
1174
1154
  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
1155
  i0.ɵɵtext(12, " Load Conversation ");
1176
1156
  i0.ɵɵelementEnd()()();
@@ -1179,9 +1159,9 @@ function AITestHarnessComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1179
1159
  } }
1180
1160
  function AITestHarnessComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
1181
1161
  const _r39 = i0.ɵɵgetCurrentView();
1182
- i0.ɵɵelementStart(0, "mj-window", 155);
1162
+ i0.ɵɵelementStart(0, "mj-window", 153);
1183
1163
  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);
1164
+ i0.ɵɵelement(1, "mj-json-viewer-window", 154);
1185
1165
  i0.ɵɵelementEnd();
1186
1166
  } if (rf & 2) {
1187
1167
  const ctx_r1 = i0.ɵɵnextContext();
@@ -3851,7 +3831,7 @@ export class AITestHarnessComponent extends BaseAngularComponent {
3851
3831
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
3852
3832
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageInput = _t.first);
3853
3833
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.saveDialogInput = _t.first);
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.ɵɵInheritDefinitionFeature, 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) {
3834
+ } }, inputs: { mode: "mode", entity: "entity", originalPromptRunId: "originalPromptRunId", systemPromptOverride: "systemPromptOverride", aiAgent: "aiAgent", isVisible: "isVisible" }, outputs: { visibilityChange: "visibilityChange", runOpened: "runOpened", minimizeRequested: "minimizeRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, 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"], ["Icon", "fa-solid fa-comments", "Title", "Start a conversation", "Message", "Send a message to begin testing the AI agent"], [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, "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"], ["Icon", "fa-solid fa-code", "Title", "No variables defined", "Message", "Click \"Add Variable\" to get started.", "Size", "compact"], [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"], ["Icon", "fa-solid fa-folder-open", "Title", "No saved conversations", "Size", "compact"], [1, "saved-item", 3, "current"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary", 3, "click"], [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) {
3855
3835
  i0.ɵɵconditionalCreate(0, AITestHarnessComponent_Conditional_0_Template, 6, 2, "div", 4);
3856
3836
  i0.ɵɵconditionalCreate(1, AITestHarnessComponent_Conditional_1_Template, 13, 3, "mj-dialog", 5);
3857
3837
  i0.ɵɵconditionalCreate(2, AITestHarnessComponent_Conditional_2_Template, 13, 2, "mj-dialog", 6);
@@ -3864,11 +3844,11 @@ export class AITestHarnessComponent extends BaseAngularComponent {
3864
3844
  i0.ɵɵconditional(ctx.showLoadConfirmDialog ? 2 : -1);
3865
3845
  i0.ɵɵadvance();
3866
3846
  i0.ɵɵconditional(ctx.showJsonWindow ? 3 : -1);
3867
- } }, dependencies: [i2.NgClass, i3.DefaultValueAccessor, i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.MJWindowComponent, i4.MJButtonDirective, i4.MJDropdownComponent, i4.MJNumericInputComponent, i4.MJSwitchComponent, i4.MJAccordionPanelComponent, i4.MJDialogComponent, i4.MJDialogTitlebarComponent, i4.MJDialogActionsComponent, i5.SplitComponent, i5.SplitAreaComponent, i6.CodeEditorComponent, i7.JsonViewerWindowComponent, i8.AgentExecutionMonitorComponent, i2.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}"] }); }
3847
+ } }, dependencies: [i2.NgClass, i3.DefaultValueAccessor, i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.MJWindowComponent, i4.MJButtonDirective, i4.MJDropdownComponent, i4.MJNumericInputComponent, i4.MJSwitchComponent, i4.MJAccordionPanelComponent, i4.MJDialogComponent, i4.MJDialogTitlebarComponent, i4.MJDialogActionsComponent, i4.MJEmptyStateComponent, i5.SplitComponent, i5.SplitAreaComponent, i6.CodeEditorComponent, i7.JsonViewerWindowComponent, i8.AgentExecutionMonitorComponent, i2.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.messages-container[_ngcontent-%COMP%] mj-empty-state[_ngcontent-%COMP%] {\n height: 100%;\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\n\n.saved-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\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}"] }); }
3868
3848
  }
3869
3849
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AITestHarnessComponent, [{
3870
3850
  type: Component,
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"] }]
3851
+ 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 <mj-empty-state\n Icon=\"fa-solid fa-comments\"\n Title=\"Start a conversation\"\n Message=\"Send a message to begin testing the AI agent\" />\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 <mj-empty-state\n Icon=\"fa-solid fa-code\"\n Title=\"No variables defined\"\n Message=\"Click &quot;Add Variable&quot; to get started.\"\n Size=\"compact\" />\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 <mj-empty-state\n Icon=\"fa-solid fa-folder-open\"\n Title=\"No saved conversations\"\n Size=\"compact\" />\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 <mj-empty-state\n Icon=\"fa-solid fa-comments\"\n Title=\"Start a conversation\"\n Message=\"Send a message to begin testing the AI agent\" />\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.messages-container mj-empty-state {\n height: 100%;\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/* Saved Conversations */\n.saved-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\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
3852
  }], () => [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }], { mode: [{
3873
3853
  type: Input
3874
3854
  }], entity: [{