llm-testrunner-components 1.2.2 → 1.2.4

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.
Files changed (98) hide show
  1. package/dist/cjs/{app-chips_4.cjs.entry.js → app-chips_5.cjs.entry.js} +41 -6
  2. package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +235 -44
  4. package/dist/cjs/index.cjs.js.map +1 -1
  5. package/dist/cjs/llm-testrunner.cjs.js +1 -1
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/collection/collection-manifest.json +1 -0
  8. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +22 -12
  9. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
  10. package/dist/collection/components/llm-test-runner/llm-test-runner.js +91 -30
  11. package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
  12. package/dist/collection/components/llm-test-runner/test-cases/chat-history.css +101 -0
  13. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js +105 -0
  14. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js.map +1 -0
  15. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +37 -4
  16. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
  17. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +12 -2
  18. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
  19. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
  20. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
  21. package/dist/collection/index.js.map +1 -1
  22. package/dist/collection/lib/evaluation/evaluation-service.js +14 -7
  23. package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
  24. package/dist/collection/lib/form/components/app-chips.js +1 -1
  25. package/dist/collection/lib/form/components/app-select.js +1 -1
  26. package/dist/collection/lib/form/components/app-textarea.css +17 -0
  27. package/dist/collection/lib/form/components/app-textarea.js +4 -1
  28. package/dist/collection/lib/form/components/app-textarea.js.map +1 -1
  29. package/dist/collection/lib/import-export/test-suite-exporter.js +4 -0
  30. package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
  31. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js +44 -0
  32. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js.map +1 -0
  33. package/dist/collection/lib/test-cases/test-case-factory.js +2 -0
  34. package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
  35. package/dist/collection/lib/test-cases/test-case-mutations.js +35 -0
  36. package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
  37. package/dist/collection/schemas/expected-outcome.js +15 -1
  38. package/dist/collection/schemas/expected-outcome.js.map +1 -1
  39. package/dist/collection/schemas/test-case.js +6 -0
  40. package/dist/collection/schemas/test-case.js.map +1 -1
  41. package/dist/collection/types/expected-outcome.js.map +1 -1
  42. package/dist/collection/types/llm-test-runner.js.map +1 -1
  43. package/dist/collection/types/test-case.js.map +1 -1
  44. package/dist/components/app-chips.js +1 -1
  45. package/dist/components/app-select.js +1 -1
  46. package/dist/components/app-textarea.js +1 -1
  47. package/dist/components/chat-history.d.ts +11 -0
  48. package/dist/components/chat-history.js +2 -0
  49. package/dist/components/chat-history.js.map +1 -0
  50. package/dist/components/index.js +1 -1
  51. package/dist/components/llm-test-runner.js +1 -1
  52. package/dist/components/{p-CJBscebi.js → p-B87Lt3z4.js} +3 -3
  53. package/dist/components/p-B87Lt3z4.js.map +1 -0
  54. package/dist/components/p-Bx2jqguC.js +2 -0
  55. package/dist/components/p-Bx2jqguC.js.map +1 -0
  56. package/dist/components/p-D2qDAxFN.js +2 -0
  57. package/dist/components/p-D2qDAxFN.js.map +1 -0
  58. package/dist/components/{p-Dv7cB5FU.js → p-D4dHUFN9.js} +2 -2
  59. package/dist/components/{p-CE5-1jfZ.js → p-eN2dLrsr.js} +2 -2
  60. package/dist/esm/{app-chips_4.entry.js → app-chips_5.entry.js} +41 -7
  61. package/dist/esm/app-chips_5.entry.js.map +1 -0
  62. package/dist/esm/index.js +235 -44
  63. package/dist/esm/index.js.map +1 -1
  64. package/dist/esm/llm-testrunner.js +1 -1
  65. package/dist/esm/loader.js +1 -1
  66. package/dist/llm-testrunner/index.esm.js +2 -2
  67. package/dist/llm-testrunner/index.esm.js.map +1 -1
  68. package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
  69. package/dist/llm-testrunner/p-21202f12.entry.js +2 -0
  70. package/dist/llm-testrunner/p-21202f12.entry.js.map +1 -0
  71. package/dist/react/components.d.ts +6 -1
  72. package/dist/react/components.d.ts.map +1 -1
  73. package/dist/react/components.js +9 -0
  74. package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +6 -0
  75. package/dist/types/components/llm-test-runner/test-cases/chat-history.d.ts +14 -0
  76. package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +1 -0
  77. package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +6 -0
  78. package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +3 -0
  79. package/dist/types/components.d.ts +55 -0
  80. package/dist/types/index.d.ts +1 -1
  81. package/dist/types/lib/import-export/test-suite-exporter.d.ts +4 -0
  82. package/dist/types/lib/test-cases/dynamic-expected-outcome-resolver.d.ts +7 -0
  83. package/dist/types/lib/test-cases/test-case-mutations.d.ts +9 -1
  84. package/dist/types/schemas/expected-outcome.d.ts +16 -1
  85. package/dist/types/schemas/test-case.d.ts +34 -2
  86. package/dist/types/types/expected-outcome.d.ts +1 -1
  87. package/dist/types/types/llm-test-runner.d.ts +3 -2
  88. package/dist/types/types/test-case.d.ts +1 -1
  89. package/package.json +1 -1
  90. package/dist/cjs/app-chips_4.cjs.entry.js.map +0 -1
  91. package/dist/components/p-BZrzx5jG.js +0 -2
  92. package/dist/components/p-BZrzx5jG.js.map +0 -1
  93. package/dist/components/p-CJBscebi.js.map +0 -1
  94. package/dist/esm/app-chips_4.entry.js.map +0 -1
  95. package/dist/llm-testrunner/p-2cc09217.entry.js +0 -2
  96. package/dist/llm-testrunner/p-2cc09217.entry.js.map +0 -1
  97. /package/dist/components/{p-Dv7cB5FU.js.map → p-D4dHUFN9.js.map} +0 -0
  98. /package/dist/components/{p-CE5-1jfZ.js.map → p-eN2dLrsr.js.map} +0 -0
