@memberjunction/ng-ai-test-harness 2.70.0 → 2.71.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.
|
@@ -22,6 +22,7 @@ const _c1 = ["fileInput"];
|
|
|
22
22
|
const _c2 = ["messageInput"];
|
|
23
23
|
const _c3 = ["saveDialogInput"];
|
|
24
24
|
const _forTrack0 = ($index, $item) => $item.id;
|
|
25
|
+
const _forTrack1 = ($index, $item) => $item.ID;
|
|
25
26
|
const _c4 = () => ({ text: "String", value: "string" });
|
|
26
27
|
const _c5 = () => ({ text: "Number", value: "number" });
|
|
27
28
|
const _c6 = () => ({ text: "Boolean", value: "boolean" });
|
|
@@ -278,12 +279,20 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_18_Template(rf,
|
|
|
278
279
|
i0.ɵɵelement(4, "i", 76);
|
|
279
280
|
i0.ɵɵtext(5, " Execution Monitor ");
|
|
280
281
|
i0.ɵɵelementEnd();
|
|
282
|
+
i0.ɵɵelementStart(6, "button", 41);
|
|
283
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_18_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectTab("agentSettings")); });
|
|
284
|
+
i0.ɵɵelement(7, "i", 77);
|
|
285
|
+
i0.ɵɵtext(8, " Settings ");
|
|
286
|
+
i0.ɵɵelementEnd();
|
|
281
287
|
} if (rf & 2) {
|
|
282
288
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
283
289
|
i0.ɵɵclassProp("active", ctx_r1.activeTab === "agentVariables");
|
|
284
290
|
i0.ɵɵproperty("disabled", ctx_r1.executionMonitorMode === "live" && ctx_r1.activeTab !== "agentVariables");
|
|
285
291
|
i0.ɵɵadvance(3);
|
|
286
292
|
i0.ɵɵclassProp("active", ctx_r1.activeTab === "executionMonitor");
|
|
293
|
+
i0.ɵɵadvance(3);
|
|
294
|
+
i0.ɵɵclassProp("active", ctx_r1.activeTab === "agentSettings");
|
|
295
|
+
i0.ɵɵproperty("disabled", ctx_r1.executionMonitorMode === "live" && ctx_r1.activeTab !== "agentSettings");
|
|
287
296
|
} }
|
|
288
297
|
function AITestHarnessComponent_div_0_Conditional_4_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
289
298
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
@@ -383,36 +392,83 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_26_Template(rf,
|
|
|
383
392
|
i0.ɵɵadvance();
|
|
384
393
|
i0.ɵɵproperty("mode", ctx_r1.executionMonitorMode)("agentRun", ctx_r1.currentAgentRun)("liveSteps", ctx_r1.liveAgentSteps)("autoExpand", true)("runId", ctx_r1.getLastRunId())("runType", ctx_r1.mode);
|
|
385
394
|
} }
|
|
386
|
-
function
|
|
387
|
-
|
|
395
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_For_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
396
|
+
i0.ɵɵtext(0);
|
|
397
|
+
} if (rf & 2) {
|
|
398
|
+
const config_r16 = i0.ɵɵnextContext().$implicit;
|
|
399
|
+
i0.ɵɵtextInterpolate1(" ", config_r16.Description, " ");
|
|
400
|
+
} }
|
|
401
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
402
|
+
i0.ɵɵtemplate(0, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_For_1_Conditional_0_Template, 1, 1);
|
|
403
|
+
} if (rf & 2) {
|
|
404
|
+
const config_r16 = ctx.$implicit;
|
|
405
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
406
|
+
i0.ɵɵconditional(config_r16.ID === ctx_r1.agentConfigurationId && config_r16.Description ? 0 : -1);
|
|
407
|
+
} }
|
|
408
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
409
|
+
i0.ɵɵrepeaterCreate(0, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_For_1_Template, 1, 1, null, null, _forTrack1);
|
|
410
|
+
} if (rf & 2) {
|
|
411
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
412
|
+
i0.ɵɵrepeater(ctx_r1.availableConfigurations);
|
|
413
|
+
} }
|
|
414
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
415
|
+
i0.ɵɵtext(0, " Using default configuration ");
|
|
416
|
+
} }
|
|
417
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
418
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
419
|
+
i0.ɵɵelementStart(0, "div", 45)(1, "div", 78)(2, "h4");
|
|
420
|
+
i0.ɵɵtext(3, "Agent Settings");
|
|
421
|
+
i0.ɵɵelementEnd();
|
|
422
|
+
i0.ɵɵelementStart(4, "p");
|
|
423
|
+
i0.ɵɵtext(5, "Configure agent execution parameters");
|
|
424
|
+
i0.ɵɵelementEnd()();
|
|
425
|
+
i0.ɵɵelementStart(6, "div", 90)(7, "div", 91)(8, "label");
|
|
426
|
+
i0.ɵɵtext(9, "AI Configuration");
|
|
427
|
+
i0.ɵɵelementEnd();
|
|
428
|
+
i0.ɵɵelementStart(10, "kendo-dropdownlist", 92);
|
|
429
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template_kendo_dropdownlist_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.agentConfigurationId, $event) || (ctx_r1.agentConfigurationId = $event); return i0.ɵɵresetView($event); });
|
|
430
|
+
i0.ɵɵelementEnd();
|
|
431
|
+
i0.ɵɵelementStart(11, "div", 93);
|
|
432
|
+
i0.ɵɵtemplate(12, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_12_Template, 2, 0)(13, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Conditional_13_Template, 1, 0);
|
|
433
|
+
i0.ɵɵelementEnd()()()();
|
|
434
|
+
} if (rf & 2) {
|
|
435
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
436
|
+
i0.ɵɵadvance(10);
|
|
437
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.agentConfigurationId);
|
|
438
|
+
i0.ɵɵproperty("data", ctx_r1.availableConfigurations)("valuePrimitive", true);
|
|
439
|
+
i0.ɵɵadvance(2);
|
|
440
|
+
i0.ɵɵconditional(ctx_r1.agentConfigurationId ? 12 : 13);
|
|
441
|
+
} }
|
|
442
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
443
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
388
444
|
i0.ɵɵelementStart(0, "div", 81)(1, "kendo-textbox", 84);
|
|
389
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
445
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template_kendo_textbox_ngModelChange_1_listener($event) { const variable_r19 = i0.ɵɵrestoreView(_r18).$implicit; i0.ɵɵtwoWayBindingSet(variable_r19.name, $event) || (variable_r19.name = $event); return i0.ɵɵresetView($event); });
|
|
390
446
|
i0.ɵɵelementEnd();
|
|
391
447
|
i0.ɵɵelementStart(2, "kendo-dropdownlist", 85);
|
|
392
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
448
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template_kendo_dropdownlist_ngModelChange_2_listener($event) { const variable_r19 = i0.ɵɵrestoreView(_r18).$implicit; i0.ɵɵtwoWayBindingSet(variable_r19.type, $event) || (variable_r19.type = $event); return i0.ɵɵresetView($event); });
|
|
393
449
|
i0.ɵɵelementEnd();
|
|
394
450
|
i0.ɵɵelementStart(3, "kendo-textbox", 86);
|
|
395
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
451
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template_kendo_textbox_ngModelChange_3_listener($event) { const variable_r19 = i0.ɵɵrestoreView(_r18).$implicit; i0.ɵɵtwoWayBindingSet(variable_r19.value, $event) || (variable_r19.value = $event); return i0.ɵɵresetView($event); });
|
|
396
452
|
i0.ɵɵelementEnd();
|
|
397
|
-
i0.ɵɵelementStart(4, "button",
|
|
398
|
-
i0.ɵɵlistener("click", function
|
|
453
|
+
i0.ɵɵelementStart(4, "button", 95);
|
|
454
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template_button_click_4_listener() { const $index_r20 = i0.ɵɵrestoreView(_r18).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.removeTemplateVariable($index_r20)); });
|
|
399
455
|
i0.ɵɵelement(5, "i", 88);
|
|
400
456
|
i0.ɵɵelementEnd()();
|
|
401
457
|
} if (rf & 2) {
|
|
402
|
-
const
|
|
458
|
+
const variable_r19 = ctx.$implicit;
|
|
403
459
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
404
460
|
i0.ɵɵadvance();
|
|
405
|
-
i0.ɵɵtwoWayProperty("ngModel",
|
|
461
|
+
i0.ɵɵtwoWayProperty("ngModel", variable_r19.name);
|
|
406
462
|
i0.ɵɵproperty("disabled", ctx_r1.isExecuting);
|
|
407
463
|
i0.ɵɵadvance();
|
|
408
|
-
i0.ɵɵtwoWayProperty("ngModel",
|
|
464
|
+
i0.ɵɵtwoWayProperty("ngModel", variable_r19.type);
|
|
409
465
|
i0.ɵɵproperty("data", i0.ɵɵpureFunction4(13, _c8, i0.ɵɵpureFunction0(9, _c4), i0.ɵɵpureFunction0(10, _c5), i0.ɵɵpureFunction0(11, _c6), i0.ɵɵpureFunction0(12, _c7)))("valuePrimitive", true)("disabled", ctx_r1.isExecuting);
|
|
410
466
|
i0.ɵɵadvance();
|
|
411
|
-
i0.ɵɵtwoWayProperty("ngModel",
|
|
412
|
-
i0.ɵɵproperty("placeholder",
|
|
467
|
+
i0.ɵɵtwoWayProperty("ngModel", variable_r19.value);
|
|
468
|
+
i0.ɵɵproperty("placeholder", variable_r19.type === "object" ? "JSON value" : "Value")("disabled", ctx_r1.isExecuting);
|
|
413
469
|
} }
|
|
414
|
-
function
|
|
415
|
-
const
|
|
470
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
471
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
416
472
|
i0.ɵɵelementStart(0, "div", 45)(1, "div", 78)(2, "h4");
|
|
417
473
|
i0.ɵɵtext(3, "Template Variables");
|
|
418
474
|
i0.ɵɵelementEnd();
|
|
@@ -420,10 +476,10 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template(rf,
|
|
|
420
476
|
i0.ɵɵtext(5, "Variables for prompt template rendering");
|
|
421
477
|
i0.ɵɵelementEnd()();
|
|
422
478
|
i0.ɵɵelementStart(6, "div", 79);
|
|
423
|
-
i0.ɵɵrepeaterCreate(7,
|
|
479
|
+
i0.ɵɵrepeaterCreate(7, AITestHarnessComponent_div_0_Conditional_4_Conditional_28_For_8_Template, 6, 18, "div", 81, i0.ɵɵrepeaterTrackByIndex);
|
|
424
480
|
i0.ɵɵelementEnd();
|
|
425
|
-
i0.ɵɵelementStart(9, "button",
|
|
426
|
-
i0.ɵɵlistener("click", function
|
|
481
|
+
i0.ɵɵelementStart(9, "button", 94);
|
|
482
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.addTemplateVariable()); });
|
|
427
483
|
i0.ɵɵelement(10, "i", 83);
|
|
428
484
|
i0.ɵɵtext(11, " Add Variable ");
|
|
429
485
|
i0.ɵɵelementEnd()();
|
|
@@ -432,22 +488,44 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template(rf,
|
|
|
432
488
|
i0.ɵɵadvance(7);
|
|
433
489
|
i0.ɵɵrepeater(ctx_r1.templateVariables);
|
|
434
490
|
} }
|
|
435
|
-
function
|
|
491
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
436
492
|
i0.ɵɵtext(0, " Using default vendor for the default model ");
|
|
437
493
|
} }
|
|
438
|
-
function
|
|
494
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
439
495
|
i0.ɵɵtext(0, " Only one vendor available for this model ");
|
|
440
496
|
} }
|
|
441
|
-
function
|
|
497
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
442
498
|
i0.ɵɵtext(0, " Select the inference provider for this model ");
|
|
443
499
|
} }
|
|
444
|
-
function
|
|
445
|
-
|
|
446
|
-
|
|
500
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_For_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
501
|
+
i0.ɵɵtext(0);
|
|
502
|
+
} if (rf & 2) {
|
|
503
|
+
const config_r22 = i0.ɵɵnextContext().$implicit;
|
|
504
|
+
i0.ɵɵtextInterpolate1(" ", config_r22.Description, " ");
|
|
505
|
+
} }
|
|
506
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
507
|
+
i0.ɵɵtemplate(0, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_For_1_Conditional_0_Template, 1, 1);
|
|
508
|
+
} if (rf & 2) {
|
|
509
|
+
const config_r22 = ctx.$implicit;
|
|
510
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
511
|
+
i0.ɵɵconditional(config_r22.ID === ctx_r1.selectedConfigurationId && config_r22.Description ? 0 : -1);
|
|
512
|
+
} }
|
|
513
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
514
|
+
i0.ɵɵrepeaterCreate(0, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_For_1_Template, 1, 1, null, null, _forTrack1);
|
|
515
|
+
} if (rf & 2) {
|
|
516
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
517
|
+
i0.ɵɵrepeater(ctx_r1.availableConfigurations);
|
|
518
|
+
} }
|
|
519
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
520
|
+
i0.ɵɵtext(0, " Using default configuration ");
|
|
521
|
+
} }
|
|
522
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_86_Template(rf, ctx) { if (rf & 1) {
|
|
523
|
+
const _r23 = i0.ɵɵgetCurrentView();
|
|
524
|
+
i0.ɵɵelementStart(0, "div", 91)(1, "label", 119);
|
|
447
525
|
i0.ɵɵtext(2, " Top Log Probs ");
|
|
448
526
|
i0.ɵɵelementEnd();
|
|
449
|
-
i0.ɵɵelementStart(3, "kendo-numerictextbox",
|
|
450
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
527
|
+
i0.ɵɵelementStart(3, "kendo-numerictextbox", 120);
|
|
528
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_86_Template_kendo_numerictextbox_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topLogProbs, $event) || (ctx_r1.advancedParams.topLogProbs = $event); return i0.ɵɵresetView($event); });
|
|
451
529
|
i0.ɵɵelementEnd()();
|
|
452
530
|
} if (rf & 2) {
|
|
453
531
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -455,121 +533,130 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Conditional_7
|
|
|
455
533
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.topLogProbs);
|
|
456
534
|
i0.ɵɵproperty("min", 2)("max", 20)("step", 1)("format", "n0");
|
|
457
535
|
} }
|
|
458
|
-
function
|
|
459
|
-
const
|
|
536
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
537
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
460
538
|
i0.ɵɵelementStart(0, "div", 47)(1, "div", 78)(2, "h4");
|
|
461
539
|
i0.ɵɵtext(3, "Model Settings");
|
|
462
540
|
i0.ɵɵelementEnd();
|
|
463
541
|
i0.ɵɵelementStart(4, "p");
|
|
464
542
|
i0.ɵɵtext(5, "Configure AI model parameters");
|
|
465
543
|
i0.ɵɵelementEnd();
|
|
466
|
-
i0.ɵɵelementStart(6, "button",
|
|
467
|
-
i0.ɵɵlistener("click", function
|
|
468
|
-
i0.ɵɵelement(7, "i",
|
|
544
|
+
i0.ɵɵelementStart(6, "button", 96);
|
|
545
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.resetToPromptDefaults()); });
|
|
546
|
+
i0.ɵɵelement(7, "i", 97);
|
|
469
547
|
i0.ɵɵelementEnd()();
|
|
470
|
-
i0.ɵɵelementStart(8, "div",
|
|
548
|
+
i0.ɵɵelementStart(8, "div", 90)(9, "div", 91)(10, "label");
|
|
471
549
|
i0.ɵɵtext(11, "AI Model");
|
|
472
550
|
i0.ɵɵelementEnd();
|
|
473
|
-
i0.ɵɵelementStart(12, "kendo-dropdownlist",
|
|
474
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
475
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
551
|
+
i0.ɵɵelementStart(12, "kendo-dropdownlist", 98);
|
|
552
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_dropdownlist_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedModelId, $event) || (ctx_r1.selectedModelId = $event); return i0.ɵɵresetView($event); });
|
|
553
|
+
i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_dropdownlist_ngModelChange_12_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onModelSelectionChange()); });
|
|
476
554
|
i0.ɵɵelementEnd()();
|
|
477
|
-
i0.ɵɵelementStart(13, "div",
|
|
555
|
+
i0.ɵɵelementStart(13, "div", 91)(14, "label");
|
|
478
556
|
i0.ɵɵtext(15, "AI Vendor");
|
|
479
557
|
i0.ɵɵelementEnd();
|
|
480
|
-
i0.ɵɵelementStart(16, "kendo-dropdownlist",
|
|
481
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
558
|
+
i0.ɵɵelementStart(16, "kendo-dropdownlist", 99);
|
|
559
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_dropdownlist_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedVendorId, $event) || (ctx_r1.selectedVendorId = $event); return i0.ɵɵresetView($event); });
|
|
560
|
+
i0.ɵɵelementEnd();
|
|
561
|
+
i0.ɵɵelementStart(17, "div", 93);
|
|
562
|
+
i0.ɵɵtemplate(18, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_18_Template, 1, 0)(19, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_19_Template, 1, 0)(20, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_20_Template, 1, 0);
|
|
563
|
+
i0.ɵɵelementEnd()();
|
|
564
|
+
i0.ɵɵelementStart(21, "div", 91)(22, "label");
|
|
565
|
+
i0.ɵɵtext(23, "AI Configuration");
|
|
566
|
+
i0.ɵɵelementEnd();
|
|
567
|
+
i0.ɵɵelementStart(24, "kendo-dropdownlist", 92);
|
|
568
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_dropdownlist_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedConfigurationId, $event) || (ctx_r1.selectedConfigurationId = $event); return i0.ɵɵresetView($event); });
|
|
482
569
|
i0.ɵɵelementEnd();
|
|
483
|
-
i0.ɵɵelementStart(
|
|
484
|
-
i0.ɵɵtemplate(
|
|
570
|
+
i0.ɵɵelementStart(25, "div", 93);
|
|
571
|
+
i0.ɵɵtemplate(26, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_26_Template, 2, 0)(27, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_27_Template, 1, 0);
|
|
485
572
|
i0.ɵɵelementEnd()();
|
|
486
|
-
i0.ɵɵelementStart(
|
|
487
|
-
i0.ɵɵtext(
|
|
573
|
+
i0.ɵɵelementStart(28, "div", 91)(29, "label");
|
|
574
|
+
i0.ɵɵtext(30, "Response Format");
|
|
488
575
|
i0.ɵɵelementEnd();
|
|
489
|
-
i0.ɵɵelementStart(
|
|
490
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
576
|
+
i0.ɵɵelementStart(31, "kendo-dropdownlist", 100);
|
|
577
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_dropdownlist_ngModelChange_31_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedResponseFormat, $event) || (ctx_r1.selectedResponseFormat = $event); return i0.ɵɵresetView($event); });
|
|
491
578
|
i0.ɵɵelementEnd();
|
|
492
|
-
i0.ɵɵelementStart(
|
|
493
|
-
i0.ɵɵtext(
|
|
579
|
+
i0.ɵɵelementStart(32, "div", 93);
|
|
580
|
+
i0.ɵɵtext(33, " Expected format for AI response (defaults to prompt setting) ");
|
|
494
581
|
i0.ɵɵelementEnd()();
|
|
495
|
-
i0.ɵɵelementStart(
|
|
496
|
-
i0.ɵɵtext(
|
|
582
|
+
i0.ɵɵelementStart(34, "div", 91)(35, "label");
|
|
583
|
+
i0.ɵɵtext(36, "Max Tokens");
|
|
497
584
|
i0.ɵɵelementEnd();
|
|
498
|
-
i0.ɵɵelementStart(
|
|
499
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
585
|
+
i0.ɵɵelementStart(37, "kendo-numerictextbox", 101);
|
|
586
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.maxTokens, $event) || (ctx_r1.maxTokens = $event); return i0.ɵɵresetView($event); });
|
|
500
587
|
i0.ɵɵelementEnd();
|
|
501
|
-
i0.ɵɵelementStart(
|
|
502
|
-
i0.ɵɵtext(
|
|
588
|
+
i0.ɵɵelementStart(38, "div", 93);
|
|
589
|
+
i0.ɵɵtext(39, " Maximum length of generated response ");
|
|
503
590
|
i0.ɵɵelementEnd()();
|
|
504
|
-
i0.ɵɵelementStart(
|
|
505
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
591
|
+
i0.ɵɵelementStart(40, "div", 91)(41, "label", 102)(42, "input", 103);
|
|
592
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_input_ngModelChange_42_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.skipValidation, $event) || (ctx_r1.skipValidation = $event); return i0.ɵɵresetView($event); });
|
|
506
593
|
i0.ɵɵelementEnd();
|
|
507
|
-
i0.ɵɵtext(
|
|
594
|
+
i0.ɵɵtext(43, " Skip Validation ");
|
|
508
595
|
i0.ɵɵelementEnd();
|
|
509
|
-
i0.ɵɵelementStart(
|
|
510
|
-
i0.ɵɵtext(
|
|
596
|
+
i0.ɵɵelementStart(44, "div", 93);
|
|
597
|
+
i0.ɵɵtext(45, " Skip output validation during testing ");
|
|
511
598
|
i0.ɵɵelementEnd()();
|
|
512
|
-
i0.ɵɵelementStart(
|
|
513
|
-
i0.ɵɵlistener("action", function
|
|
514
|
-
i0.ɵɵelementStart(
|
|
515
|
-
i0.ɵɵtext(
|
|
599
|
+
i0.ɵɵelementStart(46, "kendo-expansionpanel", 104);
|
|
600
|
+
i0.ɵɵlistener("action", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_expansionpanel_action_46_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleAdvancedParams()); });
|
|
601
|
+
i0.ɵɵelementStart(47, "div", 105)(48, "div", 91)(49, "label", 106);
|
|
602
|
+
i0.ɵɵtext(50, " Temperature ");
|
|
516
603
|
i0.ɵɵelementEnd();
|
|
517
|
-
i0.ɵɵelementStart(
|
|
518
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
604
|
+
i0.ɵɵelementStart(51, "kendo-numerictextbox", 107);
|
|
605
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_51_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.temperature, $event) || (ctx_r1.advancedParams.temperature = $event); return i0.ɵɵresetView($event); });
|
|
519
606
|
i0.ɵɵelementEnd()();
|
|
520
|
-
i0.ɵɵelementStart(
|
|
521
|
-
i0.ɵɵtext(
|
|
607
|
+
i0.ɵɵelementStart(52, "div", 91)(53, "label", 108);
|
|
608
|
+
i0.ɵɵtext(54, " Top P ");
|
|
522
609
|
i0.ɵɵelementEnd();
|
|
523
|
-
i0.ɵɵelementStart(
|
|
524
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
610
|
+
i0.ɵɵelementStart(55, "kendo-numerictextbox", 107);
|
|
611
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_55_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topP, $event) || (ctx_r1.advancedParams.topP = $event); return i0.ɵɵresetView($event); });
|
|
525
612
|
i0.ɵɵelementEnd()();
|
|
526
|
-
i0.ɵɵelementStart(
|
|
527
|
-
i0.ɵɵtext(
|
|
613
|
+
i0.ɵɵelementStart(56, "div", 91)(57, "label", 109);
|
|
614
|
+
i0.ɵɵtext(58, " Top K ");
|
|
528
615
|
i0.ɵɵelementEnd();
|
|
529
|
-
i0.ɵɵelementStart(
|
|
530
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
616
|
+
i0.ɵɵelementStart(59, "kendo-numerictextbox", 107);
|
|
617
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_59_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.topK, $event) || (ctx_r1.advancedParams.topK = $event); return i0.ɵɵresetView($event); });
|
|
531
618
|
i0.ɵɵelementEnd()();
|
|
532
|
-
i0.ɵɵelementStart(
|
|
533
|
-
i0.ɵɵtext(
|
|
619
|
+
i0.ɵɵelementStart(60, "div", 91)(61, "label", 110);
|
|
620
|
+
i0.ɵɵtext(62, " Min P ");
|
|
534
621
|
i0.ɵɵelementEnd();
|
|
535
|
-
i0.ɵɵelementStart(
|
|
536
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
622
|
+
i0.ɵɵelementStart(63, "kendo-numerictextbox", 107);
|
|
623
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_63_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.minP, $event) || (ctx_r1.advancedParams.minP = $event); return i0.ɵɵresetView($event); });
|
|
537
624
|
i0.ɵɵelementEnd()();
|
|
538
|
-
i0.ɵɵelementStart(
|
|
539
|
-
i0.ɵɵtext(
|
|
625
|
+
i0.ɵɵelementStart(64, "div", 91)(65, "label", 111);
|
|
626
|
+
i0.ɵɵtext(66, " Frequency Penalty ");
|
|
540
627
|
i0.ɵɵelementEnd();
|
|
541
|
-
i0.ɵɵelementStart(
|
|
542
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
628
|
+
i0.ɵɵelementStart(67, "kendo-numerictextbox", 107);
|
|
629
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_67_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.frequencyPenalty, $event) || (ctx_r1.advancedParams.frequencyPenalty = $event); return i0.ɵɵresetView($event); });
|
|
543
630
|
i0.ɵɵelementEnd()();
|
|
544
|
-
i0.ɵɵelementStart(
|
|
545
|
-
i0.ɵɵtext(
|
|
631
|
+
i0.ɵɵelementStart(68, "div", 91)(69, "label", 112);
|
|
632
|
+
i0.ɵɵtext(70, " Presence Penalty ");
|
|
546
633
|
i0.ɵɵelementEnd();
|
|
547
|
-
i0.ɵɵelementStart(
|
|
548
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
634
|
+
i0.ɵɵelementStart(71, "kendo-numerictextbox", 107);
|
|
635
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_71_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.presencePenalty, $event) || (ctx_r1.advancedParams.presencePenalty = $event); return i0.ɵɵresetView($event); });
|
|
549
636
|
i0.ɵɵelementEnd()();
|
|
550
|
-
i0.ɵɵelementStart(
|
|
551
|
-
i0.ɵɵtext(
|
|
637
|
+
i0.ɵɵelementStart(72, "div", 91)(73, "label", 113);
|
|
638
|
+
i0.ɵɵtext(74, " Seed ");
|
|
552
639
|
i0.ɵɵelementEnd();
|
|
553
|
-
i0.ɵɵelementStart(
|
|
554
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
640
|
+
i0.ɵɵelementStart(75, "kendo-numerictextbox", 114);
|
|
641
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_numerictextbox_ngModelChange_75_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.seed, $event) || (ctx_r1.advancedParams.seed = $event); return i0.ɵɵresetView($event); });
|
|
555
642
|
i0.ɵɵelementEnd()();
|
|
556
|
-
i0.ɵɵelementStart(
|
|
557
|
-
i0.ɵɵtext(
|
|
643
|
+
i0.ɵɵelementStart(76, "div", 91)(77, "label", 115);
|
|
644
|
+
i0.ɵɵtext(78, " Stop Sequences ");
|
|
558
645
|
i0.ɵɵelementEnd();
|
|
559
|
-
i0.ɵɵelementStart(
|
|
560
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
561
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
646
|
+
i0.ɵɵelementStart(79, "kendo-textarea", 116);
|
|
647
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_textarea_ngModelChange_79_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.stopSequencesText, $event) || (ctx_r1.stopSequencesText = $event); return i0.ɵɵresetView($event); });
|
|
648
|
+
i0.ɵɵlistener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_textarea_ngModelChange_79_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.updateStopSequences()); });
|
|
562
649
|
i0.ɵɵelementEnd();
|
|
563
|
-
i0.ɵɵelementStart(
|
|
564
|
-
i0.ɵɵtext(
|
|
650
|
+
i0.ɵɵelementStart(80, "div", 93);
|
|
651
|
+
i0.ɵɵtext(81, " Separate multiple sequences with commas ");
|
|
565
652
|
i0.ɵɵelementEnd()();
|
|
566
|
-
i0.ɵɵelementStart(
|
|
567
|
-
i0.ɵɵtext(
|
|
653
|
+
i0.ɵɵelementStart(82, "div", 91)(83, "label", 117);
|
|
654
|
+
i0.ɵɵtext(84, " Include Log Probs ");
|
|
568
655
|
i0.ɵɵelementEnd();
|
|
569
|
-
i0.ɵɵelementStart(
|
|
570
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
656
|
+
i0.ɵɵelementStart(85, "kendo-switch", 118);
|
|
657
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template_kendo_switch_ngModelChange_85_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.advancedParams.includeLogProbs, $event) || (ctx_r1.advancedParams.includeLogProbs = $event); return i0.ɵɵresetView($event); });
|
|
571
658
|
i0.ɵɵelementEnd()();
|
|
572
|
-
i0.ɵɵtemplate(
|
|
659
|
+
i0.ɵɵtemplate(86, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Conditional_86_Template, 4, 5, "div", 91);
|
|
573
660
|
i0.ɵɵelementEnd()()()();
|
|
574
661
|
} if (rf & 2) {
|
|
575
662
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -582,6 +669,11 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Template(rf,
|
|
|
582
669
|
i0.ɵɵadvance(2);
|
|
583
670
|
i0.ɵɵconditional(!ctx_r1.selectedModelId ? 18 : ctx_r1.availableVendors.length <= 1 ? 19 : 20);
|
|
584
671
|
i0.ɵɵadvance(6);
|
|
672
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedConfigurationId);
|
|
673
|
+
i0.ɵɵproperty("data", ctx_r1.availableConfigurations)("valuePrimitive", true);
|
|
674
|
+
i0.ɵɵadvance(2);
|
|
675
|
+
i0.ɵɵconditional(ctx_r1.selectedConfigurationId ? 26 : 27);
|
|
676
|
+
i0.ɵɵadvance(5);
|
|
585
677
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedResponseFormat);
|
|
586
678
|
i0.ɵɵproperty("data", ctx_r1.responseFormatOptions);
|
|
587
679
|
i0.ɵɵadvance(6);
|
|
@@ -618,64 +710,64 @@ function AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Template(rf,
|
|
|
618
710
|
i0.ɵɵadvance(6);
|
|
619
711
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.advancedParams.includeLogProbs);
|
|
620
712
|
i0.ɵɵadvance();
|
|
621
|
-
i0.ɵɵconditional(ctx_r1.advancedParams.includeLogProbs ?
|
|
713
|
+
i0.ɵɵconditional(ctx_r1.advancedParams.includeLogProbs ? 86 : -1);
|
|
622
714
|
} }
|
|
623
|
-
function
|
|
624
|
-
const
|
|
625
|
-
i0.ɵɵelementStart(0, "button",
|
|
626
|
-
i0.ɵɵlistener("click", function
|
|
715
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
716
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
717
|
+
i0.ɵɵelementStart(0, "button", 125);
|
|
718
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r24); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.newConversation()); });
|
|
627
719
|
i0.ɵɵelement(1, "i", 83);
|
|
628
720
|
i0.ɵɵtext(2, " New ");
|
|
629
721
|
i0.ɵɵelementEnd();
|
|
630
722
|
} }
|
|
631
|
-
function
|
|
632
|
-
i0.ɵɵelementStart(0, "div",
|
|
633
|
-
i0.ɵɵelement(1, "i",
|
|
723
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
724
|
+
i0.ɵɵelementStart(0, "div", 123);
|
|
725
|
+
i0.ɵɵelement(1, "i", 126);
|
|
634
726
|
i0.ɵɵelementStart(2, "p");
|
|
635
727
|
i0.ɵɵtext(3, "No saved conversations");
|
|
636
728
|
i0.ɵɵelementEnd()();
|
|
637
729
|
} }
|
|
638
|
-
function
|
|
639
|
-
const
|
|
640
|
-
i0.ɵɵelementStart(0, "div",
|
|
641
|
-
i0.ɵɵlistener("click", function
|
|
642
|
-
i0.ɵɵelementStart(1, "div",
|
|
730
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
731
|
+
const _r25 = i0.ɵɵgetCurrentView();
|
|
732
|
+
i0.ɵɵelementStart(0, "div", 127);
|
|
733
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_For_10_Template_div_click_0_listener() { const conv_r26 = i0.ɵɵrestoreView(_r25).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.loadConversation(conv_r26)); });
|
|
734
|
+
i0.ɵɵelementStart(1, "div", 128)(2, "h5");
|
|
643
735
|
i0.ɵɵtext(3);
|
|
644
736
|
i0.ɵɵelementEnd();
|
|
645
737
|
i0.ɵɵelementStart(4, "p");
|
|
646
738
|
i0.ɵɵtext(5);
|
|
647
739
|
i0.ɵɵelementEnd();
|
|
648
|
-
i0.ɵɵelementStart(6, "span",
|
|
740
|
+
i0.ɵɵelementStart(6, "span", 129);
|
|
649
741
|
i0.ɵɵtext(7);
|
|
650
742
|
i0.ɵɵpipe(8, "date");
|
|
651
743
|
i0.ɵɵelementEnd()();
|
|
652
|
-
i0.ɵɵelementStart(9, "button",
|
|
653
|
-
i0.ɵɵlistener("click", function
|
|
654
|
-
i0.ɵɵelement(10, "i",
|
|
744
|
+
i0.ɵɵelementStart(9, "button", 130);
|
|
745
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_For_10_Template_button_click_9_listener($event) { const conv_r26 = i0.ɵɵrestoreView(_r25).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.deleteConversation(conv_r26, $event)); });
|
|
746
|
+
i0.ɵɵelement(10, "i", 131);
|
|
655
747
|
i0.ɵɵelementEnd()();
|
|
656
748
|
} if (rf & 2) {
|
|
657
|
-
const
|
|
749
|
+
const conv_r26 = ctx.$implicit;
|
|
658
750
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
659
|
-
i0.ɵɵclassProp("current",
|
|
751
|
+
i0.ɵɵclassProp("current", conv_r26.id === ctx_r1.currentConversationId);
|
|
660
752
|
i0.ɵɵadvance(3);
|
|
661
|
-
i0.ɵɵtextInterpolate(
|
|
753
|
+
i0.ɵɵtextInterpolate(conv_r26.name);
|
|
662
754
|
i0.ɵɵadvance(2);
|
|
663
|
-
i0.ɵɵtextInterpolate1("",
|
|
755
|
+
i0.ɵɵtextInterpolate1("", conv_r26.messages.length, " messages");
|
|
664
756
|
i0.ɵɵadvance(2);
|
|
665
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(8, 5,
|
|
757
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(8, 5, conv_r26.updatedAt, "short"));
|
|
666
758
|
} }
|
|
667
|
-
function
|
|
759
|
+
function AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Template(rf, ctx) { if (rf & 1) {
|
|
668
760
|
i0.ɵɵelementStart(0, "div", 45)(1, "div", 78)(2, "h4");
|
|
669
761
|
i0.ɵɵtext(3, "Saved Conversations");
|
|
670
762
|
i0.ɵɵelementEnd();
|
|
671
763
|
i0.ɵɵelementStart(4, "p");
|
|
672
764
|
i0.ɵɵtext(5, "Previously saved test sessions");
|
|
673
765
|
i0.ɵɵelementEnd();
|
|
674
|
-
i0.ɵɵtemplate(6,
|
|
766
|
+
i0.ɵɵtemplate(6, AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Conditional_6_Template, 3, 0, "button", 121);
|
|
675
767
|
i0.ɵɵelementEnd();
|
|
676
|
-
i0.ɵɵelementStart(7, "div",
|
|
677
|
-
i0.ɵɵtemplate(8,
|
|
678
|
-
i0.ɵɵrepeaterCreate(9,
|
|
768
|
+
i0.ɵɵelementStart(7, "div", 122);
|
|
769
|
+
i0.ɵɵtemplate(8, AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Conditional_8_Template, 4, 0, "div", 123);
|
|
770
|
+
i0.ɵɵrepeaterCreate(9, AITestHarnessComponent_div_0_Conditional_4_Conditional_30_For_10_Template, 11, 8, "div", 124, _forTrack0);
|
|
679
771
|
i0.ɵɵelementEnd()();
|
|
680
772
|
} if (rf & 2) {
|
|
681
773
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -701,7 +793,7 @@ function AITestHarnessComponent_div_0_Conditional_4_Template(rf, ctx) { if (rf &
|
|
|
701
793
|
i0.ɵɵtemplate(13, AITestHarnessComponent_div_0_Conditional_4_Conditional_13_Template, 1, 0, "i", 36)(14, AITestHarnessComponent_div_0_Conditional_4_Conditional_14_Template, 1, 0, "i", 37);
|
|
702
794
|
i0.ɵɵelementEnd()()()()();
|
|
703
795
|
i0.ɵɵelementStart(15, "kendo-splitter-pane", 38)(16, "div", 39)(17, "div", 40);
|
|
704
|
-
i0.ɵɵtemplate(18, AITestHarnessComponent_div_0_Conditional_4_Conditional_18_Template,
|
|
796
|
+
i0.ɵɵtemplate(18, AITestHarnessComponent_div_0_Conditional_4_Conditional_18_Template, 9, 8)(19, AITestHarnessComponent_div_0_Conditional_4_Conditional_19_Template, 6, 4);
|
|
705
797
|
i0.ɵɵelementStart(20, "button", 41);
|
|
706
798
|
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_4_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.selectTab("savedConversations")); });
|
|
707
799
|
i0.ɵɵelement(21, "i", 42);
|
|
@@ -709,7 +801,7 @@ function AITestHarnessComponent_div_0_Conditional_4_Template(rf, ctx) { if (rf &
|
|
|
709
801
|
i0.ɵɵtemplate(23, AITestHarnessComponent_div_0_Conditional_4_Conditional_23_Template, 2, 1, "span", 43);
|
|
710
802
|
i0.ɵɵelementEnd()();
|
|
711
803
|
i0.ɵɵelementStart(24, "div", 44);
|
|
712
|
-
i0.ɵɵtemplate(25, AITestHarnessComponent_div_0_Conditional_4_Conditional_25_Template, 13, 2, "div", 45)(26, AITestHarnessComponent_div_0_Conditional_4_Conditional_26_Template, 2, 6, "div", 46)(27, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template,
|
|
804
|
+
i0.ɵɵtemplate(25, AITestHarnessComponent_div_0_Conditional_4_Conditional_25_Template, 13, 2, "div", 45)(26, AITestHarnessComponent_div_0_Conditional_4_Conditional_26_Template, 2, 6, "div", 46)(27, AITestHarnessComponent_div_0_Conditional_4_Conditional_27_Template, 14, 4, "div", 45)(28, AITestHarnessComponent_div_0_Conditional_4_Conditional_28_Template, 12, 0, "div", 45)(29, AITestHarnessComponent_div_0_Conditional_4_Conditional_29_Template, 87, 56, "div", 47)(30, AITestHarnessComponent_div_0_Conditional_4_Conditional_30_Template, 11, 2, "div", 45);
|
|
713
805
|
i0.ɵɵelementEnd()()()();
|
|
714
806
|
} if (rf & 2) {
|
|
715
807
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -740,11 +832,13 @@ function AITestHarnessComponent_div_0_Conditional_4_Template(rf, ctx) { if (rf &
|
|
|
740
832
|
i0.ɵɵadvance();
|
|
741
833
|
i0.ɵɵconditional(ctx_r1.activeTab === "executionMonitor" ? 26 : -1);
|
|
742
834
|
i0.ɵɵadvance();
|
|
743
|
-
i0.ɵɵconditional(ctx_r1.activeTab === "
|
|
835
|
+
i0.ɵɵconditional(ctx_r1.activeTab === "agentSettings" ? 27 : -1);
|
|
836
|
+
i0.ɵɵadvance();
|
|
837
|
+
i0.ɵɵconditional(ctx_r1.activeTab === "templateVariables" ? 28 : -1);
|
|
744
838
|
i0.ɵɵadvance();
|
|
745
|
-
i0.ɵɵconditional(ctx_r1.activeTab === "modelSettings" ?
|
|
839
|
+
i0.ɵɵconditional(ctx_r1.activeTab === "modelSettings" ? 29 : -1);
|
|
746
840
|
i0.ɵɵadvance();
|
|
747
|
-
i0.ɵɵconditional(ctx_r1.activeTab === "savedConversations" ?
|
|
841
|
+
i0.ɵɵconditional(ctx_r1.activeTab === "savedConversations" ? 30 : -1);
|
|
748
842
|
} }
|
|
749
843
|
function AITestHarnessComponent_div_0_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
750
844
|
i0.ɵɵelementStart(0, "div", 30);
|
|
@@ -761,7 +855,7 @@ function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_3_Template
|
|
|
761
855
|
i0.ɵɵtext(1, " You ");
|
|
762
856
|
} }
|
|
763
857
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
764
|
-
i0.ɵɵelement(0, "i",
|
|
858
|
+
i0.ɵɵelement(0, "i", 134);
|
|
765
859
|
i0.ɵɵtext(1);
|
|
766
860
|
} if (rf & 2) {
|
|
767
861
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
@@ -774,60 +868,60 @@ function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_7_Template
|
|
|
774
868
|
i0.ɵɵtext(2);
|
|
775
869
|
i0.ɵɵelementEnd();
|
|
776
870
|
} if (rf & 2) {
|
|
777
|
-
const
|
|
871
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
778
872
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
779
873
|
i0.ɵɵadvance(2);
|
|
780
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatElapsedTime(
|
|
874
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatElapsedTime(message_r29.elapsedTime), " ");
|
|
781
875
|
} }
|
|
782
876
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
783
877
|
i0.ɵɵelementStart(0, "span", 53);
|
|
784
878
|
i0.ɵɵtext(1);
|
|
785
879
|
i0.ɵɵelementEnd();
|
|
786
880
|
} if (rf & 2) {
|
|
787
|
-
const
|
|
881
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
788
882
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
789
|
-
i0.ɵɵproperty("title", ctx_r1.getExecutionSummary(
|
|
883
|
+
i0.ɵɵproperty("title", ctx_r1.getExecutionSummary(message_r29));
|
|
790
884
|
i0.ɵɵadvance();
|
|
791
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatExecutionTime(
|
|
885
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatExecutionTime(message_r29.executionTime));
|
|
792
886
|
} }
|
|
793
887
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
794
|
-
const
|
|
888
|
+
const _r30 = i0.ɵɵgetCurrentView();
|
|
795
889
|
i0.ɵɵelementStart(0, "button", 64);
|
|
796
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
890
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r30); const message_r29 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showRawJsonDialog(message_r29)); });
|
|
797
891
|
i0.ɵɵelement(1, "i", 65);
|
|
798
892
|
i0.ɵɵelementEnd();
|
|
799
893
|
} }
|
|
800
894
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
801
|
-
const
|
|
802
|
-
i0.ɵɵelementStart(0, "button",
|
|
803
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
895
|
+
const _r31 = i0.ɵɵgetCurrentView();
|
|
896
|
+
i0.ɵɵelementStart(0, "button", 135);
|
|
897
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r31); const message_r29 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.showMessageExecutionHistory(message_r29)); });
|
|
804
898
|
i0.ɵɵelement(1, "i", 76);
|
|
805
899
|
i0.ɵɵelementEnd();
|
|
806
900
|
} }
|
|
807
901
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
808
|
-
const
|
|
809
|
-
i0.ɵɵelementStart(0, "button",
|
|
810
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
811
|
-
i0.ɵɵelement(1, "i",
|
|
902
|
+
const _r32 = i0.ɵɵgetCurrentView();
|
|
903
|
+
i0.ɵɵelementStart(0, "button", 136);
|
|
904
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r32); const message_r29 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.navigateToAgentRun({ runId: message_r29.agentRunId, runType: "agent" })); });
|
|
905
|
+
i0.ɵɵelement(1, "i", 137);
|
|
812
906
|
i0.ɵɵelementEnd();
|
|
813
907
|
} }
|
|
814
908
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
815
|
-
i0.ɵɵelementStart(0, "div", 58)(1, "span",
|
|
909
|
+
i0.ɵɵelementStart(0, "div", 58)(1, "span", 138);
|
|
816
910
|
i0.ɵɵtext(2);
|
|
817
911
|
i0.ɵɵelementStart(3, "span", 67);
|
|
818
912
|
i0.ɵɵtext(4, "|");
|
|
819
913
|
i0.ɵɵelementEnd()()();
|
|
820
914
|
} if (rf & 2) {
|
|
821
|
-
const
|
|
915
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
822
916
|
i0.ɵɵadvance(2);
|
|
823
|
-
i0.ɵɵtextInterpolate(
|
|
917
|
+
i0.ɵɵtextInterpolate(message_r29.streamingContent);
|
|
824
918
|
} }
|
|
825
919
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
826
920
|
i0.ɵɵelement(0, "div", 59);
|
|
827
921
|
} if (rf & 2) {
|
|
828
|
-
const
|
|
922
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
829
923
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
830
|
-
i0.ɵɵproperty("innerHTML", ctx_r1.getFormattedContent(
|
|
924
|
+
i0.ɵɵproperty("innerHTML", ctx_r1.getFormattedContent(message_r29), i0.ɵɵsanitizeHtml);
|
|
831
925
|
} }
|
|
832
926
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
833
927
|
i0.ɵɵelementStart(0, "div", 60);
|
|
@@ -835,24 +929,24 @@ function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_17_Templat
|
|
|
835
929
|
i0.ɵɵtext(2);
|
|
836
930
|
i0.ɵɵelementEnd();
|
|
837
931
|
} if (rf & 2) {
|
|
838
|
-
const
|
|
932
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
839
933
|
i0.ɵɵadvance(2);
|
|
840
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
934
|
+
i0.ɵɵtextInterpolate1(" ", message_r29.error, " ");
|
|
841
935
|
} }
|
|
842
936
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
843
937
|
i0.ɵɵelementStart(0, "div", 73)(1, "pre");
|
|
844
938
|
i0.ɵɵtext(2);
|
|
845
939
|
i0.ɵɵelementEnd()();
|
|
846
940
|
} if (rf & 2) {
|
|
847
|
-
const
|
|
941
|
+
const message_r29 = i0.ɵɵnextContext(2).$implicit;
|
|
848
942
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
849
943
|
i0.ɵɵadvance(2);
|
|
850
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatJson(
|
|
944
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatJson(message_r29.payload));
|
|
851
945
|
} }
|
|
852
946
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
853
|
-
const
|
|
947
|
+
const _r33 = i0.ɵɵgetCurrentView();
|
|
854
948
|
i0.ɵɵelementStart(0, "div", 69)(1, "div", 70);
|
|
855
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Template_div_click_1_listener() { i0.ɵɵrestoreView(
|
|
949
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r33); const message_r29 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.togglePayloadCollapse(message_r29)); });
|
|
856
950
|
i0.ɵɵelementStart(2, "span", 71);
|
|
857
951
|
i0.ɵɵelement(3, "i", 65);
|
|
858
952
|
i0.ɵɵtext(4, " Payload ");
|
|
@@ -863,51 +957,51 @@ function AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Templat
|
|
|
863
957
|
i0.ɵɵtemplate(7, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Conditional_7_Template, 3, 1, "div", 73);
|
|
864
958
|
i0.ɵɵelementEnd();
|
|
865
959
|
} if (rf & 2) {
|
|
866
|
-
const
|
|
867
|
-
i0.ɵɵclassProp("collapsed",
|
|
960
|
+
const message_r29 = i0.ɵɵnextContext().$implicit;
|
|
961
|
+
i0.ɵɵclassProp("collapsed", message_r29.payloadCollapsed);
|
|
868
962
|
i0.ɵɵadvance(6);
|
|
869
|
-
i0.ɵɵclassProp("fa-chevron-down", !
|
|
963
|
+
i0.ɵɵclassProp("fa-chevron-down", !message_r29.payloadCollapsed)("fa-chevron-right", message_r29.payloadCollapsed);
|
|
870
964
|
i0.ɵɵadvance();
|
|
871
|
-
i0.ɵɵconditional(!
|
|
965
|
+
i0.ɵɵconditional(!message_r29.payloadCollapsed ? 7 : -1);
|
|
872
966
|
} }
|
|
873
967
|
function AITestHarnessComponent_div_0_Conditional_5_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
874
|
-
const
|
|
968
|
+
const _r28 = i0.ɵɵgetCurrentView();
|
|
875
969
|
i0.ɵɵelementStart(0, "div", 31)(1, "div", 49)(2, "span", 50);
|
|
876
970
|
i0.ɵɵtemplate(3, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_3_Template, 2, 0)(4, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_4_Template, 2, 1);
|
|
877
971
|
i0.ɵɵelementEnd();
|
|
878
972
|
i0.ɵɵelementStart(5, "span", 51);
|
|
879
973
|
i0.ɵɵtext(6);
|
|
880
974
|
i0.ɵɵelementEnd();
|
|
881
|
-
i0.ɵɵtemplate(7, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_7_Template, 3, 1, "span", 52)(8, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_8_Template, 2, 2, "span", 53)(9, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_9_Template, 2, 0, "button", 54)(10, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_10_Template, 2, 0, "button",
|
|
975
|
+
i0.ɵɵtemplate(7, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_7_Template, 3, 1, "span", 52)(8, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_8_Template, 2, 2, "span", 53)(9, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_9_Template, 2, 0, "button", 54)(10, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_10_Template, 2, 0, "button", 132)(11, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_11_Template, 2, 0, "button", 133);
|
|
882
976
|
i0.ɵɵelementEnd();
|
|
883
977
|
i0.ɵɵelementStart(12, "div", 55)(13, "button", 56);
|
|
884
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Template_button_click_13_listener() { const
|
|
978
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_For_5_Template_button_click_13_listener() { const message_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.copyMessage(message_r29)); });
|
|
885
979
|
i0.ɵɵelement(14, "i", 57);
|
|
886
980
|
i0.ɵɵelementEnd();
|
|
887
981
|
i0.ɵɵtemplate(15, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_15_Template, 5, 1, "div", 58)(16, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_16_Template, 1, 1, "div", 59)(17, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_17_Template, 3, 1, "div", 60)(18, AITestHarnessComponent_div_0_Conditional_5_For_5_Conditional_18_Template, 8, 7, "div", 61);
|
|
888
982
|
i0.ɵɵelementEnd()();
|
|
889
983
|
} if (rf & 2) {
|
|
890
|
-
const
|
|
984
|
+
const message_r29 = ctx.$implicit;
|
|
891
985
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
892
|
-
i0.ɵɵproperty("ngClass", ctx_r1.getMessageClass(
|
|
986
|
+
i0.ɵɵproperty("ngClass", ctx_r1.getMessageClass(message_r29));
|
|
893
987
|
i0.ɵɵadvance(3);
|
|
894
|
-
i0.ɵɵconditional(
|
|
988
|
+
i0.ɵɵconditional(message_r29.role === "user" ? 3 : 4);
|
|
895
989
|
i0.ɵɵadvance(3);
|
|
896
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatTimestamp(
|
|
990
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatTimestamp(message_r29.timestamp));
|
|
897
991
|
i0.ɵɵadvance();
|
|
898
|
-
i0.ɵɵconditional(
|
|
992
|
+
i0.ɵɵconditional(message_r29.isStreaming && message_r29.elapsedTime !== undefined ? 7 : message_r29.executionTime ? 8 : -1);
|
|
899
993
|
i0.ɵɵadvance(2);
|
|
900
|
-
i0.ɵɵconditional(ctx_r1.showRawToggle(
|
|
994
|
+
i0.ɵɵconditional(ctx_r1.showRawToggle(message_r29) ? 9 : -1);
|
|
901
995
|
i0.ɵɵadvance();
|
|
902
|
-
i0.ɵɵconditional(
|
|
996
|
+
i0.ɵɵconditional(message_r29.executionData && ctx_r1.mode === "agent" && message_r29.role === "assistant" ? 10 : -1);
|
|
903
997
|
i0.ɵɵadvance();
|
|
904
|
-
i0.ɵɵconditional(
|
|
998
|
+
i0.ɵɵconditional(message_r29.agentRunId && ctx_r1.mode === "agent" && message_r29.role === "assistant" ? 11 : -1);
|
|
905
999
|
i0.ɵɵadvance(4);
|
|
906
|
-
i0.ɵɵconditional(
|
|
1000
|
+
i0.ɵɵconditional(message_r29.isStreaming ? 15 : 16);
|
|
907
1001
|
i0.ɵɵadvance(2);
|
|
908
|
-
i0.ɵɵconditional(
|
|
1002
|
+
i0.ɵɵconditional(message_r29.error ? 17 : -1);
|
|
909
1003
|
i0.ɵɵadvance();
|
|
910
|
-
i0.ɵɵconditional(ctx_r1.hasPayload(
|
|
1004
|
+
i0.ɵɵconditional(ctx_r1.hasPayload(message_r29.payload) && ctx_r1.mode === "agent" && message_r29.role === "assistant" ? 18 : -1);
|
|
911
1005
|
} }
|
|
912
1006
|
function AITestHarnessComponent_div_0_Conditional_5_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
913
1007
|
i0.ɵɵelement(0, "i", 36);
|
|
@@ -916,17 +1010,17 @@ function AITestHarnessComponent_div_0_Conditional_5_Conditional_12_Template(rf,
|
|
|
916
1010
|
i0.ɵɵelement(0, "i", 37);
|
|
917
1011
|
} }
|
|
918
1012
|
function AITestHarnessComponent_div_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
919
|
-
const
|
|
1013
|
+
const _r27 = i0.ɵɵgetCurrentView();
|
|
920
1014
|
i0.ɵɵelementStart(0, "div", 12)(1, "div", 29, 1);
|
|
921
1015
|
i0.ɵɵtemplate(3, AITestHarnessComponent_div_0_Conditional_5_Conditional_3_Template, 6, 0, "div", 30);
|
|
922
1016
|
i0.ɵɵrepeaterCreate(4, AITestHarnessComponent_div_0_Conditional_5_For_5_Template, 19, 10, "div", 31, _forTrack0);
|
|
923
1017
|
i0.ɵɵelementEnd();
|
|
924
1018
|
i0.ɵɵelementStart(6, "div", 32)(7, "div", 33)(8, "kendo-textarea", 34, 2);
|
|
925
|
-
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_5_Template_kendo_textarea_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(
|
|
926
|
-
i0.ɵɵlistener("keypress", function AITestHarnessComponent_div_0_Conditional_5_Template_kendo_textarea_keypress_8_listener($event) { i0.ɵɵrestoreView(
|
|
1019
|
+
i0.ɵɵtwoWayListener("ngModelChange", function AITestHarnessComponent_div_0_Conditional_5_Template_kendo_textarea_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.currentUserMessage, $event) || (ctx_r1.currentUserMessage = $event); return i0.ɵɵresetView($event); });
|
|
1020
|
+
i0.ɵɵlistener("keypress", function AITestHarnessComponent_div_0_Conditional_5_Template_kendo_textarea_keypress_8_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.handleKeyPress($event)); });
|
|
927
1021
|
i0.ɵɵelementEnd();
|
|
928
1022
|
i0.ɵɵelementStart(10, "button", 35);
|
|
929
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_Template_button_click_10_listener() { i0.ɵɵrestoreView(
|
|
1023
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_div_0_Conditional_5_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r27); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.sendMessage()); });
|
|
930
1024
|
i0.ɵɵtemplate(11, AITestHarnessComponent_div_0_Conditional_5_Conditional_11_Template, 1, 0, "i", 36)(12, AITestHarnessComponent_div_0_Conditional_5_Conditional_12_Template, 1, 0, "i", 37);
|
|
931
1025
|
i0.ɵɵelementEnd()()()();
|
|
932
1026
|
} if (rf & 2) {
|
|
@@ -948,7 +1042,7 @@ function AITestHarnessComponent_div_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
948
1042
|
i0.ɵɵtemplate(2, AITestHarnessComponent_div_0_Conditional_2_Template, 25, 10, "div", 9);
|
|
949
1043
|
i0.ɵɵelementEnd();
|
|
950
1044
|
i0.ɵɵelementStart(3, "div", 10);
|
|
951
|
-
i0.ɵɵtemplate(4, AITestHarnessComponent_div_0_Conditional_4_Template,
|
|
1045
|
+
i0.ɵɵtemplate(4, AITestHarnessComponent_div_0_Conditional_4_Template, 31, 24, "kendo-splitter", 11)(5, AITestHarnessComponent_div_0_Conditional_5_Template, 13, 6, "div", 12);
|
|
952
1046
|
i0.ɵɵelementEnd()();
|
|
953
1047
|
} if (rf & 2) {
|
|
954
1048
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -958,21 +1052,21 @@ function AITestHarnessComponent_div_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
958
1052
|
i0.ɵɵconditional(ctx_r1.showSidebar ? 4 : 5);
|
|
959
1053
|
} }
|
|
960
1054
|
function AITestHarnessComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
961
|
-
const
|
|
962
|
-
i0.ɵɵelementStart(0, "kendo-dialog",
|
|
963
|
-
i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_1_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(
|
|
964
|
-
i0.ɵɵelementStart(1, "div",
|
|
1055
|
+
const _r34 = i0.ɵɵgetCurrentView();
|
|
1056
|
+
i0.ɵɵelementStart(0, "kendo-dialog", 139);
|
|
1057
|
+
i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_1_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
|
|
1058
|
+
i0.ɵɵelementStart(1, "div", 140)(2, "p");
|
|
965
1059
|
i0.ɵɵtext(3, "Enter a name for this conversation:");
|
|
966
1060
|
i0.ɵɵelementEnd();
|
|
967
|
-
i0.ɵɵelementStart(4, "input",
|
|
968
|
-
i0.ɵɵlistener("keyup", function AITestHarnessComponent_Conditional_1_Template_input_keyup_4_listener() { i0.ɵɵrestoreView(
|
|
1061
|
+
i0.ɵɵelementStart(4, "input", 141, 3);
|
|
1062
|
+
i0.ɵɵlistener("keyup", function AITestHarnessComponent_Conditional_1_Template_input_keyup_4_listener() { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.updateTempConversation()); });
|
|
969
1063
|
i0.ɵɵelementEnd()();
|
|
970
|
-
i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button",
|
|
971
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_7_listener() { i0.ɵɵrestoreView(
|
|
1064
|
+
i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button", 142);
|
|
1065
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelSaveDialog()); });
|
|
972
1066
|
i0.ɵɵtext(8, "Cancel");
|
|
973
1067
|
i0.ɵɵelementEnd();
|
|
974
|
-
i0.ɵɵelementStart(9, "button",
|
|
975
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(
|
|
1068
|
+
i0.ɵɵelementStart(9, "button", 143);
|
|
1069
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmSaveConversation()); });
|
|
976
1070
|
i0.ɵɵtext(10, " Save ");
|
|
977
1071
|
i0.ɵɵelementEnd()()();
|
|
978
1072
|
} if (rf & 2) {
|
|
@@ -982,21 +1076,21 @@ function AITestHarnessComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
982
1076
|
i0.ɵɵproperty("primary", true)("disabled", ctx_r1.tempConversationName === "");
|
|
983
1077
|
} }
|
|
984
1078
|
function AITestHarnessComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
985
|
-
const
|
|
986
|
-
i0.ɵɵelementStart(0, "kendo-dialog",
|
|
987
|
-
i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_2_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(
|
|
988
|
-
i0.ɵɵelementStart(1, "div",
|
|
1079
|
+
const _r35 = i0.ɵɵgetCurrentView();
|
|
1080
|
+
i0.ɵɵelementStart(0, "kendo-dialog", 144);
|
|
1081
|
+
i0.ɵɵlistener("close", function AITestHarnessComponent_Conditional_2_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r35); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
|
|
1082
|
+
i0.ɵɵelementStart(1, "div", 140)(2, "p");
|
|
989
1083
|
i0.ɵɵtext(3, "Loading this conversation will replace the current one. Any unsaved changes will be lost.");
|
|
990
1084
|
i0.ɵɵelementEnd();
|
|
991
1085
|
i0.ɵɵelementStart(4, "p");
|
|
992
1086
|
i0.ɵɵtext(5, "Do you want to continue?");
|
|
993
1087
|
i0.ɵɵelementEnd()();
|
|
994
|
-
i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button",
|
|
995
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(
|
|
1088
|
+
i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button", 142);
|
|
1089
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r35); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelLoadConversation()); });
|
|
996
1090
|
i0.ɵɵtext(8, "Cancel");
|
|
997
1091
|
i0.ɵɵelementEnd();
|
|
998
|
-
i0.ɵɵelementStart(9, "button",
|
|
999
|
-
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(
|
|
1092
|
+
i0.ɵɵelementStart(9, "button", 145);
|
|
1093
|
+
i0.ɵɵlistener("click", function AITestHarnessComponent_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r35); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmLoadConversation()); });
|
|
1000
1094
|
i0.ɵɵtext(10, " Load Conversation ");
|
|
1001
1095
|
i0.ɵɵelementEnd()()();
|
|
1002
1096
|
} if (rf & 2) {
|
|
@@ -1086,12 +1180,18 @@ export class AITestHarnessComponent {
|
|
|
1086
1180
|
this.selectedVendorId = '';
|
|
1087
1181
|
/** Available AI vendors for the selected model */
|
|
1088
1182
|
this.availableVendors = [];
|
|
1183
|
+
/** Selected AI configuration for prompt execution */
|
|
1184
|
+
this.selectedConfigurationId = '';
|
|
1185
|
+
/** Available AI configurations */
|
|
1186
|
+
this.availableConfigurations = [];
|
|
1089
1187
|
/** Default model for the prompt (cached for display) */
|
|
1090
1188
|
this.defaultModelName = '';
|
|
1091
1189
|
/** Maximum tokens for prompt execution */
|
|
1092
1190
|
this.maxTokens = null;
|
|
1093
1191
|
/** Whether to skip validation when running prompts */
|
|
1094
1192
|
this.skipValidation = false;
|
|
1193
|
+
/** Selected AI configuration for agent execution */
|
|
1194
|
+
this.agentConfigurationId = '';
|
|
1095
1195
|
/** Advanced LLM Parameters */
|
|
1096
1196
|
this.advancedParams = {
|
|
1097
1197
|
temperature: null,
|
|
@@ -1215,6 +1315,8 @@ export class AITestHarnessComponent {
|
|
|
1215
1315
|
this.loadSavedConversations();
|
|
1216
1316
|
this.subscribeToEvents();
|
|
1217
1317
|
this.resetHarness();
|
|
1318
|
+
// Load configurations for both modes
|
|
1319
|
+
this.loadAvailableConfigurations();
|
|
1218
1320
|
// Load models if in prompt mode
|
|
1219
1321
|
if (this.mode === 'prompt') {
|
|
1220
1322
|
this.loadAvailableModels();
|
|
@@ -1503,6 +1605,37 @@ export class AITestHarnessComponent {
|
|
|
1503
1605
|
this.availableVendors = [];
|
|
1504
1606
|
}
|
|
1505
1607
|
}
|
|
1608
|
+
/**
|
|
1609
|
+
* Loads available AI configurations from the database
|
|
1610
|
+
* Only configurations with 'Active' or 'Preview' status are shown
|
|
1611
|
+
*/
|
|
1612
|
+
async loadAvailableConfigurations() {
|
|
1613
|
+
try {
|
|
1614
|
+
const rv = new RunView();
|
|
1615
|
+
const result = await rv.RunView({
|
|
1616
|
+
EntityName: 'MJ: AI Configurations',
|
|
1617
|
+
ExtraFilter: `Status IN ('Active', 'Preview')`,
|
|
1618
|
+
OrderBy: 'IsDefault DESC, Name',
|
|
1619
|
+
ResultType: 'entity_object'
|
|
1620
|
+
});
|
|
1621
|
+
if (result.Success && result.Results) {
|
|
1622
|
+
this.availableConfigurations = result.Results;
|
|
1623
|
+
// Auto-select the default configuration if one exists
|
|
1624
|
+
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1625
|
+
if (defaultConfig) {
|
|
1626
|
+
this.selectedConfigurationId = defaultConfig.ID;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
else {
|
|
1630
|
+
console.error('Failed to load AI configurations:', result.ErrorMessage);
|
|
1631
|
+
this.availableConfigurations = [];
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
catch (error) {
|
|
1635
|
+
console.error('Error loading AI configurations:', error);
|
|
1636
|
+
this.availableConfigurations = [];
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1506
1639
|
/**
|
|
1507
1640
|
* Handles model selection change and loads available vendors for the selected model
|
|
1508
1641
|
*/
|
|
@@ -1673,6 +1806,14 @@ export class AITestHarnessComponent {
|
|
|
1673
1806
|
this.maxTokens = null;
|
|
1674
1807
|
// Reset skip validation
|
|
1675
1808
|
this.skipValidation = false;
|
|
1809
|
+
// Reset configuration to default
|
|
1810
|
+
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1811
|
+
if (defaultConfig) {
|
|
1812
|
+
this.selectedConfigurationId = defaultConfig.ID;
|
|
1813
|
+
}
|
|
1814
|
+
else {
|
|
1815
|
+
this.selectedConfigurationId = '';
|
|
1816
|
+
}
|
|
1676
1817
|
// Reset advanced parameters
|
|
1677
1818
|
this.advancedParams = {
|
|
1678
1819
|
temperature: null,
|
|
@@ -1734,6 +1875,11 @@ export class AITestHarnessComponent {
|
|
|
1734
1875
|
this.stopSequencesText = '';
|
|
1735
1876
|
this.advancedParamsExpanded = false;
|
|
1736
1877
|
this.skipValidation = false;
|
|
1878
|
+
// Reset agent configuration to default
|
|
1879
|
+
if (this.mode === 'agent') {
|
|
1880
|
+
const defaultConfig = this.availableConfigurations.find(c => c.IsDefault);
|
|
1881
|
+
this.agentConfigurationId = defaultConfig?.ID || '';
|
|
1882
|
+
}
|
|
1737
1883
|
}
|
|
1738
1884
|
/**
|
|
1739
1885
|
* Starts a new conversation
|
|
@@ -1981,8 +2127,8 @@ export class AITestHarnessComponent {
|
|
|
1981
2127
|
const sessionId = dataProvider.sessionId;
|
|
1982
2128
|
// Execute the agent
|
|
1983
2129
|
const query = `
|
|
1984
|
-
mutation RunAIAgent($agentId: String!, $messages: String!, $sessionId: String!, $data: String, $templateData: String, $lastRunId: String, $autoPopulateLastRunPayload: Boolean) {
|
|
1985
|
-
RunAIAgent(agentId: $agentId, messages: $messages, sessionId: $sessionId, data: $data, templateData: $templateData, lastRunId: $lastRunId, autoPopulateLastRunPayload: $autoPopulateLastRunPayload) {
|
|
2130
|
+
mutation RunAIAgent($agentId: String!, $messages: String!, $sessionId: String!, $data: String, $templateData: String, $lastRunId: String, $autoPopulateLastRunPayload: Boolean, $configurationId: String) {
|
|
2131
|
+
RunAIAgent(agentId: $agentId, messages: $messages, sessionId: $sessionId, data: $data, templateData: $templateData, lastRunId: $lastRunId, autoPopulateLastRunPayload: $autoPopulateLastRunPayload, configurationId: $configurationId) {
|
|
1986
2132
|
success
|
|
1987
2133
|
errorMessage
|
|
1988
2134
|
executionTimeMs
|
|
@@ -1997,7 +2143,8 @@ export class AITestHarnessComponent {
|
|
|
1997
2143
|
data: Object.keys(dataContext).length > 0 ? JSON.stringify(dataContext) : null,
|
|
1998
2144
|
templateData: Object.keys(templateData).length > 0 ? JSON.stringify(templateData) : null,
|
|
1999
2145
|
lastRunId: this.lastAgentRunId,
|
|
2000
|
-
autoPopulateLastRunPayload: this.lastAgentRunId ? true : false
|
|
2146
|
+
autoPopulateLastRunPayload: this.lastAgentRunId ? true : false,
|
|
2147
|
+
configurationId: this.agentConfigurationId || undefined
|
|
2001
2148
|
};
|
|
2002
2149
|
// Start typing animation while we wait for the first real stream
|
|
2003
2150
|
this.startTypingAnimation(assistantMessage);
|
|
@@ -2208,7 +2355,7 @@ export class AITestHarnessComponent {
|
|
|
2208
2355
|
data: JSON.stringify(dataContext),
|
|
2209
2356
|
overrideModelId: this.selectedModelId || undefined,
|
|
2210
2357
|
overrideVendorId: this.selectedVendorId || undefined,
|
|
2211
|
-
configurationId: undefined,
|
|
2358
|
+
configurationId: this.selectedConfigurationId || undefined,
|
|
2212
2359
|
skipValidation: this.skipValidation,
|
|
2213
2360
|
templateData: null, // Additional template context if needed
|
|
2214
2361
|
responseFormat: this.selectedResponseFormat?.value,
|
|
@@ -2534,7 +2681,9 @@ export class AITestHarnessComponent {
|
|
|
2534
2681
|
advancedParams: this.mode === 'prompt' ? this.advancedParams : undefined,
|
|
2535
2682
|
selectedModelId: this.mode === 'prompt' ? this.selectedModelId : undefined,
|
|
2536
2683
|
selectedVendorId: this.mode === 'prompt' ? this.selectedVendorId : undefined,
|
|
2684
|
+
selectedConfigurationId: this.mode === 'prompt' ? this.selectedConfigurationId : undefined,
|
|
2537
2685
|
skipValidation: this.mode === 'prompt' ? this.skipValidation : undefined,
|
|
2686
|
+
agentConfigurationId: this.mode === 'agent' ? this.agentConfigurationId : undefined,
|
|
2538
2687
|
createdAt: new Date(),
|
|
2539
2688
|
updatedAt: new Date()
|
|
2540
2689
|
};
|
|
@@ -2599,12 +2748,14 @@ export class AITestHarnessComponent {
|
|
|
2599
2748
|
this.savedConversations[index].dataContext = this.buildDataContext();
|
|
2600
2749
|
if (this.mode === 'agent') {
|
|
2601
2750
|
this.savedConversations[index].templateData = this.buildTemplateData();
|
|
2751
|
+
this.savedConversations[index].agentConfigurationId = this.agentConfigurationId;
|
|
2602
2752
|
}
|
|
2603
2753
|
else {
|
|
2604
2754
|
this.savedConversations[index].templateVariables = this.buildTemplateVariables();
|
|
2605
2755
|
this.savedConversations[index].advancedParams = this.advancedParams;
|
|
2606
2756
|
this.savedConversations[index].selectedModelId = this.selectedModelId;
|
|
2607
2757
|
this.savedConversations[index].selectedVendorId = this.selectedVendorId;
|
|
2758
|
+
this.savedConversations[index].selectedConfigurationId = this.selectedConfigurationId;
|
|
2608
2759
|
this.savedConversations[index].skipValidation = this.skipValidation;
|
|
2609
2760
|
}
|
|
2610
2761
|
this.savedConversations[index].updatedAt = new Date();
|
|
@@ -2661,6 +2812,12 @@ export class AITestHarnessComponent {
|
|
|
2661
2812
|
typeof value === 'object' ? 'object' : 'string'
|
|
2662
2813
|
});
|
|
2663
2814
|
}
|
|
2815
|
+
// Restore configuration for agent mode
|
|
2816
|
+
if (this.mode === 'agent') {
|
|
2817
|
+
if (conversation.agentConfigurationId !== undefined) {
|
|
2818
|
+
this.agentConfigurationId = conversation.agentConfigurationId;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2664
2821
|
// Restore template variables for prompt mode
|
|
2665
2822
|
if (this.mode === 'prompt') {
|
|
2666
2823
|
this.templateVariables = [];
|
|
@@ -2696,6 +2853,10 @@ export class AITestHarnessComponent {
|
|
|
2696
2853
|
if (conversation.selectedVendorId !== undefined && !this.selectedModelId) {
|
|
2697
2854
|
this.selectedVendorId = conversation.selectedVendorId;
|
|
2698
2855
|
}
|
|
2856
|
+
// Restore configuration selection
|
|
2857
|
+
if (conversation.selectedConfigurationId !== undefined) {
|
|
2858
|
+
this.selectedConfigurationId = conversation.selectedConfigurationId;
|
|
2859
|
+
}
|
|
2699
2860
|
// Restore skip validation setting
|
|
2700
2861
|
if (conversation.skipValidation !== undefined) {
|
|
2701
2862
|
this.skipValidation = conversation.skipValidation;
|
|
@@ -2752,12 +2913,16 @@ export class AITestHarnessComponent {
|
|
|
2752
2913
|
// Add mode-specific data
|
|
2753
2914
|
if (this.mode === 'agent') {
|
|
2754
2915
|
exportData.templateData = this.buildTemplateData();
|
|
2916
|
+
exportData.agentSettings = {
|
|
2917
|
+
configurationId: this.agentConfigurationId
|
|
2918
|
+
};
|
|
2755
2919
|
}
|
|
2756
2920
|
else {
|
|
2757
2921
|
exportData.templateVariables = this.buildTemplateVariables();
|
|
2758
2922
|
exportData.modelSettings = {
|
|
2759
2923
|
modelId: this.selectedModelId,
|
|
2760
2924
|
vendorId: this.selectedVendorId,
|
|
2925
|
+
configurationId: this.selectedConfigurationId,
|
|
2761
2926
|
maxTokens: this.maxTokens,
|
|
2762
2927
|
skipValidation: this.skipValidation
|
|
2763
2928
|
};
|
|
@@ -2812,6 +2977,40 @@ export class AITestHarnessComponent {
|
|
|
2812
2977
|
this.advancedParams = { ...this.advancedParams, ...data.advancedParams };
|
|
2813
2978
|
this.stopSequencesText = this.advancedParams.stopSequences?.join(', ') || '';
|
|
2814
2979
|
}
|
|
2980
|
+
// Import agent settings if in agent mode
|
|
2981
|
+
if (this.mode === 'agent' && data.agentSettings) {
|
|
2982
|
+
if (data.agentSettings.configurationId !== undefined) {
|
|
2983
|
+
this.agentConfigurationId = data.agentSettings.configurationId;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
// Import model settings if in prompt mode
|
|
2987
|
+
if (this.mode === 'prompt' && data.modelSettings) {
|
|
2988
|
+
if (data.modelSettings.modelId !== undefined) {
|
|
2989
|
+
this.selectedModelId = data.modelSettings.modelId;
|
|
2990
|
+
// Trigger vendor loading if model is selected
|
|
2991
|
+
if (this.selectedModelId) {
|
|
2992
|
+
this.onModelSelectionChange();
|
|
2993
|
+
// After vendors load, restore vendor selection
|
|
2994
|
+
setTimeout(() => {
|
|
2995
|
+
if (data.modelSettings.vendorId !== undefined) {
|
|
2996
|
+
this.selectedVendorId = data.modelSettings.vendorId;
|
|
2997
|
+
}
|
|
2998
|
+
}, 100);
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
if (data.modelSettings.vendorId !== undefined && !this.selectedModelId) {
|
|
3002
|
+
this.selectedVendorId = data.modelSettings.vendorId;
|
|
3003
|
+
}
|
|
3004
|
+
if (data.modelSettings.configurationId !== undefined) {
|
|
3005
|
+
this.selectedConfigurationId = data.modelSettings.configurationId;
|
|
3006
|
+
}
|
|
3007
|
+
if (data.modelSettings.maxTokens !== undefined) {
|
|
3008
|
+
this.maxTokens = data.modelSettings.maxTokens;
|
|
3009
|
+
}
|
|
3010
|
+
if (data.modelSettings.skipValidation !== undefined) {
|
|
3011
|
+
this.skipValidation = data.modelSettings.skipValidation;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
2815
3014
|
this.currentConversationId = null;
|
|
2816
3015
|
this.scrollNeeded = true;
|
|
2817
3016
|
MJNotificationService.Instance.CreateSimpleNotification('Conversation imported successfully', 'success', 3000);
|
|
@@ -3520,7 +3719,7 @@ export class AITestHarnessComponent {
|
|
|
3520
3719
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
|
|
3521
3720
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageInput = _t.first);
|
|
3522
3721
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.saveDialogInput = _t.first);
|
|
3523
|
-
} }, inputs: { mode: "mode", entity: "entity", aiAgent: "aiAgent", isVisible: "isVisible" }, outputs: { visibilityChange: "visibilityChange", runOpened: "runOpened", minimizeRequested: "minimizeRequested" }, features: [i0.ɵɵNgOnChangesFeature], decls: 3, vars: 3, consts: [["fileInput", ""], ["messagesContainer", ""], ["messageInput", ""], ["saveDialogInput", ""], ["class", "harness-container", "kendoWindowContainer", "", 4, "ngIf"], [1, "save-dialog", 3, "title", "width"], [1, "confirm-dialog", 3, "title", "width"], ["kendoWindowContainer", "", 1, "harness-container"], [1, "harness-header"], [1, "agent-info"], [1, "harness-body"], ["orientation", "horizontal", 2, "height", "100%", "width", "100%"], [1, "chat-area"], [1, "agent-details"], [1, "entity-logo", 3, "src", "alt"], [3, "class"], [1, "header-actions"], ["title", "Clear conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-broom"], ["title", "Save conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-save"], ["title", "Export conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-download"], ["title", "Import conversation", 1, "custom-button", 3, "click"], [1, "fa-solid", "fa-upload"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["title", "Toggle sidebar", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid"], [3, "collapsible", "resizable", "min"], [1, "messages-container"], [1, "empty-state"], [3, "ngClass"], [1, "input-area"], [1, "input-container"], ["placeholder", "Type your message here... (Press Enter to send, Shift+Enter for new line)", 1, "message-input", 3, "ngModelChange", "keypress", "ngModel", "rows", "disabled"], ["title", "Send message", 1, "send-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-paper-plane"], [3, "collapsible", "resizable", "size", "min"], [1, "sidebar"], [1, "sidebar-tabs"], [1, "tab-button", 3, "click", "disabled"], [1, "fa-solid", "fa-history"], [1, "badge"], [1, "sidebar-content"], [1, "tab-content"], [1, "tab-content", 2, "padding", "0", "height", "100%"], [1, "tab-content", 2, "overflow-y", "auto"], [1, "fa-solid", "fa-comments"], [1, "message-header"], [1, "message-role"], [1, "message-time"], [1, "execution-time", "streaming"], [1, "execution-time", 3, "title"], ["title", "View raw JSON response", 1, "raw-toggle"], [1, "message-content"], ["title", "Copy message", 1, "copy-button-in-bubble", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "streaming-wrapper"], [3, "innerHTML"], [1, "error-details"], [1, "payload-section", 3, "collapsed"], [1, "fa-solid", "fa-user"], [1, "message-role-logo", 3, "src", "alt"], ["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, "tab-button", 3, "click"], [1, "fa-solid", "fa-diagram-project"], [1, "fa-solid", "fa-sliders"], [1, "tab-header"], [1, "variables-list"], [1, "empty-variables"], [1, "variable-item"], [1, "add-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], ["placeholder", "Variable name", 1, "variable-name", 3, "ngModelChange", "ngModel", "disabled"], ["textField", "text", "valueField", "value", 1, "variable-type", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "disabled"], [1, "variable-value", 3, "ngModelChange", "ngModel", "placeholder", "disabled"], ["title", "Remove variable", 1, "remove-button", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [3, "viewRunClick", "mode", "agentRun", "liveSteps", "autoExpand", "runId", "runType"], [1, "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"], [
|
|
3722
|
+
} }, inputs: { mode: "mode", entity: "entity", aiAgent: "aiAgent", isVisible: "isVisible" }, outputs: { visibilityChange: "visibilityChange", runOpened: "runOpened", minimizeRequested: "minimizeRequested" }, features: [i0.ɵɵNgOnChangesFeature], decls: 3, vars: 3, consts: [["fileInput", ""], ["messagesContainer", ""], ["messageInput", ""], ["saveDialogInput", ""], ["class", "harness-container", "kendoWindowContainer", "", 4, "ngIf"], [1, "save-dialog", 3, "title", "width"], [1, "confirm-dialog", 3, "title", "width"], ["kendoWindowContainer", "", 1, "harness-container"], [1, "harness-header"], [1, "agent-info"], [1, "harness-body"], ["orientation", "horizontal", 2, "height", "100%", "width", "100%"], [1, "chat-area"], [1, "agent-details"], [1, "entity-logo", 3, "src", "alt"], [3, "class"], [1, "header-actions"], ["title", "Clear conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-broom"], ["title", "Save conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-save"], ["title", "Export conversation", 1, "custom-button", 3, "click", "disabled"], [1, "fa-solid", "fa-download"], ["title", "Import conversation", 1, "custom-button", 3, "click"], [1, "fa-solid", "fa-upload"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["title", "Toggle sidebar", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid"], [3, "collapsible", "resizable", "min"], [1, "messages-container"], [1, "empty-state"], [3, "ngClass"], [1, "input-area"], [1, "input-container"], ["placeholder", "Type your message here... (Press Enter to send, Shift+Enter for new line)", 1, "message-input", 3, "ngModelChange", "keypress", "ngModel", "rows", "disabled"], ["title", "Send message", 1, "send-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-paper-plane"], [3, "collapsible", "resizable", "size", "min"], [1, "sidebar"], [1, "sidebar-tabs"], [1, "tab-button", 3, "click", "disabled"], [1, "fa-solid", "fa-history"], [1, "badge"], [1, "sidebar-content"], [1, "tab-content"], [1, "tab-content", 2, "padding", "0", "height", "100%"], [1, "tab-content", 2, "overflow-y", "auto"], [1, "fa-solid", "fa-comments"], [1, "message-header"], [1, "message-role"], [1, "message-time"], [1, "execution-time", "streaming"], [1, "execution-time", 3, "title"], ["title", "View raw JSON response", 1, "raw-toggle"], [1, "message-content"], ["title", "Copy message", 1, "copy-button-in-bubble", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "streaming-wrapper"], [3, "innerHTML"], [1, "error-details"], [1, "payload-section", 3, "collapsed"], [1, "fa-solid", "fa-user"], [1, "message-role-logo", 3, "src", "alt"], ["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, "tab-button", 3, "click"], [1, "fa-solid", "fa-diagram-project"], [1, "fa-solid", "fa-sliders"], [1, "tab-header"], [1, "variables-list"], [1, "empty-variables"], [1, "variable-item"], [1, "add-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], ["placeholder", "Variable name", 1, "variable-name", 3, "ngModelChange", "ngModel", "disabled"], ["textField", "text", "valueField", "value", 1, "variable-type", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "disabled"], [1, "variable-value", 3, "ngModelChange", "ngModel", "placeholder", "disabled"], ["title", "Remove variable", 1, "remove-button", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [3, "viewRunClick", "mode", "agentRun", "liveSteps", "autoExpand", "runId", "runType"], [1, "model-settings"], [1, "setting-group"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a configuration...", 1, "configuration-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [1, "setting-help"], [1, "add-button", 3, "click"], ["title", "Remove variable", 1, "remove-button", 3, "click"], ["title", "Reset to Prompt Settings", 1, "custom-button", "icon-only", 3, "click"], [1, "fa-solid", "fa-undo"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 1, "model-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a vendor...", 1, "vendor-selector", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "disabled"], ["textField", "text", "valueField", "value", "placeholder", "Select format...", 1, "format-selector", 3, "ngModelChange", "ngModel", "data"], ["placeholder", "Max tokens...", 1, "max-tokens-input", 3, "ngModelChange", "ngModel", "min", "max", "step"], [1, "checkbox-label"], ["type", "checkbox", 1, "skip-validation-checkbox", 3, "ngModelChange", "ngModel"], ["title", "Advanced Parameters", 1, "advanced-params-panel", 3, "action", "expanded"], [1, "advanced-settings"], ["title", "Controls randomness: 0 = more focused and deterministic, 2 = more random and creative"], ["placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "min", "max", "step", "format"], ["title", "Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens"], ["title", "Only sample from the top K tokens. Lower values reduce randomness"], ["title", "Minimum probability for token selection. Filters out low-probability tokens"], ["title", "Penalizes tokens based on their frequency in the text. Positive values reduce repetition"], ["title", "Penalizes tokens that have appeared in the text. Positive values increase topic diversity"], ["title", "Random seed for deterministic generation. Same seed produces same output"], ["placeholder", "None", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "format"], ["title", "Sequences that will stop generation when encountered. Enter comma-separated values"], ["placeholder", "Enter comma-separated sequences", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "rows"], ["title", "Include log probabilities of the output tokens in the response"], [1, "advanced-param-switch", 3, "ngModelChange", "ngModel"], ["title", "Number of top log probabilities to include for each token"], ["placeholder", "2", 1, "advanced-param-input", 3, "ngModelChange", "ngModel", "min", "max", "step", "format"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary"], [1, "saved-list"], [1, "empty-saved"], [1, "saved-item", 3, "current"], ["title", "Start a new conversation", 1, "custom-button", "small", "primary", 3, "click"], [1, "fa-solid", "fa-folder-open"], [1, "saved-item", 3, "click"], [1, "saved-info"], [1, "saved-date"], ["title", "Delete conversation", 1, "delete-button", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "View execution details", 1, "execution-history-toggle"], ["title", "View full run details", 1, "execution-history-toggle"], [1, "fa-solid", "fa-robot"], ["title", "View execution details", 1, "execution-history-toggle", 3, "click"], ["title", "View full run details", 1, "execution-history-toggle", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "streaming-content"], [1, "save-dialog", 3, "close", "title", "width"], [1, "dialog-content"], ["type", "text", "placeholder", "Conversation name", 1, "k-textbox", "k-input", "k-input-md", "k-rounded-md", "k-input-solid", "full-width", 3, "keyup"], ["kendoButton", "", 3, "click"], ["kendoButton", "", 3, "click", "primary", "disabled"], [1, "confirm-dialog", 3, "close", "title", "width"], ["kendoButton", "", 3, "click", "primary"]], template: function AITestHarnessComponent_Template(rf, ctx) { if (rf & 1) {
|
|
3524
3723
|
i0.ɵɵtemplate(0, AITestHarnessComponent_div_0_Template, 6, 2, "div", 4)(1, AITestHarnessComponent_Conditional_1_Template, 11, 4, "kendo-dialog", 5)(2, AITestHarnessComponent_Conditional_2_Template, 11, 3, "kendo-dialog", 6);
|
|
3525
3724
|
} if (rf & 2) {
|
|
3526
3725
|
i0.ɵɵproperty("ngIf", ctx.isVisible);
|
|
@@ -3532,7 +3731,7 @@ export class AITestHarnessComponent {
|
|
|
3532
3731
|
}
|
|
3533
3732
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AITestHarnessComponent, [{
|
|
3534
3733
|
type: Component,
|
|
3535
|
-
args: [{ selector: 'mj-ai-test-harness', template: "<div class=\"harness-container\" *ngIf=\"isVisible\" kendoWindowContainer>\n <!-- Header -->\n <div class=\"harness-header\">\n @if (entity) {\n <div class=\"agent-info\">\n <div class=\"agent-details\">\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"entity-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n <div>\n <h3>{{ getEntityName() }}</h3>\n @if (entity.Description) {\n <p>{{ entity.Description }}</p>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n <button \n class=\"custom-button\"\n (click)=\"clearConversation()\"\n [disabled]=\"isExecuting || conversationMessages.length === 0\"\n title=\"Clear conversation\">\n <i class=\"fa-solid fa-broom\"></i>\n Clear\n </button>\n <button \n class=\"custom-button\"\n (click)=\"saveConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Save conversation\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n <button \n class=\"custom-button\"\n (click)=\"exportConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Export conversation\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button \n class=\"custom-button\"\n (click)=\"importConversation()\"\n title=\"Import conversation\">\n <i class=\"fa-solid fa-upload\"></i>\n Import\n </button>\n <input \n #fileInput\n type=\"file\"\n accept=\".json\"\n style=\"display: none\"\n (change)=\"onFileSelected($event)\">\n <button \n class=\"custom-button icon-only\"\n (click)=\"toggleSidebar()\"\n title=\"Toggle sidebar\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!showSidebar\" [class.fa-chevron-left]=\"showSidebar\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Main Content Area with Splitter -->\n <div class=\"harness-body\">\n @if (showSidebar) {\n <kendo-splitter \n orientation=\"horizontal\"\n style=\"height: 100%; width: 100%;\">\n \n <!-- Chat Area (Left Pane) -->\n <kendo-splitter-pane \n [collapsible]=\"false\"\n [resizable]=\"true\"\n [min]=\"'400px'\">\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n\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\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n </kendo-splitter-pane>\n \n <!-- Sidebar (Right Pane) -->\n <kendo-splitter-pane \n [collapsible]=\"false\"\n [resizable]=\"true\"\n [size]=\"'30%'\"\n [min]=\"'300px'\">\n <div class=\"sidebar\">\n <!-- Tab Navigation -->\n <div class=\"sidebar-tabs\">\n @if (mode === 'agent') {\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentVariables'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentVariables'\"\n (click)=\"selectTab('agentVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Agent Variables\n </button>\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'executionMonitor'\"\n (click)=\"selectTab('executionMonitor')\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n Execution Monitor\n </button>\n } @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\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 \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 \n @for (variable of agentVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox \n [(ngModel)]=\"variable.name\" \n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n \n <kendo-dropdownlist \n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n \n <kendo-textbox \n [(ngModel)]=\"variable.value\" \n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n \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 \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\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\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 \n <div class=\"variables-list\">\n @for (variable of templateVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox \n [(ngModel)]=\"variable.name\" \n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n \n <kendo-dropdownlist \n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n \n <kendo-textbox \n [(ngModel)]=\"variable.value\" \n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n \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 \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\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 \n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Model</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedModelId\"\n (ngModelChange)=\"onModelSelectionChange()\"\n [data]=\"availableModels\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a model...\"\n class=\"model-selector\">\n </kendo-dropdownlist>\n </div>\n \n <div class=\"setting-group\">\n <label>AI Vendor</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedVendorId\"\n [data]=\"availableVendors\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [disabled]=\"availableVendors.length <= 1 || !selectedModelId\"\n placeholder=\"Select a vendor...\"\n class=\"vendor-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (!selectedModelId) {\n Using default vendor for the default model\n } @else if (availableVendors.length <= 1) {\n Only one vendor available for this model\n } @else {\n Select the inference provider for this model\n }\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label>Response Format</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedResponseFormat\"\n [data]=\"responseFormatOptions\"\n textField=\"text\"\n valueField=\"value\"\n placeholder=\"Select format...\"\n class=\"format-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n Expected format for AI response (defaults to prompt setting)\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label>Max Tokens</label>\n <kendo-numerictextbox \n [(ngModel)]=\"maxTokens\"\n [min]=\"100\"\n [max]=\"8000\"\n [step]=\"100\"\n placeholder=\"Max tokens...\"\n class=\"max-tokens-input\">\n </kendo-numerictextbox>\n <div class=\"setting-help\">\n Maximum length of generated response\n </div>\n </div>\n \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 \n <!-- Advanced Parameters Expansion Panel -->\n <kendo-expansionpanel \n [expanded]=\"advancedParamsExpanded\"\n (action)=\"toggleAdvancedParams()\"\n title=\"Advanced Parameters\"\n class=\"advanced-params-panel\">\n <div class=\"advanced-settings\">\n <div class=\"setting-group\">\n <label title=\"Controls randomness: 0 = more focused and deterministic, 2 = more random and creative\">\n Temperature\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.temperature\"\n [min]=\"0\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens\">\n Top P\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Only sample from the top K tokens. Lower values reduce randomness\">\n Top K\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topK\"\n [min]=\"1\"\n [max]=\"100\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Minimum probability for token selection. Filters out low-probability tokens\">\n Min P\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.minP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Penalizes tokens based on their frequency in the text. Positive values reduce repetition\">\n Frequency Penalty\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.frequencyPenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Penalizes tokens that have appeared in the text. Positive values increase topic diversity\">\n Presence Penalty\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.presencePenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Random seed for deterministic generation. Same seed produces same output\">\n Seed\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.seed\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Sequences that will stop generation when encountered. Enter comma-separated values\">\n Stop Sequences\n </label>\n <kendo-textarea \n [(ngModel)]=\"stopSequencesText\"\n (ngModelChange)=\"updateStopSequences()\"\n [rows]=\"2\"\n placeholder=\"Enter comma-separated sequences\"\n class=\"advanced-param-input\">\n </kendo-textarea>\n <div class=\"setting-help\">\n Separate multiple sequences with commas\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Include log probabilities of the output tokens in the response\">\n Include Log Probs\n </label>\n <kendo-switch \n [(ngModel)]=\"advancedParams.includeLogProbs\"\n class=\"advanced-param-switch\">\n </kendo-switch>\n </div>\n \n @if (advancedParams.includeLogProbs) {\n <div class=\"setting-group\">\n <label title=\"Number of top log probabilities to include for each token\">\n Top Log Probs\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topLogProbs\"\n [min]=\"2\"\n [max]=\"20\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"2\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n </div>\n </div>\n }\n\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 \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 \n @for (conv of savedConversations; track conv.id) {\n <div class=\"saved-item\" \n [class.current]=\"conv.id === currentConversationId\"\n (click)=\"loadConversation(conv)\">\n <div class=\"saved-info\">\n <h5>{{ conv.name }}</h5>\n <p>{{ conv.messages.length }} messages</p>\n <span class=\"saved-date\">{{ conv.updatedAt | date:'short' }}</span>\n </div>\n <button \n class=\"delete-button\"\n (click)=\"deleteConversation(conv, $event)\"\n title=\"Delete conversation\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n } @else {\n <!-- No sidebar - full width chat -->\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n\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\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Save Conversation Dialog -->\n @if (showSaveDialog) {\n <kendo-dialog \n [title]=\"'Save Conversation'\" \n [width]=\"400\"\n (close)=\"cancelSaveDialog()\"\n class=\"save-dialog\">\n <div class=\"dialog-content\">\n <p>Enter a name for this conversation:</p>\n <input \n #saveDialogInput\n type=\"text\"\n (keyup)=\"updateTempConversation()\"\n placeholder=\"Conversation name\"\n class=\"k-textbox k-input k-input-md k-rounded-md k-input-solid full-width\" />\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelSaveDialog()\">Cancel</button>\n <button kendoButton \n [primary]=\"true\" \n (click)=\"confirmSaveConversation()\"\n [disabled]=\"tempConversationName === ''\">\n Save\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n \n <!-- Load Confirmation Dialog -->\n @if (showLoadConfirmDialog) {\n <kendo-dialog \n [title]=\"'Replace Current Conversation?'\" \n [width]=\"400\"\n (close)=\"cancelLoadConversation()\"\n class=\"confirm-dialog\">\n <div class=\"dialog-content\">\n <p>Loading this conversation will replace the current one. Any unsaved changes will be lost.</p>\n <p>Do you want to continue?</p>\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelLoadConversation()\">Cancel</button>\n <button kendoButton \n [primary]=\"true\" \n (click)=\"confirmLoadConversation()\">\n Load Conversation\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n\n", styles: ["/* Container Styles */\n.harness-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n/* Custom Button Styles */\n.custom-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: #495057;\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: #f8f9fa;\n border-color: #adb5bd;\n color: #212529;\n}\n\n.custom-button:active:not(:disabled) {\n background: #e9ecef;\n border-color: #adb5bd;\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: #0d6efd;\n border: 1px solid #0d6efd;\n color: white;\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: #0b5ed7;\n border-color: #0a58ca;\n}\n\n.send-button:active:not(:disabled) {\n background: #0a58ca;\n border-color: #0a58ca;\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: white;\n border: 1px solid #0d6efd;\n color: #0d6efd;\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: #0d6efd;\n color: white;\n}\n\n/* Remove/Delete Buttons */\n.remove-button,\n.delete-button {\n background: transparent;\n border: none;\n color: #dc3545;\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: rgba(220, 53, 69, 0.1);\n color: #bd2130;\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: #adb5bd;\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: #6c757d;\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: #495057;\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: #6c757d;\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: #495057;\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: white;\n border-bottom: 1px solid #dee2e6;\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: #17a2b8;\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: #212529;\n}\n\n.agent-details p {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: #6c757d;\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: white;\n border-right: 1px solid #dee2e6;\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: #6c757d;\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: #495057;\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: #6f42c1;\n}\n\n.message-assistant .message-role {\n color: #17a2b8;\n}\n\n.message-time {\n color: #6c757d;\n font-size: 12px;\n}\n\n.execution-time {\n background: #e9ecef;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: #495057;\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming {\n background: #fff3cd;\n color: #856404;\n border: 1px solid #ffeaa7;\n}\n\n.raw-toggle {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: #6c757d;\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: #495057;\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: #e7f3ff;\n border: 1px solid #b8daff;\n}\n\n.message-assistant .message-content {\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n}\n\n.message.streaming .message-content {\n background: #fff3cd;\n border: 1px solid #ffeaa7;\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: #495057;\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: #f8d7da;\n border: 1px solid #f5c6cb;\n border-radius: 6px;\n color: #721c24;\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details i {\n color: #dc3545;\n}\n\n/* Payload Section Styles */\n.payload-section {\n margin-top: 12px;\n border: 1px solid #e9ecef;\n border-radius: 6px;\n overflow: hidden;\n background: #ffffff;\n}\n\n.payload-header {\n background: #f8f9fa;\n padding: 8px 12px;\n border-bottom: 1px solid #e9ecef;\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: #e9ecef;\n}\n\n.payload-label {\n font-size: 13px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label i {\n color: #6c757d;\n font-size: 12px;\n}\n\n.payload-content {\n max-height: 250px;\n overflow: auto;\n background: #f8f9fa;\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: #212529;\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: #6c757d;\n transition: color 0.2s;\n}\n\n.payload-toggle:hover {\n color: #495057;\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: #333;\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 #dee2e6;\n border-radius: 4px;\n \n &:focus {\n outline: none;\n border-color: #ff6358;\n box-shadow: 0 0 0 0.25rem rgba(255, 99, 88, 0.25);\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: #f8f9fa;\n border: 1px solid #e0e0e0;\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: #333;\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: #212529;\n border-bottom: 2px solid #e9ecef;\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: #212529;\n border-bottom: 1px solid #e9ecef;\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: #212529;\n}\n\n.code-block {\n background: #f8f9fa;\n border: 1px solid #e9ecef;\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: #212529;\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: #d73e48;\n}\n\n.inline-code {\n background: #f1f3f4;\n border: 1px solid #dadce0;\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: #d73e48;\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: #0d6efd;\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link:hover {\n color: #0a58ca;\n text-decoration: none;\n}\n\n/* Ensure proper text wrapping in message content */\n.message-content {\n background: #f8f9fa;\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: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: #495057;\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: #f8f9fa;\n border-color: #adb5bd;\n color: #212529;\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: white;\n border-top: 1px solid #dee2e6;\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.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: white;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* Kendo Splitter Specific Styles */\n.harness-body kendo-splitter {\n height: 100%;\n}\n\n.harness-body kendo-splitter-pane {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Sidebar Tabs */\n.sidebar-tabs {\n display: flex;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\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: #6c757d;\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: #e9ecef;\n color: #495057;\n}\n\n.tab-button.active {\n color: #0d6efd;\n border-bottom-color: #0d6efd;\n background: white;\n}\n\n.tab-button i {\n font-size: 14px;\n}\n\n.tab-button .badge {\n background: #6c757d;\n color: white;\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: #0d6efd;\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: #212529;\n}\n\n.tab-header p {\n margin: 0;\n font-size: 13px;\n color: #6c757d;\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: #6c757d;\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: #6c757d;\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 #dee2e6;\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: #f8f9fa;\n border-color: #adb5bd;\n}\n\n.saved-item.current {\n background: #e7f3ff;\n border-color: #0d6efd;\n}\n\n.saved-info h5 {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: #212529;\n}\n\n.saved-info p {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: #6c757d;\n}\n\n.saved-date {\n font-size: 11px;\n color: #6c757d;\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: #f1f1f1;\n}\n\n.messages-container::-webkit-scrollbar-thumb,\n.sidebar-content::-webkit-scrollbar-thumb {\n background: #c1c1c1;\n border-radius: 4px;\n}\n\n.messages-container::-webkit-scrollbar-thumb:hover,\n.sidebar-content::-webkit-scrollbar-thumb:hover {\n background: #a1a1a1;\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: #343a40;\n color: white;\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: white;\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 #dee2e6;\n border-radius: 4px;\n}\n\n.advanced-params-panel ::ng-deep .k-expander-title {\n font-weight: 600;\n color: #495057;\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}"] }]
|
|
3734
|
+
args: [{ selector: 'mj-ai-test-harness', template: "<div class=\"harness-container\" *ngIf=\"isVisible\" kendoWindowContainer>\n <!-- Header -->\n <div class=\"harness-header\">\n @if (entity) {\n <div class=\"agent-info\">\n <div class=\"agent-details\">\n @if (hasEntityLogo()) {\n <img [src]=\"getEntityLogoURL()\" [alt]=\"getEntityName() + ' logo'\" class=\"entity-logo\">\n } @else {\n <i [class]=\"getEntityIconClass()\"></i>\n }\n <div>\n <h3>{{ getEntityName() }}</h3>\n @if (entity.Description) {\n <p>{{ entity.Description }}</p>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n <button \n class=\"custom-button\"\n (click)=\"clearConversation()\"\n [disabled]=\"isExecuting || conversationMessages.length === 0\"\n title=\"Clear conversation\">\n <i class=\"fa-solid fa-broom\"></i>\n Clear\n </button>\n <button \n class=\"custom-button\"\n (click)=\"saveConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Save conversation\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n <button \n class=\"custom-button\"\n (click)=\"exportConversation()\"\n [disabled]=\"conversationMessages.length === 0\"\n title=\"Export conversation\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button \n class=\"custom-button\"\n (click)=\"importConversation()\"\n title=\"Import conversation\">\n <i class=\"fa-solid fa-upload\"></i>\n Import\n </button>\n <input \n #fileInput\n type=\"file\"\n accept=\".json\"\n style=\"display: none\"\n (change)=\"onFileSelected($event)\">\n <button \n class=\"custom-button icon-only\"\n (click)=\"toggleSidebar()\"\n title=\"Toggle sidebar\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!showSidebar\" [class.fa-chevron-left]=\"showSidebar\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Main Content Area with Splitter -->\n <div class=\"harness-body\">\n @if (showSidebar) {\n <kendo-splitter \n orientation=\"horizontal\"\n style=\"height: 100%; width: 100%;\">\n \n <!-- Chat Area (Left Pane) -->\n <kendo-splitter-pane \n [collapsible]=\"false\"\n [resizable]=\"true\"\n [min]=\"'400px'\">\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n\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\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n </kendo-splitter-pane>\n \n <!-- Sidebar (Right Pane) -->\n <kendo-splitter-pane \n [collapsible]=\"false\"\n [resizable]=\"true\"\n [size]=\"'30%'\"\n [min]=\"'300px'\">\n <div class=\"sidebar\">\n <!-- Tab Navigation -->\n <div class=\"sidebar-tabs\">\n @if (mode === 'agent') {\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentVariables'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentVariables'\"\n (click)=\"selectTab('agentVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Agent Variables\n </button>\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'executionMonitor'\"\n (click)=\"selectTab('executionMonitor')\">\n <i class=\"fa-solid fa-diagram-project\"></i>\n Execution Monitor\n </button>\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'agentSettings'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'agentSettings'\"\n (click)=\"selectTab('agentSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Settings\n </button>\n } @else {\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'templateVariables'\"\n (click)=\"selectTab('templateVariables')\">\n <i class=\"fa-solid fa-code\"></i>\n Template Variables\n </button>\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'modelSettings'\"\n (click)=\"selectTab('modelSettings')\">\n <i class=\"fa-solid fa-sliders\"></i>\n Model Settings\n </button>\n }\n <button \n class=\"tab-button\"\n [class.active]=\"activeTab === 'savedConversations'\"\n [disabled]=\"executionMonitorMode === 'live' && activeTab !== 'savedConversations'\"\n (click)=\"selectTab('savedConversations')\">\n <i class=\"fa-solid fa-history\"></i>\n Saved\n @if (savedConversations.length > 0) {\n <span class=\"badge\">{{ savedConversations.length }}</span>\n }\n </button>\n </div>\n\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 \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 \n @for (variable of agentVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox \n [(ngModel)]=\"variable.name\" \n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n \n <kendo-dropdownlist \n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n \n <kendo-textbox \n [(ngModel)]=\"variable.value\" \n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n \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 \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\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\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 \n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <kendo-dropdownlist \n [(ngModel)]=\"agentConfigurationId\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (agentConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (config.ID === 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\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 \n <div class=\"variables-list\">\n @for (variable of templateVariables; track $index) {\n <div class=\"variable-item\">\n <kendo-textbox \n [(ngModel)]=\"variable.name\" \n placeholder=\"Variable name\"\n [disabled]=\"isExecuting\"\n class=\"variable-name\">\n </kendo-textbox>\n \n <kendo-dropdownlist \n [(ngModel)]=\"variable.type\"\n [data]=\"[\n {text: 'String', value: 'string'}, \n {text: 'Number', value: 'number'}, \n {text: 'Boolean', value: 'boolean'}, \n {text: 'Object', value: 'object'}\n ]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [disabled]=\"isExecuting\"\n class=\"variable-type\">\n </kendo-dropdownlist>\n \n <kendo-textbox \n [(ngModel)]=\"variable.value\" \n [placeholder]=\"variable.type === 'object' ? 'JSON value' : 'Value'\"\n [disabled]=\"isExecuting\"\n class=\"variable-value\">\n </kendo-textbox>\n \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 \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\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 \n <div class=\"model-settings\">\n <div class=\"setting-group\">\n <label>AI Model</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedModelId\"\n (ngModelChange)=\"onModelSelectionChange()\"\n [data]=\"availableModels\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a model...\"\n class=\"model-selector\">\n </kendo-dropdownlist>\n </div>\n \n <div class=\"setting-group\">\n <label>AI Vendor</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedVendorId\"\n [data]=\"availableVendors\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [disabled]=\"availableVendors.length <= 1 || !selectedModelId\"\n placeholder=\"Select a vendor...\"\n class=\"vendor-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (!selectedModelId) {\n Using default vendor for the default model\n } @else if (availableVendors.length <= 1) {\n Only one vendor available for this model\n } @else {\n Select the inference provider for this model\n }\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label>AI Configuration</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedConfigurationId\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select a configuration...\"\n class=\"configuration-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n @if (selectedConfigurationId) {\n @for (config of availableConfigurations; track config.ID) {\n @if (config.ID === selectedConfigurationId && config.Description) {\n {{ config.Description }}\n }\n }\n } @else {\n Using default configuration\n }\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label>Response Format</label>\n <kendo-dropdownlist \n [(ngModel)]=\"selectedResponseFormat\"\n [data]=\"responseFormatOptions\"\n textField=\"text\"\n valueField=\"value\"\n placeholder=\"Select format...\"\n class=\"format-selector\">\n </kendo-dropdownlist>\n <div class=\"setting-help\">\n Expected format for AI response (defaults to prompt setting)\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label>Max Tokens</label>\n <kendo-numerictextbox \n [(ngModel)]=\"maxTokens\"\n [min]=\"100\"\n [max]=\"8000\"\n [step]=\"100\"\n placeholder=\"Max tokens...\"\n class=\"max-tokens-input\">\n </kendo-numerictextbox>\n <div class=\"setting-help\">\n Maximum length of generated response\n </div>\n </div>\n \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 \n <!-- Advanced Parameters Expansion Panel -->\n <kendo-expansionpanel \n [expanded]=\"advancedParamsExpanded\"\n (action)=\"toggleAdvancedParams()\"\n title=\"Advanced Parameters\"\n class=\"advanced-params-panel\">\n <div class=\"advanced-settings\">\n <div class=\"setting-group\">\n <label title=\"Controls randomness: 0 = more focused and deterministic, 2 = more random and creative\">\n Temperature\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.temperature\"\n [min]=\"0\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Nucleus sampling: only consider tokens with cumulative probability up to this value. 1 = consider all tokens\">\n Top P\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Only sample from the top K tokens. Lower values reduce randomness\">\n Top K\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topK\"\n [min]=\"1\"\n [max]=\"100\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Minimum probability for token selection. Filters out low-probability tokens\">\n Min P\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.minP\"\n [min]=\"0\"\n [max]=\"1\"\n [step]=\"0.01\"\n [format]=\"'n2'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Penalizes tokens based on their frequency in the text. Positive values reduce repetition\">\n Frequency Penalty\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.frequencyPenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Penalizes tokens that have appeared in the text. Positive values increase topic diversity\">\n Presence Penalty\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.presencePenalty\"\n [min]=\"-2\"\n [max]=\"2\"\n [step]=\"0.1\"\n [format]=\"'n1'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Random seed for deterministic generation. Same seed produces same output\">\n Seed\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.seed\"\n [format]=\"'n0'\"\n placeholder=\"None\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Sequences that will stop generation when encountered. Enter comma-separated values\">\n Stop Sequences\n </label>\n <kendo-textarea \n [(ngModel)]=\"stopSequencesText\"\n (ngModelChange)=\"updateStopSequences()\"\n [rows]=\"2\"\n placeholder=\"Enter comma-separated sequences\"\n class=\"advanced-param-input\">\n </kendo-textarea>\n <div class=\"setting-help\">\n Separate multiple sequences with commas\n </div>\n </div>\n \n <div class=\"setting-group\">\n <label title=\"Include log probabilities of the output tokens in the response\">\n Include Log Probs\n </label>\n <kendo-switch \n [(ngModel)]=\"advancedParams.includeLogProbs\"\n class=\"advanced-param-switch\">\n </kendo-switch>\n </div>\n \n @if (advancedParams.includeLogProbs) {\n <div class=\"setting-group\">\n <label title=\"Number of top log probabilities to include for each token\">\n Top Log Probs\n </label>\n <kendo-numerictextbox \n [(ngModel)]=\"advancedParams.topLogProbs\"\n [min]=\"2\"\n [max]=\"20\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"2\"\n class=\"advanced-param-input\">\n </kendo-numerictextbox>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n </div>\n </div>\n }\n\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 \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 \n @for (conv of savedConversations; track conv.id) {\n <div class=\"saved-item\" \n [class.current]=\"conv.id === currentConversationId\"\n (click)=\"loadConversation(conv)\">\n <div class=\"saved-info\">\n <h5>{{ conv.name }}</h5>\n <p>{{ conv.messages.length }} messages</p>\n <span class=\"saved-date\">{{ conv.updatedAt | date:'short' }}</span>\n </div>\n <button \n class=\"delete-button\"\n (click)=\"deleteConversation(conv, $event)\"\n title=\"Delete conversation\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n } @else {\n <!-- No sidebar - full width chat -->\n <div class=\"chat-area\">\n <!-- Messages Container -->\n <div class=\"messages-container\" #messagesContainer>\n @if (conversationMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <h4>Start a conversation</h4>\n <p>Send a message to begin testing the AI agent</p>\n </div>\n }\n\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\n <!-- Input Area -->\n <div class=\"input-area\">\n <div class=\"input-container\">\n <kendo-textarea\n #messageInput\n [(ngModel)]=\"currentUserMessage\"\n [rows]=\"3\"\n placeholder=\"Type your message here... (Press Enter to send, Shift+Enter for new line)\"\n (keypress)=\"handleKeyPress($event)\"\n [disabled]=\"isExecuting\"\n class=\"message-input\">\n </kendo-textarea>\n <button\n class=\"send-button\"\n (click)=\"sendMessage()\"\n [disabled]=\"isExecuting || !currentUserMessage.trim()\"\n title=\"Send message\">\n @if (isExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Save Conversation Dialog -->\n @if (showSaveDialog) {\n <kendo-dialog \n [title]=\"'Save Conversation'\" \n [width]=\"400\"\n (close)=\"cancelSaveDialog()\"\n class=\"save-dialog\">\n <div class=\"dialog-content\">\n <p>Enter a name for this conversation:</p>\n <input \n #saveDialogInput\n type=\"text\"\n (keyup)=\"updateTempConversation()\"\n placeholder=\"Conversation name\"\n class=\"k-textbox k-input k-input-md k-rounded-md k-input-solid full-width\" />\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelSaveDialog()\">Cancel</button>\n <button kendoButton \n [primary]=\"true\" \n (click)=\"confirmSaveConversation()\"\n [disabled]=\"tempConversationName === ''\">\n Save\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n \n <!-- Load Confirmation Dialog -->\n @if (showLoadConfirmDialog) {\n <kendo-dialog \n [title]=\"'Replace Current Conversation?'\" \n [width]=\"400\"\n (close)=\"cancelLoadConversation()\"\n class=\"confirm-dialog\">\n <div class=\"dialog-content\">\n <p>Loading this conversation will replace the current one. Any unsaved changes will be lost.</p>\n <p>Do you want to continue?</p>\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelLoadConversation()\">Cancel</button>\n <button kendoButton \n [primary]=\"true\" \n (click)=\"confirmLoadConversation()\">\n Load Conversation\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n\n", styles: ["/* Container Styles */\n.harness-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n/* Custom Button Styles */\n.custom-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 13px;\n color: #495057;\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: #f8f9fa;\n border-color: #adb5bd;\n color: #212529;\n}\n\n.custom-button:active:not(:disabled) {\n background: #e9ecef;\n border-color: #adb5bd;\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: #0d6efd;\n border: 1px solid #0d6efd;\n color: white;\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: #0b5ed7;\n border-color: #0a58ca;\n}\n\n.send-button:active:not(:disabled) {\n background: #0a58ca;\n border-color: #0a58ca;\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: white;\n border: 1px solid #0d6efd;\n color: #0d6efd;\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: #0d6efd;\n color: white;\n}\n\n/* Remove/Delete Buttons */\n.remove-button,\n.delete-button {\n background: transparent;\n border: none;\n color: #dc3545;\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: rgba(220, 53, 69, 0.1);\n color: #bd2130;\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: #adb5bd;\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: #6c757d;\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: #495057;\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: #6c757d;\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: #495057;\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: white;\n border-bottom: 1px solid #dee2e6;\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: #17a2b8;\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: #212529;\n}\n\n.agent-details p {\n margin: 4px 0 0 0;\n font-size: 14px;\n color: #6c757d;\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: white;\n border-right: 1px solid #dee2e6;\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: #6c757d;\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: #495057;\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: #6f42c1;\n}\n\n.message-assistant .message-role {\n color: #17a2b8;\n}\n\n.message-time {\n color: #6c757d;\n font-size: 12px;\n}\n\n.execution-time {\n background: #e9ecef;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n color: #495057;\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.execution-time.streaming {\n background: #fff3cd;\n color: #856404;\n border: 1px solid #ffeaa7;\n}\n\n.raw-toggle {\n background: transparent;\n border: none;\n padding: 4px 8px;\n font-size: 12px;\n color: #6c757d;\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: #495057;\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: #e7f3ff;\n border: 1px solid #b8daff;\n}\n\n.message-assistant .message-content {\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n}\n\n.message.streaming .message-content {\n background: #fff3cd;\n border: 1px solid #ffeaa7;\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: #495057;\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: #f8d7da;\n border: 1px solid #f5c6cb;\n border-radius: 6px;\n color: #721c24;\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-details i {\n color: #dc3545;\n}\n\n/* Payload Section Styles */\n.payload-section {\n margin-top: 12px;\n border: 1px solid #e9ecef;\n border-radius: 6px;\n overflow: hidden;\n background: #ffffff;\n}\n\n.payload-header {\n background: #f8f9fa;\n padding: 8px 12px;\n border-bottom: 1px solid #e9ecef;\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: #e9ecef;\n}\n\n.payload-label {\n font-size: 13px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.payload-label i {\n color: #6c757d;\n font-size: 12px;\n}\n\n.payload-content {\n max-height: 250px;\n overflow: auto;\n background: #f8f9fa;\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: #212529;\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: #6c757d;\n transition: color 0.2s;\n}\n\n.payload-toggle:hover {\n color: #495057;\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: #333;\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 #dee2e6;\n border-radius: 4px;\n \n &:focus {\n outline: none;\n border-color: #ff6358;\n box-shadow: 0 0 0 0.25rem rgba(255, 99, 88, 0.25);\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: #f8f9fa;\n border: 1px solid #e0e0e0;\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: #333;\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: #212529;\n border-bottom: 2px solid #e9ecef;\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: #212529;\n border-bottom: 1px solid #e9ecef;\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: #212529;\n}\n\n.code-block {\n background: #f8f9fa;\n border: 1px solid #e9ecef;\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: #212529;\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: #d73e48;\n}\n\n.inline-code {\n background: #f1f3f4;\n border: 1px solid #dadce0;\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: #d73e48;\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: #0d6efd;\n text-decoration: underline;\n transition: color 0.2s;\n}\n\n.markdown-link:hover {\n color: #0a58ca;\n text-decoration: none;\n}\n\n/* Ensure proper text wrapping in message content */\n.message-content {\n background: #f8f9fa;\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: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n color: #495057;\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: #f8f9fa;\n border-color: #adb5bd;\n color: #212529;\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: white;\n border-top: 1px solid #dee2e6;\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.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: white;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* Kendo Splitter Specific Styles */\n.harness-body kendo-splitter {\n height: 100%;\n}\n\n.harness-body kendo-splitter-pane {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Sidebar Tabs */\n.sidebar-tabs {\n display: flex;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\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: #6c757d;\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: #e9ecef;\n color: #495057;\n}\n\n.tab-button.active {\n color: #0d6efd;\n border-bottom-color: #0d6efd;\n background: white;\n}\n\n.tab-button i {\n font-size: 14px;\n}\n\n.tab-button .badge {\n background: #6c757d;\n color: white;\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: #0d6efd;\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: #212529;\n}\n\n.tab-header p {\n margin: 0;\n font-size: 13px;\n color: #6c757d;\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: #6c757d;\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: #6c757d;\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 #dee2e6;\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: #f8f9fa;\n border-color: #adb5bd;\n}\n\n.saved-item.current {\n background: #e7f3ff;\n border-color: #0d6efd;\n}\n\n.saved-info h5 {\n margin: 0 0 4px 0;\n font-size: 14px;\n font-weight: 600;\n color: #212529;\n}\n\n.saved-info p {\n margin: 0 0 4px 0;\n font-size: 12px;\n color: #6c757d;\n}\n\n.saved-date {\n font-size: 11px;\n color: #6c757d;\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: #f1f1f1;\n}\n\n.messages-container::-webkit-scrollbar-thumb,\n.sidebar-content::-webkit-scrollbar-thumb {\n background: #c1c1c1;\n border-radius: 4px;\n}\n\n.messages-container::-webkit-scrollbar-thumb:hover,\n.sidebar-content::-webkit-scrollbar-thumb:hover {\n background: #a1a1a1;\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: #343a40;\n color: white;\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: white;\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 #dee2e6;\n border-radius: 4px;\n}\n\n.advanced-params-panel ::ng-deep .k-expander-title {\n font-weight: 600;\n color: #495057;\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}"] }]
|
|
3536
3735
|
}], () => [{ type: i1.DomSanitizer }, { type: i2.WindowService }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }, { type: i3.Router }], { mode: [{
|
|
3537
3736
|
type: Input
|
|
3538
3737
|
}], entity: [{
|
|
@@ -3560,5 +3759,5 @@ export class AITestHarnessComponent {
|
|
|
3560
3759
|
type: ViewChild,
|
|
3561
3760
|
args: ['saveDialogInput']
|
|
3562
3761
|
}] }); })();
|
|
3563
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber:
|
|
3762
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AITestHarnessComponent, { className: "AITestHarnessComponent", filePath: "lib/ai-test-harness.component.ts", lineNumber: 155 }); })();
|
|
3564
3763
|
//# sourceMappingURL=ai-test-harness.component.js.map
|