@@ -0,0 +1,101 @@
1
+ .chat-history {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-3);
5
+ margin-top: var(--spacing-4);
6
+ }
7
+
8
+ .chat-history__toggle-row {
9
+ display: flex;
10
+ align-items: center;
11
+ }
12
+
13
+ .chat-history__switch {
14
+ position: relative;
15
+ display: inline-flex;
16
+ align-items: center;
17
+ gap: var(--spacing-3);
18
+ cursor: pointer;
19
+ user-select: none;
20
+ }
21
+
22
+ .chat-history__switch-input {
23
+ position: absolute;
24
+ width: 1px;
25
+ height: 1px;
26
+ padding: 0;
27
+ margin: -1px;
28
+ overflow: hidden;
29
+ clip: rect(0, 0, 0, 0);
30
+ white-space: nowrap;
31
+ border: 0;
32
+ }
33
+
34
+ .chat-history__switch-ui {
35
+ position: relative;
36
+ flex-shrink: 0;
37
+ width: 2.75rem;
38
+ height: 1.5rem;
39
+ border-radius: var(--radius-full);
40
+ background: var(--muted);
41
+ border: var(--border-width) solid var(--border);
42
+ transition:
43
+ background 0.15s ease,
44
+ border-color 0.15s ease;
45
+ }
46
+
47
+ @media (prefers-reduced-motion: reduce) {
48
+ .chat-history__switch-ui,
49
+ .chat-history__switch-thumb {
50
+ transition: none;
51
+ }
52
+ }
53
+
54
+ .chat-history__switch-thumb {
55
+ position: absolute;
56
+ top: 2px;
57
+ left: 2px;
58
+ width: calc(1.5rem - 6px);
59
+ height: calc(1.5rem - 6px);
60
+ border-radius: var(--radius-full);
61
+ background: var(--background);
62
+ box-shadow: var(--shadow-sm);
63
+ transition: transform 0.15s ease;
64
+ }
65
+
66
+ .chat-history__switch-input:checked + .chat-history__switch-ui {
67
+ background: var(--primary);
68
+ border-color: var(--primary);
69
+ }
70
+
71
+ .chat-history__switch-input:checked + .chat-history__switch-ui .chat-history__switch-thumb {
72
+ /* track width − end padding (2px × 2) − thumb width */
73
+ transform: translateX(calc(2.75rem - (1.5rem - 6px) - 4px));
74
+ }
75
+
76
+ .chat-history__switch-input:focus-visible + .chat-history__switch-ui {
77
+ outline: 2px solid var(--ring);
78
+ outline-offset: 2px;
79
+ }
80
+
81
+ .chat-history__switch-text {
82
+ font-size: var(--font-size-sm, 0.875rem);
83
+ color: var(--foreground);
84
+ }
85
+
86
+ .chat-history__textarea {
87
+ width: 100%;
88
+ box-sizing: border-box;
89
+ padding: var(--spacing-2) var(--spacing-3);
90
+ border: var(--border-width) solid var(--border);
91
+ border-radius: var(--radius-md);
92
+ font: inherit;
93
+ resize: vertical;
94
+ min-height: 9rem;
95
+ background: var(--background);
96
+ }
97
+
98
+ .chat-history__textarea:focus-visible {
99
+ outline: 2px solid var(--ring);
100
+ outline-offset: 2px;
101
+ }
@@ -0,0 +1,105 @@
1
+ import { h } from "@stencil/core";
2
+ const CHAT_HISTORY_PLACEHOLDER = `[
3
+ {"role": "user", "content": "How do I import a saved suite?"},
4
+ {"role": "model", "content": "Use Import and pick the JSON from Export suite."}
5
+ ]`;
6
+ export class ChatHistory {
7
+ chatHistoryEnabled = false;
8
+ chatHistoryValue = '';
9
+ chatHistoryChange;
10
+ emit(detail) {
11
+ this.chatHistoryChange.emit(detail);
12
+ }
13
+ onToggle = (e) => {
14
+ const checked = e.target.checked;
15
+ this.emit({ enabled: checked, value: this.chatHistoryValue });
16
+ };
17
+ onTextInput = (e) => {
18
+ const value = e.target.value;
19
+ this.emit({ enabled: this.chatHistoryEnabled, value });
20
+ };
21
+ render() {
22
+ return (h("div", { key: 'f444a4b5bd9b48df151cad67b54bef54116d11b3', class: "chat-history" }, h("div", { key: '7216d764fb905ac5e8e33209d9586525e59fa218', class: "chat-history__toggle-row" }, h("label", { key: 'd5d092c323b48543c96525d449bcb03dcaf5113b', class: "chat-history__switch" }, h("input", { key: '5104ce460686434156454fc1dfd3685ba0e0968c', type: "checkbox", class: "chat-history__switch-input", checked: this.chatHistoryEnabled, onInput: this.onToggle }), h("span", { key: 'fa2e51bce0d6ff2d3bf133383e1ce940521097b0', class: "chat-history__switch-ui", "aria-hidden": "true" }, h("span", { key: 'e0d897ca166623ece09834b44b5baa12605cb9f3', class: "chat-history__switch-thumb" })), h("span", { key: 'e769678fde5d670e634d7a8e905ef09ce936f440', class: "chat-history__switch-text" }, "Chat history"))), this.chatHistoryEnabled ? (h("textarea", { class: "chat-history__textarea", value: this.chatHistoryValue, rows: 8, placeholder: CHAT_HISTORY_PLACEHOLDER, "aria-label": "Chat history", onInput: this.onTextInput })) : null));
23
+ }
24
+ static get is() { return "chat-history"; }
25
+ static get encapsulation() { return "shadow"; }
26
+ static get originalStyleUrls() {
27
+ return {
28
+ "$": ["chat-history.css"]
29
+ };
30
+ }
31
+ static get styleUrls() {
32
+ return {
33
+ "$": ["chat-history.css"]
34
+ };
35
+ }
36
+ static get properties() {
37
+ return {
38
+ "chatHistoryEnabled": {
39
+ "type": "boolean",
40
+ "mutable": false,
41
+ "complexType": {
42
+ "original": "boolean",
43
+ "resolved": "boolean",
44
+ "references": {}
45
+ },
46
+ "required": false,
47
+ "optional": false,
48
+ "docs": {
49
+ "tags": [],
50
+ "text": ""
51
+ },
52
+ "getter": false,
53
+ "setter": false,
54
+ "reflect": false,
55
+ "attribute": "chat-history-enabled",
56
+ "defaultValue": "false"
57
+ },
58
+ "chatHistoryValue": {
59
+ "type": "string",
60
+ "mutable": false,
61
+ "complexType": {
62
+ "original": "string",
63
+ "resolved": "string",
64
+ "references": {}
65
+ },
66
+ "required": false,
67
+ "optional": false,
68
+ "docs": {
69
+ "tags": [],
70
+ "text": ""
71
+ },
72
+ "getter": false,
73
+ "setter": false,
74
+ "reflect": false,
75
+ "attribute": "chat-history-value",
76
+ "defaultValue": "''"
77
+ }
78
+ };
79
+ }
80
+ static get events() {
81
+ return [{
82
+ "method": "chatHistoryChange",
83
+ "name": "chatHistoryChange",
84
+ "bubbles": true,
85
+ "cancelable": true,
86
+ "composed": true,
87
+ "docs": {
88
+ "tags": [],
89
+ "text": ""
90
+ },
91
+ "complexType": {
92
+ "original": "ChatHistoryChangeDetail",
93
+ "resolved": "{ enabled: boolean; value: string; }",
94
+ "references": {
95
+ "ChatHistoryChangeDetail": {
96
+ "location": "local",
97
+ "path": "/home/runner/work/llm-testrunner-lib/llm-testrunner-lib/src/components/llm-test-runner/test-cases/chat-history.tsx",
98
+ "id": "src/components/llm-test-runner/test-cases/chat-history.tsx::ChatHistoryChangeDetail"
99
+ }
100
+ }
101
+ }
102
+ }];
103
+ }
104
+ }
105
+ //# sourceMappingURL=chat-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-history.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/chat-history.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAgB,IAAI,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAExE,MAAM,wBAAwB,GAAG;;;EAG/B,CAAC;AAYH,MAAM,OAAO,WAAW;IACd,kBAAkB,GAAG,KAAK,CAAC;IAC3B,gBAAgB,GAAG,EAAE,CAAC;IAG9B,iBAAiB,CAAwC;IAEjD,IAAI,CAAC,MAA+B;QAC1C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAEO,QAAQ,GAAG,CAAC,CAAQ,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAI,CAAC,CAAC,MAA2B,CAAC,OAAO,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC;IAEM,WAAW,GAAG,CAAC,CAAQ,EAAE,EAAE;QACjC,MAAM,KAAK,GAAI,CAAC,CAAC,MAA8B,CAAC,KAAK,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC;IAEF,MAAM;QACJ,OAAO,CACL,4DAAK,KAAK,EAAC,cAAc;YACvB,4DAAK,KAAK,EAAC,0BAA0B;gBACnC,8DAAO,KAAK,EAAC,sBAAsB;oBACjC,8DACE,IAAI,EAAC,UAAU,EACf,KAAK,EAAC,4BAA4B,EAClC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAChC,OAAO,EAAE,IAAI,CAAC,QAAQ,GACtB;oBACF,6DAAM,KAAK,EAAC,yBAAyB,iBAAa,MAAM;wBACtD,6DAAM,KAAK,EAAC,4BAA4B,GAAG,CACtC;oBACP,6DAAM,KAAK,EAAC,2BAA2B,mBAAoB,CACrD,CACJ;YACL,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,CACzB,gBACE,KAAK,EAAC,wBAAwB,EAC9B,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAC5B,IAAI,EAAE,CAAC,EACP,WAAW,EAAE,wBAAwB,gBAC1B,cAAc,EACzB,OAAO,EAAE,IAAI,CAAC,WAAW,GACzB,CACH,CAAC,CAAC,CAAC,IAAI,CACJ,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';\n\nconst CHAT_HISTORY_PLACEHOLDER = `[\n {\"role\": \"user\", \"content\": \"How do I import a saved suite?\"},\n {\"role\": \"model\", \"content\": \"Use Import and pick the JSON from Export suite.\"}\n]`;\n\nexport type ChatHistoryChangeDetail = {\n enabled: boolean;\n value: string;\n};\n\n@Component({\n tag: 'chat-history',\n styleUrl: 'chat-history.css',\n shadow: true,\n})\nexport class ChatHistory {\n @Prop() chatHistoryEnabled = false;\n @Prop() chatHistoryValue = '';\n\n @Event({ bubbles: true, composed: true })\n chatHistoryChange: EventEmitter<ChatHistoryChangeDetail>;\n\n private emit(detail: ChatHistoryChangeDetail) {\n this.chatHistoryChange.emit(detail);\n }\n\n private onToggle = (e: Event) => {\n const checked = (e.target as HTMLInputElement).checked;\n this.emit({ enabled: checked, value: this.chatHistoryValue });\n };\n\n private onTextInput = (e: Event) => {\n const value = (e.target as HTMLTextAreaElement).value;\n this.emit({ enabled: this.chatHistoryEnabled, value });\n };\n\n render() {\n return (\n <div class=\"chat-history\">\n <div class=\"chat-history__toggle-row\">\n <label class=\"chat-history__switch\">\n <input\n type=\"checkbox\"\n class=\"chat-history__switch-input\"\n checked={this.chatHistoryEnabled}\n onInput={this.onToggle}\n />\n <span class=\"chat-history__switch-ui\" aria-hidden=\"true\">\n <span class=\"chat-history__switch-thumb\" />\n </span>\n <span class=\"chat-history__switch-text\">Chat history</span>\n </label>\n </div>\n {this.chatHistoryEnabled ? (\n <textarea\n class=\"chat-history__textarea\"\n value={this.chatHistoryValue}\n rows={8}\n placeholder={CHAT_HISTORY_PLACEHOLDER}\n aria-label=\"Chat history\"\n onInput={this.onTextInput}\n />\n ) : null}\n </div>\n );\n }\n}\n"]}
@@ -2,7 +2,7 @@ import { h } from "@stencil/core";
2
2
  import { FormFieldType } from "../../../lib/form/schema";
3
3
  import { EvaluationApproach, } from "../../../lib/evaluation/constants";
4
4
  import { getAllowedApproachesForFieldType } from "../../../lib/evaluation/field-evaluation-approach";
5
- export const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange, }) => {
5
+ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionSupported = false, onExpectedOutcomeChange, }) => {
6
6
  const emit = (detail) => onExpectedOutcomeChange({
7
7
  detail,
8
8
  });
@@ -15,6 +15,23 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeC
15
15
  optionList,
16
16
  defaultValue: EvaluationApproach.EXACT,
17
17
  });
18
+ const buildOutcomeModeConfig = (index) => ({
19
+ name: `expectedOutcomeMode-${index}`,
20
+ fieldType: FormFieldType.SELECT,
21
+ label: 'Outcome Mode',
22
+ placeholder: 'Select outcome mode',
23
+ required: true,
24
+ optionList: ['static', 'dynamic'],
25
+ defaultValue: 'static',
26
+ });
27
+ const buildResolutionQueryConfig = (index) => ({
28
+ name: `expectedOutcomeResolutionQuery-${index}`,
29
+ fieldType: FormFieldType.TEXT_AREA,
30
+ label: 'Resolution Query',
31
+ placeholder: 'Query used to resolve expected value',
32
+ required: false,
33
+ rows: 2,
34
+ });
18
35
  const renderEvaluationSelector = (field, index) => {
19
36
  const optionList = getAllowedApproachesForFieldType(field.type);
20
37
  return (h("app-select", { config: buildEvaluationConfig(index, optionList), value: field.evaluationParameters?.approach, onValueChange: (e) => emit({
@@ -26,12 +43,17 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeC
26
43
  };
27
44
  return (h("div", { class: "expected-outcome-renderer" }, (fields || []).map((field, index) => {
28
45
  if (field.type === 'textarea') {
46
+ const isDynamic = dynamicResolutionSupported && field.outcomeMode === 'dynamic';
29
47
  const config = {
30
48
  name: `expectedOutcome-${index}`,
31
49
  fieldType: FormFieldType.TEXT_AREA,
32
50
  label: field.label,
33
- placeholder: field.placeholder,
34
- required: true,
51
+ placeholder: isDynamic ? 'Resolved on run' : field.placeholder,
52
+ required: !isDynamic,
53
+ readOnly: isDynamic,
54
+ helpText: isDynamic
55
+ ? 'Filled automatically when the test is run'
56
+ : undefined,
35
57
  rows: field.rows || 2,
36
58
  };
37
59
  return (h("div", { class: "expected-outcome-renderer__group" }, h("app-textarea", { config: config, value: field.value, onValueChange: (e) => emit({
@@ -39,7 +61,18 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeC
39
61
  index,
40
62
  operation: 'set-value',
41
63
  value: e.detail.value,
42
- }) }), renderEvaluationSelector(field, index)));
64
+ }) }), dynamicResolutionSupported && (h("app-select", { config: buildOutcomeModeConfig(index), value: field.outcomeMode || 'static', onValueChange: (e) => emit({
65
+ testCaseId,
66
+ index,
67
+ operation: 'set-outcome-mode',
68
+ value: e.detail.value,
69
+ }) })), dynamicResolutionSupported &&
70
+ field.outcomeMode === 'dynamic' && (h("app-textarea", { config: buildResolutionQueryConfig(index), value: field.resolutionQuery || '', onValueChange: (e) => emit({
71
+ testCaseId,
72
+ index,
73
+ operation: 'set-resolution-query',
74
+ value: e.detail.value,
75
+ }) })), !isDynamic && renderEvaluationSelector(field, index)));
43
76
  }
44
77
  if (field.type === 'chips-input') {
45
78
  const config = {
@@ -1 +1 @@
1
- {"version":3,"file":"expected-outcome-renderer.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/expected-outcome-renderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport {\n ExpectedOutcomeField,\n} from '../../../types/llm-test-runner';\nimport { ChipsConfig, FormFieldType, SelectConfig, TextAreaConfig } from '../../../lib/form/schema';\nimport {\n EvaluationApproach,\n} from '../../../lib/evaluation/constants';\nimport { getAllowedApproachesForFieldType } from '../../../lib/evaluation/field-evaluation-approach';\nimport { ExpectedOutcomeChange } from '../../../lib/test-cases/test-case-mutations';\n\nexport type ExpectedOutcomeChangeDetail = {\n testCaseId: string;\n} & ExpectedOutcomeChange;\n\ninterface ExpectedOutcomeRendererProps {\n testCaseId: string;\n fields: ExpectedOutcomeField[];\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n}\n\nexport const ExpectedOutcomeRenderer: FunctionalComponent<ExpectedOutcomeRendererProps> = ({\n testCaseId,\n fields,\n onExpectedOutcomeChange,\n}) => {\n const emit = (detail: ExpectedOutcomeChangeDetail) =>\n onExpectedOutcomeChange({\n detail,\n } as CustomEvent<ExpectedOutcomeChangeDetail>);\n\n const buildEvaluationConfig = (\n index: number,\n optionList: string[],\n ): SelectConfig => ({\n name: `expectedOutcomeEvaluation-${index}`,\n fieldType: FormFieldType.SELECT,\n label: 'Evaluation Approach',\n placeholder: 'Select evaluation approach…',\n required: true,\n optionList,\n defaultValue: EvaluationApproach.EXACT,\n });\n\n const renderEvaluationSelector = (\n field: ExpectedOutcomeField,\n index: number,\n ) => {\n const optionList = getAllowedApproachesForFieldType(field.type);\n\n return (\n <app-select\n config={buildEvaluationConfig(index, optionList)}\n value={field.evaluationParameters?.approach}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-evaluation-approach',\n value: e.detail.value as EvaluationApproach,\n })\n }\n />\n );\n };\n\n return (\n <div class=\"expected-outcome-renderer\">\n {(fields || []).map((field, index) => {\n if (field.type === 'textarea') {\n const config: TextAreaConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.TEXT_AREA,\n label: field.label,\n placeholder: field.placeholder,\n required: true,\n rows: field.rows || 2,\n };\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-textarea\n config={config}\n value={field.value}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: e.detail.value,\n })\n }\n />\n {renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n if (field.type === 'chips-input') {\n const config: ChipsConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.CHIPS,\n label: field.label,\n placeholder: field.placeholder,\n required: true,\n };\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-chips\n config={config}\n value={field.value}\n onAddChip={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'add-chip',\n value: e.detail.value,\n })\n }\n onRemoveChip={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'remove-chip',\n value: e.detail.value,\n })\n }\n />\n {renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n if (field.type === 'select') {\n const config: SelectConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.SELECT,\n label: field.label,\n placeholder: field.placeholder,\n required: true,\n optionList: field.options,\n };\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-select\n config={config}\n value={field.value}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: e.detail.value,\n })\n }\n />\n {renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <div class=\"expected-outcome-renderer__text\">\n <label>{field.label}</label>\n <input\n type=\"text\"\n value={field.value}\n placeholder={field.placeholder}\n onInput={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: (e.target as HTMLInputElement).value,\n })\n }\n />\n </div>\n {renderEvaluationSelector(field, index)}\n </div>\n );\n })}\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"expected-outcome-renderer.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/expected-outcome-renderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport {\n ExpectedOutcomeField,\n type ExpectedOutcomeMode,\n} from '../../../types/llm-test-runner';\nimport { ChipsConfig, FormFieldType, SelectConfig, TextAreaConfig } from '../../../lib/form/schema';\nimport {\n EvaluationApproach,\n} from '../../../lib/evaluation/constants';\nimport { getAllowedApproachesForFieldType } from '../../../lib/evaluation/field-evaluation-approach';\nimport { ExpectedOutcomeChange } from '../../../lib/test-cases/test-case-mutations';\n\nexport type ExpectedOutcomeChangeDetail = {\n testCaseId: string;\n} & ExpectedOutcomeChange;\n\ninterface ExpectedOutcomeRendererProps {\n testCaseId: string;\n fields: ExpectedOutcomeField[];\n dynamicResolutionSupported?: boolean;\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n}\n\nexport const ExpectedOutcomeRenderer: FunctionalComponent<ExpectedOutcomeRendererProps> = ({\n testCaseId,\n fields,\n dynamicResolutionSupported = false,\n onExpectedOutcomeChange,\n}) => {\n const emit = (detail: ExpectedOutcomeChangeDetail) =>\n onExpectedOutcomeChange({\n detail,\n } as CustomEvent<ExpectedOutcomeChangeDetail>);\n\n const buildEvaluationConfig = (\n index: number,\n optionList: string[],\n ): SelectConfig => ({\n name: `expectedOutcomeEvaluation-${index}`,\n fieldType: FormFieldType.SELECT,\n label: 'Evaluation Approach',\n placeholder: 'Select evaluation approach…',\n required: true,\n optionList,\n defaultValue: EvaluationApproach.EXACT,\n });\n\n const buildOutcomeModeConfig = (index: number): SelectConfig => ({\n name: `expectedOutcomeMode-${index}`,\n fieldType: FormFieldType.SELECT,\n label: 'Outcome Mode',\n placeholder: 'Select outcome mode',\n required: true,\n optionList: ['static', 'dynamic'],\n defaultValue: 'static',\n });\n\n const buildResolutionQueryConfig = (index: number): TextAreaConfig => ({\n name: `expectedOutcomeResolutionQuery-${index}`,\n fieldType: FormFieldType.TEXT_AREA,\n label: 'Resolution Query',\n placeholder: 'Query used to resolve expected value',\n required: false,\n rows: 2,\n });\n\n const renderEvaluationSelector = (\n field: ExpectedOutcomeField,\n index: number,\n ) => {\n const optionList = getAllowedApproachesForFieldType(field.type);\n\n return (\n <app-select\n config={buildEvaluationConfig(index, optionList)}\n value={field.evaluationParameters?.approach}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-evaluation-approach',\n value: e.detail.value as EvaluationApproach,\n })\n }\n />\n );\n };\n\n return (\n <div class=\"expected-outcome-renderer\">\n {(fields || []).map((field, index) => {\n if (field.type === 'textarea') {\n const isDynamic =\n dynamicResolutionSupported && field.outcomeMode === 'dynamic';\n const config: TextAreaConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.TEXT_AREA,\n label: field.label,\n placeholder: isDynamic ? 'Resolved on run' : field.placeholder,\n required: !isDynamic,\n readOnly: isDynamic,\n helpText: isDynamic\n ? 'Filled automatically when the test is run'\n : undefined,\n rows: field.rows || 2,\n };\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-textarea\n config={config}\n value={field.value}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: e.detail.value,\n })\n }\n />\n {dynamicResolutionSupported && (\n <app-select\n config={buildOutcomeModeConfig(index)}\n value={field.outcomeMode || 'static'}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-outcome-mode',\n value: e.detail.value as ExpectedOutcomeMode,\n })\n }\n />\n )}\n {dynamicResolutionSupported &&\n field.outcomeMode === 'dynamic' && (\n <app-textarea\n config={buildResolutionQueryConfig(index)}\n value={field.resolutionQuery || ''}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-resolution-query',\n value: e.detail.value,\n })\n }\n />\n )}\n {!isDynamic && renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n if (field.type === 'chips-input') {\n const config: ChipsConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.CHIPS,\n label: field.label,\n placeholder: field.placeholder,\n required: true,\n };\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-chips\n config={config}\n value={field.value}\n onAddChip={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'add-chip',\n value: e.detail.value,\n })\n }\n onRemoveChip={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'remove-chip',\n value: e.detail.value,\n })\n }\n />\n {renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n if (field.type === 'select') {\n const config: SelectConfig = {\n name: `expectedOutcome-${index}`,\n fieldType: FormFieldType.SELECT,\n label: field.label,\n placeholder: field.placeholder,\n required: true,\n optionList: field.options,\n };\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <app-select\n config={config}\n value={field.value}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: e.detail.value,\n })\n }\n />\n {renderEvaluationSelector(field, index)}\n </div>\n );\n }\n\n return (\n <div class=\"expected-outcome-renderer__group\">\n <div class=\"expected-outcome-renderer__text\">\n <label>{field.label}</label>\n <input\n type=\"text\"\n value={field.value}\n placeholder={field.placeholder}\n onInput={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-value',\n value: (e.target as HTMLInputElement).value,\n })\n }\n />\n </div>\n {renderEvaluationSelector(field, index)}\n </div>\n );\n })}\n </div>\n );\n};\n"]}
@@ -4,7 +4,7 @@ import { EvaluationSummary } from "./evaluation/evaluation-summary";
4
4
  import { RowActions } from "./actions/row-actions";
5
5
  import { FormFieldType } from "../../../lib/form/schema";
6
6
  import { ExpectedOutcomeRenderer, } from "./expected-outcome-renderer";
7
- export const LLMTestCaseRow = ({ testCase, onRun, onDelete, handleTestCaseChange, onExpectedOutcomeChange, }) => {
7
+ export const LLMTestCaseRow = ({ testCase, dynamicResolutionSupported = false, onRun, onDelete, handleTestCaseChange, onExpectedOutcomeChange, onChatHistoryChange, }) => {
8
8
  const questionConfig = {
9
9
  name: 'question',
10
10
  fieldType: FormFieldType.TEXT_AREA,
@@ -20,6 +20,16 @@ export const LLMTestCaseRow = ({ testCase, onRun, onDelete, handleTestCaseChange
20
20
  key: 'question',
21
21
  value: e.detail.value,
22
22
  },
23
- }) }), h(ExpectedOutcomeRenderer, { testCaseId: testCase.id, fields: testCase.expectedOutcome || [], onExpectedOutcomeChange: onExpectedOutcomeChange })), h(ResponseOutput, { output: testCase.output, isRunning: testCase.isRunning }), h(EvaluationSummary, { result: testCase.evaluationResult, isRunning: testCase.isRunning }), h(RowActions, { isRunning: testCase.isRunning, canRun: !!testCase.question.trim(), onRun: () => onRun(testCase), onDelete: () => onDelete(testCase.id) })));
23
+ }) }), h("chat-history", { chatHistoryEnabled: testCase.chatHistory?.enabled ?? false, chatHistoryValue: testCase.chatHistory?.value ?? '', onChatHistoryChange: (e) => {
24
+ const { enabled, value } = e
25
+ .detail;
26
+ onChatHistoryChange({
27
+ detail: {
28
+ testCaseId: testCase.id,
29
+ enabled,
30
+ value,
31
+ },
32
+ });
33
+ } }), h(ExpectedOutcomeRenderer, { testCaseId: testCase.id, fields: testCase.expectedOutcome || [], dynamicResolutionSupported: dynamicResolutionSupported, onExpectedOutcomeChange: onExpectedOutcomeChange })), h(ResponseOutput, { output: testCase.output, isRunning: testCase.isRunning }), h(EvaluationSummary, { result: testCase.evaluationResult, isRunning: testCase.isRunning }), h(RowActions, { isRunning: testCase.isRunning, canRun: !!testCase.question.trim(), onRun: () => onRun(testCase), onDelete: () => onDelete(testCase.id) })));
24
34
  };
25
35
  //# sourceMappingURL=llm-test-case-row.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm-test-case-row.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/llm-test-case-row.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAkB,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAEL,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAcrC,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,oBAAoB,EACpB,uBAAuB,GACxB,EAAE,EAAE;IACH,MAAM,cAAc,GAAmB;QACrC,IAAI,EAAE,UAAU;QAChB,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,6BAA6B;QAC1C,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,CAAC;KACR,CAAC;IACF,OAAO,CACL,WAAK,KAAK,EAAC,eAAe,EAAC,GAAG,EAAE,QAAQ,CAAC,EAAE;QACzC,WAAK,KAAK,EAAC,6BAA6B;YACtC,oBACE,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,QAAQ,CAAC,QAAQ,EACxB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CACnB,oBAAoB,CAAC;oBACnB,MAAM,EAAE;wBACN,UAAU,EAAE,QAAQ,CAAC,EAAE;wBACvB,GAAG,EAAE,UAAU;wBACf,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;qBACtB;iBACiE,CAAC,GAEvE;YACF,EAAC,uBAAuB,IACtB,UAAU,EAAE,QAAQ,CAAC,EAAE,EACvB,MAAM,EAAE,QAAQ,CAAC,eAAe,IAAI,EAAE,EACtC,uBAAuB,EAAE,uBAAuB,GAChD,CACE;QAEN,EAAC,cAAc,IAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,GAAI;QAE1E,EAAC,iBAAiB,IAChB,MAAM,EAAE,QAAQ,CAAC,gBAAgB,EACjC,SAAS,EAAE,QAAQ,CAAC,SAAS,GAC7B;QAEF,EAAC,UAAU,IACT,SAAS,EAAE,QAAQ,CAAC,SAAS,EAC7B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,GACrC,CACE,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport { TestCase } from '../../../types/llm-test-runner';\nimport { ResponseOutput } from './output/response-output';\nimport { EvaluationSummary } from './evaluation/evaluation-summary';\nimport { RowActions } from './actions/row-actions';\nimport { FormFieldType, TextAreaConfig } from '../../../lib/form/schema';\nimport {\n ExpectedOutcomeChangeDetail,\n ExpectedOutcomeRenderer,\n} from './expected-outcome-renderer';\n\nexport interface LLMTestCaseRowProps {\n testCase: TestCase;\n onRun: (testCase: TestCase) => void;\n onDelete: (id: string) => void;\n handleTestCaseChange: (\n e: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => void;\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n}\n\nexport const LLMTestCaseRow: FunctionalComponent<LLMTestCaseRowProps> = ({\n testCase,\n onRun,\n onDelete,\n handleTestCaseChange,\n onExpectedOutcomeChange,\n}) => {\n const questionConfig: TextAreaConfig = {\n name: 'question',\n fieldType: FormFieldType.TEXT_AREA,\n type: 'text',\n label: 'Question',\n placeholder: 'Enter your question here...',\n required: true,\n rows: 3,\n };\n return (\n <div class=\"test-case-row\" key={testCase.id}>\n <div class=\"test-case-row__input-column\">\n <app-textarea\n config={questionConfig}\n value={testCase.question}\n onValueChange={(e) =>\n handleTestCaseChange({\n detail: {\n testCaseId: testCase.id,\n key: 'question',\n value: e.detail.value,\n },\n } as CustomEvent<{ testCaseId: string; key: string; value: string }>)\n }\n />\n <ExpectedOutcomeRenderer\n testCaseId={testCase.id}\n fields={testCase.expectedOutcome || []}\n onExpectedOutcomeChange={onExpectedOutcomeChange}\n />\n </div>\n\n <ResponseOutput output={testCase.output} isRunning={testCase.isRunning} />\n\n <EvaluationSummary\n result={testCase.evaluationResult}\n isRunning={testCase.isRunning}\n />\n\n <RowActions\n isRunning={testCase.isRunning}\n canRun={!!testCase.question.trim()}\n onRun={() => onRun(testCase)}\n onDelete={() => onDelete(testCase.id)}\n />\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"llm-test-case-row.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/llm-test-case-row.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAkB,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAEL,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAqBrC,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,QAAQ,EACR,0BAA0B,GAAG,KAAK,EAClC,KAAK,EACL,QAAQ,EACR,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,GACpB,EAAE,EAAE;IACH,MAAM,cAAc,GAAmB;QACrC,IAAI,EAAE,UAAU;QAChB,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,6BAA6B;QAC1C,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,CAAC;KACR,CAAC;IACF,OAAO,CACL,WAAK,KAAK,EAAC,eAAe,EAAC,GAAG,EAAE,QAAQ,CAAC,EAAE;QACzC,WAAK,KAAK,EAAC,6BAA6B;YACtC,oBACE,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,QAAQ,CAAC,QAAQ,EACxB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CACnB,oBAAoB,CAAC;oBACnB,MAAM,EAAE;wBACN,UAAU,EAAE,QAAQ,CAAC,EAAE;wBACvB,GAAG,EAAE,UAAU;wBACf,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;qBACtB;iBACiE,CAAC,GAEvE;YACF,oBACE,kBAAkB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,IAAI,KAAK,EAC1D,gBAAgB,EAAE,QAAQ,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,EACnD,mBAAmB,EAAE,CAAC,CAAQ,EAAE,EAAE;oBAChC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAI,CAA0C;yBACnE,MAAM,CAAC;oBACV,mBAAmB,CAAC;wBAClB,MAAM,EAAE;4BACN,UAAU,EAAE,QAAQ,CAAC,EAAE;4BACvB,OAAO;4BACP,KAAK;yBACN;qBACyC,CAAC,CAAC;gBAChD,CAAC,GACD;YACF,EAAC,uBAAuB,IACtB,UAAU,EAAE,QAAQ,CAAC,EAAE,EACvB,MAAM,EAAE,QAAQ,CAAC,eAAe,IAAI,EAAE,EACtC,0BAA0B,EAAE,0BAA0B,EACtD,uBAAuB,EAAE,uBAAuB,GAChD,CACE;QAEN,EAAC,cAAc,IAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,GAAI;QAE1E,EAAC,iBAAiB,IAChB,MAAM,EAAE,QAAQ,CAAC,gBAAgB,EACjC,SAAS,EAAE,QAAQ,CAAC,SAAS,GAC7B;QAEF,EAAC,UAAU,IACT,SAAS,EAAE,QAAQ,CAAC,SAAS,EAC7B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,GACrC,CACE,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport { TestCase } from '../../../types/llm-test-runner';\nimport { ResponseOutput } from './output/response-output';\nimport { EvaluationSummary } from './evaluation/evaluation-summary';\nimport { RowActions } from './actions/row-actions';\nimport { FormFieldType, TextAreaConfig } from '../../../lib/form/schema';\nimport {\n ExpectedOutcomeChangeDetail,\n ExpectedOutcomeRenderer,\n} from './expected-outcome-renderer';\nimport type { ChatHistoryChangeDetail } from './chat-history';\n\nexport type ChatHistoryRowChangeDetail = {\n testCaseId: string;\n} & ChatHistoryChangeDetail;\n\nexport interface LLMTestCaseRowProps {\n testCase: TestCase;\n dynamicResolutionSupported?: boolean;\n onRun: (testCase: TestCase) => void;\n onDelete: (id: string) => void;\n handleTestCaseChange: (\n e: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => void;\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n onChatHistoryChange: (e: CustomEvent<ChatHistoryRowChangeDetail>) => void;\n}\n\nexport const LLMTestCaseRow: FunctionalComponent<LLMTestCaseRowProps> = ({\n testCase,\n dynamicResolutionSupported = false,\n onRun,\n onDelete,\n handleTestCaseChange,\n onExpectedOutcomeChange,\n onChatHistoryChange,\n}) => {\n const questionConfig: TextAreaConfig = {\n name: 'question',\n fieldType: FormFieldType.TEXT_AREA,\n type: 'text',\n label: 'Question',\n placeholder: 'Enter your question here...',\n required: true,\n rows: 3,\n };\n return (\n <div class=\"test-case-row\" key={testCase.id}>\n <div class=\"test-case-row__input-column\">\n <app-textarea\n config={questionConfig}\n value={testCase.question}\n onValueChange={(e) =>\n handleTestCaseChange({\n detail: {\n testCaseId: testCase.id,\n key: 'question',\n value: e.detail.value,\n },\n } as CustomEvent<{ testCaseId: string; key: string; value: string }>)\n }\n />\n <chat-history\n chatHistoryEnabled={testCase.chatHistory?.enabled ?? false}\n chatHistoryValue={testCase.chatHistory?.value ?? ''}\n onChatHistoryChange={(e: Event) => {\n const { enabled, value } = (e as CustomEvent<ChatHistoryChangeDetail>)\n .detail;\n onChatHistoryChange({\n detail: {\n testCaseId: testCase.id,\n enabled,\n value,\n },\n } as CustomEvent<ChatHistoryRowChangeDetail>);\n }}\n />\n <ExpectedOutcomeRenderer\n testCaseId={testCase.id}\n fields={testCase.expectedOutcome || []}\n dynamicResolutionSupported={dynamicResolutionSupported}\n onExpectedOutcomeChange={onExpectedOutcomeChange}\n />\n </div>\n\n <ResponseOutput output={testCase.output} isRunning={testCase.isRunning} />\n\n <EvaluationSummary\n result={testCase.evaluationResult}\n isRunning={testCase.isRunning}\n />\n\n <RowActions\n isRunning={testCase.isRunning}\n canRun={!!testCase.question.trim()}\n onRun={() => onRun(testCase)}\n onDelete={() => onDelete(testCase.id)}\n />\n </div>\n );\n};\n"]}
@@ -1,7 +1,7 @@
1
1
  import { h } from "@stencil/core";
2
2
  import { LLMTestCaseRow } from "./llm-test-case-row";
3
3
  import { Button } from "../../../lib/ui/button/index";
4
- export const LLMTestCases = ({ testCases, onRun, onDelete, onAddTestCase, handleTestCaseChange, onExpectedOutcomeChange, }) => {
5
- return (h("div", { class: "test-cases" }, h("div", { class: "test-cases__column-headers" }, h("div", { class: "test-cases__column-header" }, "Input"), h("div", { class: "test-cases__column-header" }, "Output"), h("div", { class: "test-cases__column-header" }, "Evaluation"), h("div", { class: "test-cases__column-header" }, "Actions")), testCases.map(testCase => (h(LLMTestCaseRow, { testCase: testCase, onRun: onRun, onDelete: onDelete, handleTestCaseChange: handleTestCaseChange, onExpectedOutcomeChange: onExpectedOutcomeChange }))), h("div", { class: "test-cases__add-section" }, h(Button, { variant: "outline", size: "md", onClick: onAddTestCase }, "+ Add Question"))));
4
+ export const LLMTestCases = ({ testCases, dynamicResolutionSupported = false, onRun, onDelete, onAddTestCase, handleTestCaseChange, onExpectedOutcomeChange, onChatHistoryChange, }) => {
5
+ return (h("div", { class: "test-cases" }, h("div", { class: "test-cases__column-headers" }, h("div", { class: "test-cases__column-header" }, "Input"), h("div", { class: "test-cases__column-header" }, "Output"), h("div", { class: "test-cases__column-header" }, "Evaluation"), h("div", { class: "test-cases__column-header" }, "Actions")), testCases.map(testCase => (h(LLMTestCaseRow, { testCase: testCase, dynamicResolutionSupported: dynamicResolutionSupported, onRun: onRun, onDelete: onDelete, handleTestCaseChange: handleTestCaseChange, onExpectedOutcomeChange: onExpectedOutcomeChange, onChatHistoryChange: onChatHistoryChange }))), h("div", { class: "test-cases__add-section" }, h(Button, { variant: "outline", size: "md", onClick: onAddTestCase }, "+ Add Question"))));
6
6
  };
7
7
  //# sourceMappingURL=llm-test-cases.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm-test-cases.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/llm-test-cases.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAgBtD,MAAM,CAAC,MAAM,YAAY,GAA2C,CAAC,EACnE,SAAS,EACT,KAAK,EACL,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,uBAAuB,GACxB,EAAE,EAAE;IACH,OAAO,CACL,WAAK,KAAK,EAAC,YAAY;QACrB,WAAK,KAAK,EAAC,4BAA4B;YACrC,WAAK,KAAK,EAAC,2BAA2B,YAAY;YAClD,WAAK,KAAK,EAAC,2BAA2B,aAAa;YACnD,WAAK,KAAK,EAAC,2BAA2B,iBAAiB;YACvD,WAAK,KAAK,EAAC,2BAA2B,cAAc,CAChD;QAEL,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CACzB,EAAC,cAAc,IACb,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,oBAAoB,EAAE,oBAAoB,EAC1C,uBAAuB,EAAE,uBAAuB,GAChD,CACH,CAAC;QAEF,WAAK,KAAK,EAAC,yBAAyB;YAClC,EAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,aAAa,qBAEjD,CACL,CACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport { TestCase } from '../../../types/llm-test-runner';\nimport { LLMTestCaseRow } from './llm-test-case-row';\nimport { Button } from '../../../lib/ui/button/index';\nimport { ExpectedOutcomeChangeDetail } from './expected-outcome-renderer';\n\nexport interface LLMTestCasesProps {\n testCases: TestCase[];\n onRun: (testCase: TestCase) => void;\n onDelete: (id: string) => void;\n onAddTestCase: () => void;\n handleTestCaseChange: (\n e: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => void;\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n}\n\nexport const LLMTestCases: FunctionalComponent<LLMTestCasesProps> = ({\n testCases,\n onRun,\n onDelete,\n onAddTestCase,\n handleTestCaseChange,\n onExpectedOutcomeChange,\n}) => {\n return (\n <div class=\"test-cases\">\n <div class=\"test-cases__column-headers\">\n <div class=\"test-cases__column-header\">Input</div>\n <div class=\"test-cases__column-header\">Output</div>\n <div class=\"test-cases__column-header\">Evaluation</div>\n <div class=\"test-cases__column-header\">Actions</div>\n </div>\n\n {testCases.map(testCase => (\n <LLMTestCaseRow\n testCase={testCase}\n onRun={onRun}\n onDelete={onDelete}\n handleTestCaseChange={handleTestCaseChange}\n onExpectedOutcomeChange={onExpectedOutcomeChange}\n />\n ))}\n\n <div class=\"test-cases__add-section\">\n <Button variant=\"outline\" size=\"md\" onClick={onAddTestCase}>\n + Add Question\n </Button>\n </div>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"llm-test-cases.js","sourceRoot":"","sources":["../../../../src/components/llm-test-runner/test-cases/llm-test-cases.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,cAAc,EAA8B,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAkBtD,MAAM,CAAC,MAAM,YAAY,GAA2C,CAAC,EACnE,SAAS,EACT,0BAA0B,GAAG,KAAK,EAClC,KAAK,EACL,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,GACpB,EAAE,EAAE;IACH,OAAO,CACL,WAAK,KAAK,EAAC,YAAY;QACrB,WAAK,KAAK,EAAC,4BAA4B;YACrC,WAAK,KAAK,EAAC,2BAA2B,YAAY;YAClD,WAAK,KAAK,EAAC,2BAA2B,aAAa;YACnD,WAAK,KAAK,EAAC,2BAA2B,iBAAiB;YACvD,WAAK,KAAK,EAAC,2BAA2B,cAAc,CAChD;QAEL,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CACzB,EAAC,cAAc,IACb,QAAQ,EAAE,QAAQ,EAClB,0BAA0B,EAAE,0BAA0B,EACtD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,oBAAoB,EAAE,oBAAoB,EAC1C,uBAAuB,EAAE,uBAAuB,EAChD,mBAAmB,EAAE,mBAAmB,GACxC,CACH,CAAC;QAEF,WAAK,KAAK,EAAC,yBAAyB;YAClC,EAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,aAAa,qBAEjD,CACL,CACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport { TestCase } from '../../../types/llm-test-runner';\nimport { LLMTestCaseRow, ChatHistoryRowChangeDetail } from './llm-test-case-row';\nimport { Button } from '../../../lib/ui/button/index';\nimport { ExpectedOutcomeChangeDetail } from './expected-outcome-renderer';\n\nexport interface LLMTestCasesProps {\n testCases: TestCase[];\n dynamicResolutionSupported?: boolean;\n onRun: (testCase: TestCase) => void;\n onDelete: (id: string) => void;\n onAddTestCase: () => void;\n handleTestCaseChange: (\n e: CustomEvent<{ testCaseId: string; key: string; value: string }>,\n ) => void;\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n onChatHistoryChange: (e: CustomEvent<ChatHistoryRowChangeDetail>) => void;\n}\n\nexport const LLMTestCases: FunctionalComponent<LLMTestCasesProps> = ({\n testCases,\n dynamicResolutionSupported = false,\n onRun,\n onDelete,\n onAddTestCase,\n handleTestCaseChange,\n onExpectedOutcomeChange,\n onChatHistoryChange,\n}) => {\n return (\n <div class=\"test-cases\">\n <div class=\"test-cases__column-headers\">\n <div class=\"test-cases__column-header\">Input</div>\n <div class=\"test-cases__column-header\">Output</div>\n <div class=\"test-cases__column-header\">Evaluation</div>\n <div class=\"test-cases__column-header\">Actions</div>\n </div>\n\n {testCases.map(testCase => (\n <LLMTestCaseRow\n testCase={testCase}\n dynamicResolutionSupported={dynamicResolutionSupported}\n onRun={onRun}\n onDelete={onDelete}\n handleTestCaseChange={handleTestCaseChange}\n onExpectedOutcomeChange={onExpectedOutcomeChange}\n onChatHistoryChange={onChatHistoryChange}\n />\n ))}\n\n <div class=\"test-cases__add-section\">\n <Button variant=\"outline\" size=\"md\" onClick={onAddTestCase}>\n + Add Question\n </Button>\n </div>\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC","sourcesContent":["export { LLMTestRunner } from './components/llm-test-runner/llm-test-runner';\nexport type { TestCase, LLMRequestPayload } from './types/llm-test-runner';\nexport type * from './components.d.ts';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC","sourcesContent":["export { LLMTestRunner } from './components/llm-test-runner/llm-test-runner';\nexport type {\n TestCase,\n TestCaseChatHistory,\n LLMRequestPayload,\n} from './types/llm-test-runner';\nexport type * from './components.d.ts';\n"]}
@@ -18,13 +18,20 @@ export class EvaluationService {
18
18
  console.warn('⚠️ No output to evaluate for test case:', testCase.id);
19
19
  return;
20
20
  }
21
- const fields = (testCase.expectedOutcome || []).map((field, index) => ({
22
- index,
23
- label: field.label,
24
- type: field.type,
25
- expectedValue: getFieldExpectedValue(field),
26
- evaluationParameters: normalizeEvaluationParametersForField(field.type, field.evaluationParameters),
27
- }));
21
+ const fields = (testCase.expectedOutcome || []).flatMap((field, index) => {
22
+ if (field.type === 'textarea' && field.outcomeMode === 'dynamic') {
23
+ return [];
24
+ }
25
+ return [
26
+ {
27
+ index,
28
+ label: field.label,
29
+ type: field.type,
30
+ expectedValue: getFieldExpectedValue(field),
31
+ evaluationParameters: normalizeEvaluationParametersForField(field.type, field.evaluationParameters),
32
+ },
33
+ ];
34
+ });
28
35
  const evaluationRequest = {
29
36
  testCaseId: testCase.id,
30
37
  question: testCase.question,
@@ -1 +1 @@
1
- {"version":3,"file":"evaluation-service.js","sourceRoot":"","sources":["../../../src/lib/evaluation/evaluation-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAO1D,OAAO,EAAE,qCAAqC,EAAE,MAAM,6BAA6B,CAAC;AAEpF;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAsB;IAEpC;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CACpB,QAAkB,EAClB,QAA4C;QAE5C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAA2B,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,GAAG,CACzE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACjB,KAAK;YACL,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,aAAa,EAAE,qBAAqB,CAAC,KAAK,CAAC;YAC3C,oBAAoB,EAAE,qCAAqC,CACzD,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,oBAAoB,CAC3B;SACF,CAAC,CACH,CAAC;QAEF,MAAM,iBAAiB,GAAwB;YAC7C,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,cAAc,EAAE,QAAQ,CAAC,MAAM;YAC/B,MAAM;SACP,CAAC;QAEF,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAChC,iBAAiB,EACjB,CAAC,MAAwB,EAAE,EAAE;YAC3B,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;YACtD,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CACF,CAAC;IACJ,CAAC;CACF;AAED,SAAS,qBAAqB,CAAC,KAA2B;IACxD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC","sourcesContent":["import { LLMEvaluationEngine } from './evaluation-engine';\nimport {\n EvaluationResult,\n FieldEvaluationInput,\n EvaluationRequestV2,\n} from './types';\nimport { TestCase, ExpectedOutcomeField } from '../../types/llm-test-runner';\nimport { normalizeEvaluationParametersForField } from './field-evaluation-approach';\n\n/**\n * Service for evaluating test case responses\n */\nexport class EvaluationService {\n private engine: LLMEvaluationEngine;\n\n constructor() {\n this.engine = new LLMEvaluationEngine();\n }\n\n /**\n * Evaluates a test case response\n * @param testCase - The test case to evaluate\n * @param onResult - Callback to handle the evaluation result\n */\n async evaluateTestCase(\n testCase: TestCase,\n onResult: (result: EvaluationResult) => void,\n ): Promise<void> {\n if (!testCase.output) {\n console.warn('⚠️ No output to evaluate for test case:', testCase.id);\n return;\n }\n\n const fields: FieldEvaluationInput[] = (testCase.expectedOutcome || []).map(\n (field, index) => ({\n index,\n label: field.label,\n type: field.type,\n expectedValue: getFieldExpectedValue(field),\n evaluationParameters: normalizeEvaluationParametersForField(\n field.type,\n field.evaluationParameters,\n ),\n }),\n );\n\n const evaluationRequest: EvaluationRequestV2 = {\n testCaseId: testCase.id,\n question: testCase.question,\n actualResponse: testCase.output,\n fields,\n };\n\n await this.engine.evaluateResponse(\n evaluationRequest,\n (result: EvaluationResult) => {\n console.log('📊 Evaluation result received:', result);\n onResult(result);\n },\n );\n }\n}\n\nfunction getFieldExpectedValue(field: ExpectedOutcomeField): string {\n if (field.type === 'chips-input') {\n return field.value.join(', ');\n }\n return field.value;\n}\n"]}
1
+ {"version":3,"file":"evaluation-service.js","sourceRoot":"","sources":["../../../src/lib/evaluation/evaluation-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAO1D,OAAO,EAAE,qCAAqC,EAAE,MAAM,6BAA6B,CAAC;AAEpF;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAsB;IAEpC;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CACpB,QAAkB,EAClB,QAA4C;QAE5C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAA2B,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,OAAO,CAC7E,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACf,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACjE,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO;gBACL;oBACE,KAAK;oBACL,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,aAAa,EAAE,qBAAqB,CAAC,KAAK,CAAC;oBAC3C,oBAAoB,EAAE,qCAAqC,CACzD,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,oBAAoB,CAC3B;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,MAAM,iBAAiB,GAAwB;YAC7C,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,cAAc,EAAE,QAAQ,CAAC,MAAM;YAC/B,MAAM;SACP,CAAC;QAEF,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAChC,iBAAiB,EACjB,CAAC,MAAwB,EAAE,EAAE;YAC3B,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;YACtD,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CACF,CAAC;IACJ,CAAC;CACF;AAED,SAAS,qBAAqB,CAAC,KAA2B;IACxD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC","sourcesContent":["import { LLMEvaluationEngine } from './evaluation-engine';\nimport {\n EvaluationResult,\n FieldEvaluationInput,\n EvaluationRequestV2,\n} from './types';\nimport { TestCase, ExpectedOutcomeField } from '../../types/llm-test-runner';\nimport { normalizeEvaluationParametersForField } from './field-evaluation-approach';\n\n/**\n * Service for evaluating test case responses\n */\nexport class EvaluationService {\n private engine: LLMEvaluationEngine;\n\n constructor() {\n this.engine = new LLMEvaluationEngine();\n }\n\n /**\n * Evaluates a test case response\n * @param testCase - The test case to evaluate\n * @param onResult - Callback to handle the evaluation result\n */\n async evaluateTestCase(\n testCase: TestCase,\n onResult: (result: EvaluationResult) => void,\n ): Promise<void> {\n if (!testCase.output) {\n console.warn('⚠️ No output to evaluate for test case:', testCase.id);\n return;\n }\n\n const fields: FieldEvaluationInput[] = (testCase.expectedOutcome || []).flatMap(\n (field, index) => {\n if (field.type === 'textarea' && field.outcomeMode === 'dynamic') {\n return [];\n }\n\n return [\n {\n index,\n label: field.label,\n type: field.type,\n expectedValue: getFieldExpectedValue(field),\n evaluationParameters: normalizeEvaluationParametersForField(\n field.type,\n field.evaluationParameters,\n ),\n },\n ];\n },\n );\n\n const evaluationRequest: EvaluationRequestV2 = {\n testCaseId: testCase.id,\n question: testCase.question,\n actualResponse: testCase.output,\n fields,\n };\n\n await this.engine.evaluateResponse(\n evaluationRequest,\n (result: EvaluationResult) => {\n console.log('📊 Evaluation result received:', result);\n onResult(result);\n },\n );\n }\n}\n\nfunction getFieldExpectedValue(field: ExpectedOutcomeField): string {\n if (field.type === 'chips-input') {\n return field.value.join(', ');\n }\n return field.value;\n}\n"]}
@@ -29,7 +29,7 @@ export class AppChips {
29
29
  name: c.name,
30
30
  autocomplete: c.autocomplete,
31
31
  };
32
- return (h("div", { key: '4f081007c0b11fb20bd74644eb063a6dd5a45d98', class: "app-chips" }, c.label && (h("label", { key: '3934ec12898c947b163a15494330a9326fe3d6f1', class: "app-chips__label", htmlFor: c.name }, c.label)), h("div", { key: 'cba194df0033a5951f568875e4686a76c9c28438', class: "app-chips__container" }, this.value.map((chip) => (h("span", { class: "app-chips__chip", key: chip }, c.type === 'url' ? (h("a", { href: chip, target: "_blank", rel: "noopener noreferrer", class: "app-chips__link" }, chip)) : (chip), h("button", { class: "app-chips__remove", type: "button", onClick: () => this.emitRemoveChip(chip) }, "\u00D7")))), h("input", { key: '11c9e7f326c37cb3a413e9124926ca88eefb1911', class: "app-chips__input", type: c.type || 'text', ...allowedAttrs, onKeyDown: (e) => {
32
+ return (h("div", { key: 'fb7d4d5444e9c9ac33c56aec88e3e10ed103c8be', class: "app-chips" }, c.label && (h("label", { key: '2d0041b3a137fecddef2273eac3792b5e8de27ab', class: "app-chips__label", htmlFor: c.name }, c.label)), h("div", { key: 'f73b1105e567b233626073e05b9da712689e7b12', class: "app-chips__container" }, this.value.map((chip) => (h("span", { class: "app-chips__chip", key: chip }, c.type === 'url' ? (h("a", { href: chip, target: "_blank", rel: "noopener noreferrer", class: "app-chips__link" }, chip)) : (chip), h("button", { class: "app-chips__remove", type: "button", onClick: () => this.emitRemoveChip(chip) }, "\u00D7")))), h("input", { key: '7676ff95531b34d10cbf9402e72a723e7e123e0e', class: "app-chips__input", type: c.type || 'text', ...allowedAttrs, onKeyDown: (e) => {
33
33
  if (e.key === 'Enter') {
34
34
  const input = e.target;
35
35
  const val = input.value.trim();
@@ -14,7 +14,7 @@ export class AppSelect {
14
14
  placeholder: c.placeholder,
15
15
  autocomplete: c.autocomplete,
16
16
  };
17
- return (h("div", { key: '4d9d250026b51799b073ae828c7d15563ec27c22', class: "app-select" }, c.label && (h("label", { key: '53e101427e78063bd6ed671a31919bbe373c5563', class: "app-select__label", htmlFor: c.name }, c.label)), h("div", { key: '28b18245c261a3766948ed7d151c356b8faeb4cf' }, h("select", { key: 'eed9bcb9fc3e00ae62c681a37e967815d350d5fb', ...allowedAttrs, class: "app-select__select", onInput: (e) => {
17
+ return (h("div", { key: '968f0fffe1eff976ac7e00f02db6fb84aa529de4', class: "app-select" }, c.label && (h("label", { key: 'dac02d2335754ff5d6ce6ba1df5777f8b019cfae', class: "app-select__label", htmlFor: c.name }, c.label)), h("div", { key: 'c92698199479bbdde1cfd559d69fc97e54d2862a' }, h("select", { key: '6e9b27b034d057921f52fbd12653c5ef1b6af1bc', ...allowedAttrs, class: "app-select__select", onInput: (e) => {
18
18
  const raw = e.target.value;
19
19
  const matched = c.optionList.find(opt => String(opt) === raw);
20
20
  this.valueChange.emit({
@@ -30,6 +30,23 @@
30
30
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
31
31
  }
32
32
 
33
+ .textarea-wrapper--read-only .textarea-label {
34
+ color: var(--muted-foreground);
35
+ }
36
+
37
+ .textarea-element:read-only {
38
+ background: var(--muted);
39
+ color: var(--muted-foreground);
40
+ border-color: var(--border);
41
+ cursor: not-allowed;
42
+ resize: none;
43
+ }
44
+
45
+ .textarea-element:read-only:focus {
46
+ border-color: var(--border);
47
+ box-shadow: none;
48
+ }
49
+
33
50
  .help-text {
34
51
  margin-top: var(--spacing-1);
35
52
  font-size: var(--font-size-xs);
@@ -21,7 +21,10 @@ export class AppTextarea {
21
21
  name: c.name,
22
22
  autocomplete: c.autocomplete,
23
23
  };
24
- return (h("div", { key: 'cc0073d70c9de40a8a12a1cabc3c1c06ac8c1863', class: "textarea-wrapper" }, c.label && (h("label", { key: 'a886cf95f25afee2e09ebcbc4dc62d2c9bca5ee0', class: "textarea-label", htmlFor: c.name }, c.label)), h("textarea", { key: 'c16b072269c450f3e09764b23cdfdaf966975977', ...allowedAttrs, class: "textarea-element", value: this.value, onInput: this.handleChange }), c.helpText && h("p", { key: '9df941aa068b937d90f9a5f2a841a8fe426b3371', class: "help-text" }, c.helpText)));
24
+ return (h("div", { key: 'f0749b1f2badf8434272da9fb37b354b42ba988b', class: {
25
+ 'textarea-wrapper': true,
26
+ 'textarea-wrapper--read-only': !!c.readOnly,
27
+ } }, c.label && (h("label", { key: '3448c838bcf9e962df005eae8fc313d216497c35', class: "textarea-label", htmlFor: c.name }, c.label)), h("textarea", { key: 'b4ee67a24fa71b0fa042625f943b0e226a6d14b7', ...allowedAttrs, class: "textarea-element", value: this.value, onInput: this.handleChange }), c.helpText && h("p", { key: 'fb6263c32e6cc5e36dbc77344c31487d63d51a1c', class: "help-text" }, c.helpText)));
25
28
  }
26
29
  static get is() { return "app-textarea"; }
27
30
  static get encapsulation() { return "shadow"; }
@@ -1 +1 @@
1
- {"version":3,"file":"app-textarea.js","sourceRoot":"","sources":["../../../../src/lib/form/components/app-textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAgB,IAAI,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAQxE,MAAM,OAAO,WAAW;IACd,KAAK,CAAS;IACd,MAAM,CAAiB;IAEtB,WAAW,CAAkC;IAE9C,YAAY,GAAG,CAAC,CAAQ,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,CAAC,CAAC,MAA6B,CAAC;QAE/C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAEtB,MAAM,YAAY,GAAG;YACnB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,EAAE,EAAE,CAAC,CAAC,IAAI;YACV,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC;QAEF,OAAO,CACL,4DAAK,KAAK,EAAC,kBAAkB;YAC1B,CAAC,CAAC,KAAK,IAAI,CACV,8DAAO,KAAK,EAAC,gBAAgB,EAAC,OAAO,EAAE,CAAC,CAAC,IAAI,IAC1C,CAAC,CAAC,KAAK,CACF,CACT;YAED,oEACM,YAAY,EAChB,KAAK,EAAC,kBAAkB,EACxB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,OAAO,EAAE,IAAI,CAAC,YAAY,GAChB;YAEX,CAAC,CAAC,QAAQ,IAAI,0DAAG,KAAK,EAAC,WAAW,IAAE,CAAC,CAAC,QAAQ,CAAK,CAChD,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';\nimport { TextAreaConfig } from '../schema';\n\n@Component({\n tag: 'app-textarea',\n styleUrl: 'app-textarea.css',\n shadow: true,\n})\nexport class AppTextarea {\n @Prop() value: string;\n @Prop() config: TextAreaConfig;\n\n @Event() valueChange: EventEmitter<{ value: string }>;\n\n private handleChange = (e: Event) => {\n const target = e.target as HTMLTextAreaElement;\n\n this.valueChange.emit({\n value: target.value,\n });\n };\n\n render() {\n const c = this.config;\n\n const allowedAttrs = {\n placeholder: c.placeholder,\n required: c.required,\n disabled: c.disabled,\n readOnly: c.readOnly,\n rows: c.rows,\n id: c.name,\n name: c.name,\n autocomplete: c.autocomplete,\n };\n\n return (\n <div class=\"textarea-wrapper\">\n {c.label && (\n <label class=\"textarea-label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <textarea\n {...allowedAttrs}\n class=\"textarea-element\"\n value={this.value}\n onInput={this.handleChange}\n ></textarea>\n\n {c.helpText && <p class=\"help-text\">{c.helpText}</p>}\n </div>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"app-textarea.js","sourceRoot":"","sources":["../../../../src/lib/form/components/app-textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAgB,IAAI,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAQxE,MAAM,OAAO,WAAW;IACd,KAAK,CAAS;IACd,MAAM,CAAiB;IAEtB,WAAW,CAAkC;IAE9C,YAAY,GAAG,CAAC,CAAQ,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,CAAC,CAAC,MAA6B,CAAC;QAE/C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAEtB,MAAM,YAAY,GAAG;YACnB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,EAAE,EAAE,CAAC,CAAC,IAAI;YACV,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC;QAEF,OAAO,CACL,4DACE,KAAK,EAAE;gBACL,kBAAkB,EAAE,IAAI;gBACxB,6BAA6B,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ;aAC5C;YAEA,CAAC,CAAC,KAAK,IAAI,CACV,8DAAO,KAAK,EAAC,gBAAgB,EAAC,OAAO,EAAE,CAAC,CAAC,IAAI,IAC1C,CAAC,CAAC,KAAK,CACF,CACT;YAED,oEACM,YAAY,EAChB,KAAK,EAAC,kBAAkB,EACxB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,OAAO,EAAE,IAAI,CAAC,YAAY,GAChB;YAEX,CAAC,CAAC,QAAQ,IAAI,0DAAG,KAAK,EAAC,WAAW,IAAE,CAAC,CAAC,QAAQ,CAAK,CAChD,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';\nimport { TextAreaConfig } from '../schema';\n\n@Component({\n tag: 'app-textarea',\n styleUrl: 'app-textarea.css',\n shadow: true,\n})\nexport class AppTextarea {\n @Prop() value: string;\n @Prop() config: TextAreaConfig;\n\n @Event() valueChange: EventEmitter<{ value: string }>;\n\n private handleChange = (e: Event) => {\n const target = e.target as HTMLTextAreaElement;\n\n this.valueChange.emit({\n value: target.value,\n });\n };\n\n render() {\n const c = this.config;\n\n const allowedAttrs = {\n placeholder: c.placeholder,\n required: c.required,\n disabled: c.disabled,\n readOnly: c.readOnly,\n rows: c.rows,\n id: c.name,\n name: c.name,\n autocomplete: c.autocomplete,\n };\n\n return (\n <div\n class={{\n 'textarea-wrapper': true,\n 'textarea-wrapper--read-only': !!c.readOnly,\n }}\n >\n {c.label && (\n <label class=\"textarea-label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <textarea\n {...allowedAttrs}\n class=\"textarea-element\"\n value={this.value}\n onInput={this.handleChange}\n ></textarea>\n\n {c.helpText && <p class=\"help-text\">{c.helpText}</p>}\n </div>\n );\n }\n}\n"]}
@@ -8,6 +8,10 @@ export function formatTestSuiteAsJson(testCases) {
8
8
  id: testCase.id,
9
9
  question: testCase.question,
10
10
  expectedOutcome: testCase.expectedOutcome,
11
+ chatHistory: {
12
+ enabled: testCase.chatHistory.enabled,
13
+ value: testCase.chatHistory.value,
14
+ },
11
15
  }));
12
16
  return JSON.stringify(exportData, null, 2);
13
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"test-suite-exporter.js","sourceRoot":"","sources":["../../../src/lib/import-export/test-suite-exporter.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAqB;IACzD,MAAM,UAAU,GAA0B,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnE,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,eAAe,EAAE,QAAQ,CAAC,eAAe;KAC1C,CAAC,CAAC,CAAC;IAEJ,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { ExpectedOutcomeField, TestCase } from '../../types/llm-test-runner';\n\nexport interface TestSuiteExportData {\n id: string;\n question: string;\n expectedOutcome: ExpectedOutcomeField[];\n}\n\n/**\n * Formats test cases as a JSON string suitable for saving as a test suite\n * @param testCases - Array of test cases to format\n * @returns JSON string representation of the test suite\n */\nexport function formatTestSuiteAsJson(testCases: TestCase[]): string {\n const exportData: TestSuiteExportData[] = testCases.map(testCase => ({\n id: testCase.id,\n question: testCase.question,\n expectedOutcome: testCase.expectedOutcome,\n }));\n\n return JSON.stringify(exportData, null, 2);\n}\n"]}
1
+ {"version":3,"file":"test-suite-exporter.js","sourceRoot":"","sources":["../../../src/lib/import-export/test-suite-exporter.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAqB;IACzD,MAAM,UAAU,GAA0B,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnE,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,eAAe,EAAE,QAAQ,CAAC,eAAe;QACzC,WAAW,EAAE;YACX,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,OAAO;YACrC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,KAAK;SAClC;KACF,CAAC,CAAC,CAAC;IAEJ,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { ExpectedOutcomeField, TestCase } from '../../types/llm-test-runner';\n\nexport interface TestSuiteExportData {\n id: string;\n question: string;\n expectedOutcome: ExpectedOutcomeField[];\n chatHistory: {\n enabled: boolean;\n value: string;\n };\n}\n\n/**\n * Formats test cases as a JSON string suitable for saving as a test suite\n * @param testCases - Array of test cases to format\n * @returns JSON string representation of the test suite\n */\nexport function formatTestSuiteAsJson(testCases: TestCase[]): string {\n const exportData: TestSuiteExportData[] = testCases.map(testCase => ({\n id: testCase.id,\n question: testCase.question,\n expectedOutcome: testCase.expectedOutcome,\n chatHistory: {\n enabled: testCase.chatHistory.enabled,\n value: testCase.chatHistory.value,\n },\n }));\n\n return JSON.stringify(exportData, null, 2);\n}\n"]}