llm-testrunner-components 1.2.3 → 1.3.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.
Files changed (110) hide show
  1. package/README.md +9 -5
  2. package/dist/cjs/{app-chips_4.cjs.entry.js → app-chips_5.cjs.entry.js} +38 -6
  3. package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
  4. package/dist/cjs/index.cjs.js +499 -68
  5. package/dist/cjs/index.cjs.js.map +1 -1
  6. package/dist/cjs/llm-testrunner.cjs.js +1 -1
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/collection/collection-manifest.json +1 -0
  9. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +22 -12
  10. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
  11. package/dist/collection/components/llm-test-runner/llm-test-runner.js +59 -15
  12. package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
  13. package/dist/collection/components/llm-test-runner/test-cases/chat-history.css +101 -0
  14. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js +105 -0
  15. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js.map +1 -0
  16. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +45 -5
  17. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
  18. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.css +21 -0
  19. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +12 -2
  20. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
  21. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
  22. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
  23. package/dist/collection/components/llm-test-runner/test-cases/output/response-output.js +1 -1
  24. package/dist/collection/components/llm-test-runner/test-cases/output/response-output.js.map +1 -1
  25. package/dist/collection/index.js.map +1 -1
  26. package/dist/collection/lib/evaluation/actual-value-resolver.js +52 -0
  27. package/dist/collection/lib/evaluation/actual-value-resolver.js.map +1 -0
  28. package/dist/collection/lib/evaluation/evaluation-engine.js +1 -1
  29. package/dist/collection/lib/evaluation/evaluation-engine.js.map +1 -1
  30. package/dist/collection/lib/evaluation/evaluation-service.js +55 -17
  31. package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
  32. package/dist/collection/lib/evaluation/types.js.map +1 -1
  33. package/dist/collection/lib/form/components/app-chips.js +1 -1
  34. package/dist/collection/lib/form/components/app-select.js +1 -1
  35. package/dist/collection/lib/form/components/app-textarea.js +2 -2
  36. package/dist/collection/lib/import-export/test-suite-exporter.js +4 -0
  37. package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
  38. package/dist/collection/lib/import-export/test-suite-importer.js +7 -1
  39. package/dist/collection/lib/import-export/test-suite-importer.js.map +1 -1
  40. package/dist/collection/lib/test-cases/test-case-factory.js +7 -0
  41. package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
  42. package/dist/collection/lib/test-cases/test-case-mutations.js +58 -23
  43. package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
  44. package/dist/collection/schemas/expected-outcome.js +39 -0
  45. package/dist/collection/schemas/expected-outcome.js.map +1 -1
  46. package/dist/collection/schemas/model-response.js +7 -0
  47. package/dist/collection/schemas/model-response.js.map +1 -0
  48. package/dist/collection/schemas/test-case.js +8 -1
  49. package/dist/collection/schemas/test-case.js.map +1 -1
  50. package/dist/collection/types/expected-outcome.js.map +1 -1
  51. package/dist/collection/types/llm-test-runner.js.map +1 -1
  52. package/dist/collection/types/test-case.js.map +1 -1
  53. package/dist/components/app-chips.js +1 -1
  54. package/dist/components/app-select.js +1 -1
  55. package/dist/components/app-textarea.js +1 -1
  56. package/dist/components/chat-history.d.ts +11 -0
  57. package/dist/components/chat-history.js +2 -0
  58. package/dist/components/chat-history.js.map +1 -0
  59. package/dist/components/index.js +1 -1
  60. package/dist/components/llm-test-runner.js +1 -1
  61. package/dist/components/{p-CVtKFBJl.js → p-D2qDAxFN.js} +2 -2
  62. package/dist/components/{p-Dv7cB5FU.js → p-D4dHUFN9.js} +2 -2
  63. package/dist/components/{p-CE5-1jfZ.js → p-eN2dLrsr.js} +2 -2
  64. package/dist/components/p-kmtfMXcQ.js +2 -0
  65. package/dist/components/p-kmtfMXcQ.js.map +1 -0
  66. package/dist/components/{p-BcygfrMf.js → p-wzA48RFK.js} +3 -3
  67. package/dist/components/p-wzA48RFK.js.map +1 -0
  68. package/dist/esm/{app-chips_4.entry.js → app-chips_5.entry.js} +38 -7
  69. package/dist/esm/app-chips_5.entry.js.map +1 -0
  70. package/dist/esm/index.js +499 -68
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/llm-testrunner.js +1 -1
  73. package/dist/esm/loader.js +1 -1
  74. package/dist/llm-testrunner/index.esm.js +2 -2
  75. package/dist/llm-testrunner/index.esm.js.map +1 -1
  76. package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
  77. package/dist/llm-testrunner/p-5bf1fc78.entry.js +2 -0
  78. package/dist/llm-testrunner/p-5bf1fc78.entry.js.map +1 -0
  79. package/dist/react/components.d.ts +6 -1
  80. package/dist/react/components.d.ts.map +1 -1
  81. package/dist/react/components.js +9 -0
  82. package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +4 -4
  83. package/dist/types/components/llm-test-runner/test-cases/chat-history.d.ts +14 -0
  84. package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +1 -0
  85. package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +6 -0
  86. package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +3 -0
  87. package/dist/types/components/llm-test-runner/test-cases/output/response-output.d.ts +2 -1
  88. package/dist/types/components.d.ts +55 -2
  89. package/dist/types/index.d.ts +1 -1
  90. package/dist/types/lib/evaluation/actual-value-resolver.d.ts +9 -0
  91. package/dist/types/lib/evaluation/evaluation-service.d.ts +2 -2
  92. package/dist/types/lib/evaluation/types.d.ts +1 -1
  93. package/dist/types/lib/import-export/test-suite-exporter.d.ts +4 -0
  94. package/dist/types/lib/import-export/test-suite-importer.d.ts +1 -1
  95. package/dist/types/lib/test-cases/test-case-mutations.d.ts +10 -1
  96. package/dist/types/schemas/expected-outcome.d.ts +116 -0
  97. package/dist/types/schemas/model-response.d.ts +7 -0
  98. package/dist/types/schemas/test-case.d.ts +93 -1
  99. package/dist/types/types/expected-outcome.d.ts +1 -1
  100. package/dist/types/types/llm-test-runner.d.ts +6 -3
  101. package/dist/types/types/test-case.d.ts +1 -1
  102. package/package.json +1 -1
  103. package/dist/cjs/app-chips_4.cjs.entry.js.map +0 -1
  104. package/dist/components/p-BcygfrMf.js.map +0 -1
  105. package/dist/esm/app-chips_4.entry.js.map +0 -1
  106. package/dist/llm-testrunner/p-5df053b4.entry.js +0 -2
  107. package/dist/llm-testrunner/p-5df053b4.entry.js.map +0 -1
  108. /package/dist/components/{p-CVtKFBJl.js.map → p-D2qDAxFN.js.map} +0 -0
  109. /package/dist/components/{p-Dv7cB5FU.js.map → p-D4dHUFN9.js.map} +0 -0
  110. /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
+ display: flex;
38
+ align-items: center;
39
+ padding: 0px 4px;
40
+ width: 2.75rem;
41
+ height: 1.5rem;
42
+ border-radius: var(--radius-full);
43
+ background: var(--muted);
44
+ border: var(--border-width) solid var(--border);
45
+ transition:
46
+ background 0.15s ease,
47
+ border-color 0.15s ease;
48
+ }
49
+
50
+ @media (prefers-reduced-motion: reduce) {
51
+ .chat-history__switch-ui,
52
+ .chat-history__switch-thumb {
53
+ transition: none;
54
+ }
55
+ }
56
+
57
+ .chat-history__switch-thumb {
58
+ display: inline-block;
59
+ width: calc(1.5rem - 6px);
60
+ height: calc(1.5rem - 6px);
61
+ border-radius: var(--radius-full);
62
+ background: var(--background);
63
+ box-shadow: var(--shadow-sm);
64
+ transition: transform 0.15s ease;
65
+ }
66
+
67
+ .chat-history__switch-input:checked + .chat-history__switch-ui {
68
+ background: var(--primary);
69
+ border-color: var(--primary);
70
+ }
71
+
72
+ .chat-history__switch-input:checked + .chat-history__switch-ui .chat-history__switch-thumb {
73
+ transform: translateX(calc(2.75rem - (1.5rem - 6px)));
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,9 @@ 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, dynamicResolutionSupported = false, onExpectedOutcomeChange, }) => {
5
+ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionSupported = false, extractorIds = [], onExpectedOutcomeChange, }) => {
6
+ const hasExtractorOptions = extractorIds.length > 0;
7
+ const firstExtractorId = extractorIds[0];
6
8
  const emit = (detail) => onExpectedOutcomeChange({
7
9
  detail,
8
10
  });
@@ -32,6 +34,23 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionS
32
34
  required: false,
33
35
  rows: 2,
34
36
  });
37
+ const buildEvaluationSourceConfig = (index) => ({
38
+ name: `expectedOutcomeEvaluationSource-${index}`,
39
+ fieldType: FormFieldType.SELECT,
40
+ label: 'Evaluation Source',
41
+ placeholder: 'Select evaluation source',
42
+ required: true,
43
+ optionList: ['text', 'custom'],
44
+ defaultValue: 'text',
45
+ });
46
+ const buildExtractorConfig = (index) => ({
47
+ name: `expectedOutcomeEvaluationSourceExtractor-${index}`,
48
+ fieldType: FormFieldType.SELECT,
49
+ label: 'Extractor',
50
+ placeholder: 'Select extractor',
51
+ required: true,
52
+ optionList: extractorIds,
53
+ });
35
54
  const renderEvaluationSelector = (field, index) => {
36
55
  const optionList = getAllowedApproachesForFieldType(field.type);
37
56
  return (h("app-select", { config: buildEvaluationConfig(index, optionList), value: field.evaluationParameters?.approach, onValueChange: (e) => emit({
@@ -41,6 +60,27 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionS
41
60
  value: e.detail.value,
42
61
  }) }));
43
62
  };
63
+ const renderEvaluationSourceSelector = (field, index) => {
64
+ if (!hasExtractorOptions) {
65
+ return null;
66
+ }
67
+ const sourceType = field.evaluationSource?.type || 'text';
68
+ return (h("div", null, h("app-select", { config: buildEvaluationSourceConfig(index), value: sourceType, onValueChange: (e) => emit({
69
+ testCaseId,
70
+ index,
71
+ operation: 'set-evaluation-source-type',
72
+ value: e.detail.value,
73
+ fallbackExtractorId: firstExtractorId,
74
+ }) }), sourceType === 'custom' && (h("app-select", { config: buildExtractorConfig(index), value: field.evaluationSource?.type === 'custom'
75
+ ? field.evaluationSource.extractorId
76
+ : '', onValueChange: (e) => emit({
77
+ testCaseId,
78
+ index,
79
+ operation: 'set-evaluation-source-extractor',
80
+ value: e.detail.value,
81
+ }) }))));
82
+ };
83
+ const renderEvaluationOptions = (field, index) => (h("details", { class: "expected-outcome-renderer__options" }, h("summary", { class: "expected-outcome-renderer__options-summary" }, "More options"), h("div", { class: "expected-outcome-renderer__options-content" }, renderEvaluationSelector(field, index), renderEvaluationSourceSelector(field, index))));
44
84
  return (h("div", { class: "expected-outcome-renderer" }, (fields || []).map((field, index) => {
45
85
  if (field.type === 'textarea') {
46
86
  const isDynamic = dynamicResolutionSupported && field.outcomeMode === 'dynamic';
@@ -72,7 +112,7 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionS
72
112
  index,
73
113
  operation: 'set-resolution-query',
74
114
  value: e.detail.value,
75
- }) })), !isDynamic && renderEvaluationSelector(field, index)));
115
+ }) })), !isDynamic && renderEvaluationOptions(field, index)));
76
116
  }
77
117
  if (field.type === 'chips-input') {
78
118
  const config = {
@@ -92,7 +132,7 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionS
92
132
  index,
93
133
  operation: 'remove-chip',
94
134
  value: e.detail.value,
95
- }) }), renderEvaluationSelector(field, index)));
135
+ }) }), renderEvaluationOptions(field, index)));
96
136
  }
97
137
  if (field.type === 'select') {
98
138
  const config = {
@@ -108,14 +148,14 @@ export const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionS
108
148
  index,
109
149
  operation: 'set-value',
110
150
  value: e.detail.value,
111
- }) }), renderEvaluationSelector(field, index)));
151
+ }) }), renderEvaluationOptions(field, index)));
112
152
  }
113
153
  return (h("div", { class: "expected-outcome-renderer__group" }, h("div", { class: "expected-outcome-renderer__text" }, h("label", null, field.label), h("input", { type: "text", value: field.value, placeholder: field.placeholder, onInput: (e) => emit({
114
154
  testCaseId,
115
155
  index,
116
156
  operation: 'set-value',
117
157
  value: e.target.value,
118
- }) })), renderEvaluationSelector(field, index)));
158
+ }) })), renderEvaluationOptions(field, index)));
119
159
  })));
120
160
  };
121
161
  //# sourceMappingURL=expected-outcome-renderer.js.map
@@ -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 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"]}
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 EvaluationSource,\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 extractorIds?: string[];\n onExpectedOutcomeChange: (\n e: CustomEvent<ExpectedOutcomeChangeDetail>,\n ) => void;\n}\n\nexport const ExpectedOutcomeRenderer: FunctionalComponent<ExpectedOutcomeRendererProps> = ({\n testCaseId,\n fields,\n dynamicResolutionSupported = false,\n extractorIds = [],\n onExpectedOutcomeChange,\n}) => {\n const hasExtractorOptions = extractorIds.length > 0;\n const firstExtractorId = extractorIds[0];\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 buildEvaluationSourceConfig = (index: number): SelectConfig => ({\n name: `expectedOutcomeEvaluationSource-${index}`,\n fieldType: FormFieldType.SELECT,\n label: 'Evaluation Source',\n placeholder: 'Select evaluation source',\n required: true,\n optionList: ['text', 'custom'],\n defaultValue: 'text',\n });\n\n const buildExtractorConfig = (index: number): SelectConfig => ({\n name: `expectedOutcomeEvaluationSourceExtractor-${index}`,\n fieldType: FormFieldType.SELECT,\n label: 'Extractor',\n placeholder: 'Select extractor',\n required: true,\n optionList: extractorIds,\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 const renderEvaluationSourceSelector = (\n field: ExpectedOutcomeField,\n index: number,\n ) => {\n if (!hasExtractorOptions) {\n return null;\n }\n\n const sourceType = field.evaluationSource?.type || 'text';\n\n return (\n <div>\n <app-select\n config={buildEvaluationSourceConfig(index)}\n value={sourceType}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-evaluation-source-type',\n value: e.detail.value as EvaluationSource['type'],\n fallbackExtractorId: firstExtractorId,\n })\n }\n />\n {sourceType === 'custom' && (\n <app-select\n config={buildExtractorConfig(index)}\n value={field.evaluationSource?.type === 'custom'\n ? field.evaluationSource.extractorId\n : ''}\n onValueChange={(e) =>\n emit({\n testCaseId,\n index,\n operation: 'set-evaluation-source-extractor',\n value: e.detail.value,\n })\n }\n />\n )}\n </div>\n );\n };\n\n const renderEvaluationOptions = (field: ExpectedOutcomeField, index: number) => (\n <details class=\"expected-outcome-renderer__options\">\n <summary class=\"expected-outcome-renderer__options-summary\">\n More options\n </summary>\n <div class=\"expected-outcome-renderer__options-content\">\n {renderEvaluationSelector(field, index)}\n {renderEvaluationSourceSelector(field, index)}\n </div>\n </details>\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 && renderEvaluationOptions(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 {renderEvaluationOptions(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 {renderEvaluationOptions(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 {renderEvaluationOptions(field, index)}\n </div>\n );\n })}\n </div>\n );\n};\n"]}
@@ -35,6 +35,27 @@
35
35
  background: var(--background);
36
36
  }
37
37
 
38
+ .expected-outcome-renderer__options {
39
+ border: var(--border-width) solid var(--border);
40
+ border-radius: var(--radius-sm);
41
+ background: var(--muted);
42
+ }
43
+
44
+ .expected-outcome-renderer__options-summary {
45
+ cursor: pointer;
46
+ font-size: var(--font-size-sm);
47
+ color: var(--foreground);
48
+ padding: var(--spacing-2) var(--spacing-3);
49
+ user-select: none;
50
+ }
51
+
52
+ .expected-outcome-renderer__options-content {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: var(--spacing-2);
56
+ padding: 0 var(--spacing-3) var(--spacing-3);
57
+ }
58
+
38
59
  /* Responsive Design */
39
60
  @media (max-width: 1200px) {
40
61
  .test-case-row {
@@ -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, dynamicResolutionSupported = false, onRun, onDelete, handleTestCaseChange, onExpectedOutcomeChange, }) => {
7
+ export const LLMTestCaseRow = ({ testCase, dynamicResolutionSupported = false, extractorIds = [], 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, dynamicResolutionSupported = false, o
20
20
  key: 'question',
21
21
  value: e.detail.value,
22
22
  },
23
- }) }), 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) })));
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, extractorIds: extractorIds, 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;AAerC,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,QAAQ,EACR,0BAA0B,GAAG,KAAK,EAClC,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,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';\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}\n\nexport const LLMTestCaseRow: FunctionalComponent<LLMTestCaseRowProps> = ({\n testCase,\n dynamicResolutionSupported = false,\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 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
+ {"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;AAsBrC,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,QAAQ,EACR,0BAA0B,GAAG,KAAK,EAClC,YAAY,GAAG,EAAE,EACjB,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,YAAY,EAAE,YAAY,EAC1B,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 extractorIds?: string[];\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 extractorIds = [],\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 extractorIds={extractorIds}\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, dynamicResolutionSupported = false, 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, dynamicResolutionSupported: dynamicResolutionSupported, 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, extractorIds = [], 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, extractorIds: extractorIds, 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;AAiBtD,MAAM,CAAC,MAAM,YAAY,GAA2C,CAAC,EACnE,SAAS,EACT,0BAA0B,GAAG,KAAK,EAClC,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,0BAA0B,EAAE,0BAA0B,EACtD,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 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}\n\nexport const LLMTestCases: FunctionalComponent<LLMTestCasesProps> = ({\n testCases,\n dynamicResolutionSupported = false,\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 dynamicResolutionSupported={dynamicResolutionSupported}\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;AAmBtD,MAAM,CAAC,MAAM,YAAY,GAA2C,CAAC,EACnE,SAAS,EACT,0BAA0B,GAAG,KAAK,EAClC,YAAY,GAAG,EAAE,EACjB,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,YAAY,EAAE,YAAY,EAC1B,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 extractorIds?: string[];\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 extractorIds = [],\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 extractorIds={extractorIds}\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,5 +1,5 @@
1
1
  import { h } from "@stencil/core";
2
2
  export const ResponseOutput = ({ output, isRunning, }) => {
3
- return (h("div", { class: "response-output" }, output ? (h("div", { class: "response-output__content" }, output)) : (h("div", { class: "response-output__placeholder" }, isRunning ? 'Running...' : ''))));
3
+ return (h("div", { class: "response-output" }, output?.text ? (h("div", { class: "response-output__content" }, output.text)) : (h("div", { class: "response-output__placeholder" }, isRunning ? 'Running...' : ''))));
4
4
  };
5
5
  //# sourceMappingURL=response-output.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"response-output.js","sourceRoot":"","sources":["../../../../../src/components/llm-test-runner/test-cases/output/response-output.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAOvD,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,MAAM,EACN,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,WAAK,KAAK,EAAC,iBAAiB,IACzB,MAAM,CAAC,CAAC,CAAC,CACR,WAAK,KAAK,EAAC,0BAA0B,IAAE,MAAM,CAAO,CACrD,CAAC,CAAC,CAAC,CACF,WAAK,KAAK,EAAC,8BAA8B,IAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAO,CAChF,CACG,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\n\nexport interface ResponseOutputProps {\n output?: string;\n isRunning: boolean;\n}\n\nexport const ResponseOutput: FunctionalComponent<ResponseOutputProps> = ({\n output,\n isRunning,\n}) => {\n return (\n <div class=\"response-output\">\n {output ? (\n <div class=\"response-output__content\">{output}</div>\n ) : (\n <div class=\"response-output__placeholder\">{isRunning ? 'Running...' : ''}</div>\n )}\n </div>\n );\n};\n\n"]}
1
+ {"version":3,"file":"response-output.js","sourceRoot":"","sources":["../../../../../src/components/llm-test-runner/test-cases/output/response-output.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAuB,MAAM,eAAe,CAAC;AAQvD,MAAM,CAAC,MAAM,cAAc,GAA6C,CAAC,EACvE,MAAM,EACN,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,WAAK,KAAK,EAAC,iBAAiB,IACzB,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CACd,WAAK,KAAK,EAAC,0BAA0B,IAAE,MAAM,CAAC,IAAI,CAAO,CAC1D,CAAC,CAAC,CAAC,CACF,WAAK,KAAK,EAAC,8BAA8B,IAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAO,CAChF,CACG,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { h, FunctionalComponent } from '@stencil/core';\nimport type { ModelResponsePayload } from '../../../../types/llm-test-runner';\n\nexport interface ResponseOutputProps {\n output?: ModelResponsePayload;\n isRunning: boolean;\n}\n\nexport const ResponseOutput: FunctionalComponent<ResponseOutputProps> = ({\n output,\n isRunning,\n}) => {\n return (\n <div class=\"response-output\">\n {output?.text ? (\n <div class=\"response-output__content\">{output.text}</div>\n ) : (\n <div class=\"response-output__placeholder\">{isRunning ? 'Running...' : ''}</div>\n )}\n </div>\n );\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"]}
@@ -0,0 +1,52 @@
1
+ function toTextSource() {
2
+ return { type: 'text' };
3
+ }
4
+ export async function resolveActualValue(field, output, extractors) {
5
+ const source = field.evaluationSource || toTextSource();
6
+ if (source.type === 'text') {
7
+ const text = output?.text?.trim();
8
+ if (!text) {
9
+ return {
10
+ success: false,
11
+ error: 'Model response text is empty.',
12
+ };
13
+ }
14
+ return { success: true, value: text };
15
+ }
16
+ const extractor = extractors?.[source.extractorId];
17
+ if (!extractor) {
18
+ return {
19
+ success: false,
20
+ error: `Extractor "${source.extractorId}" is not registered.`,
21
+ };
22
+ }
23
+ try {
24
+ const extractedRaw = await extractor(output || {});
25
+ if (typeof extractedRaw !== 'string') {
26
+ return {
27
+ success: false,
28
+ error: `Extractor "${source.extractorId}" must return a string.`,
29
+ };
30
+ }
31
+ const extracted = extractedRaw.trim();
32
+ if (!extracted) {
33
+ return {
34
+ success: false,
35
+ error: `Extractor "${source.extractorId}" returned an empty value.`,
36
+ };
37
+ }
38
+ return {
39
+ success: true,
40
+ value: extracted,
41
+ };
42
+ }
43
+ catch (error) {
44
+ return {
45
+ success: false,
46
+ error: error instanceof Error
47
+ ? error.message
48
+ : `Extractor "${source.extractorId}" failed.`,
49
+ };
50
+ }
51
+ }
52
+ //# sourceMappingURL=actual-value-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actual-value-resolver.js","sourceRoot":"","sources":["../../../src/lib/evaluation/actual-value-resolver.ts"],"names":[],"mappings":"AAUA,SAAS,YAAY;IACnB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAW,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAA2B,EAC3B,MAA6B,EAC7B,UAAuC;IAEvC,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,IAAI,YAAY,EAAE,CAAC;IAExD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,+BAA+B;aACvC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,cAAc,MAAM,CAAC,WAAW,sBAAsB;SAC9D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,cAAc,MAAM,CAAC,WAAW,yBAAyB;aACjE,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,cAAc,MAAM,CAAC,WAAW,4BAA4B;aACpE,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;SACjB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EACH,KAAK,YAAY,KAAK;gBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,cAAc,MAAM,CAAC,WAAW,WAAW;SAClD,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import type {\n EvaluationSourceExtractors,\n ExpectedOutcomeField,\n ModelResponsePayload,\n} from '../../types/llm-test-runner';\n\nexport type ResolvedActualValue =\n | { success: true; value: string }\n | { success: false; error: string };\n\nfunction toTextSource() {\n return { type: 'text' } as const;\n}\n\nexport async function resolveActualValue(\n field: ExpectedOutcomeField,\n output?: ModelResponsePayload,\n extractors?: EvaluationSourceExtractors,\n): Promise<ResolvedActualValue> {\n const source = field.evaluationSource || toTextSource();\n\n if (source.type === 'text') {\n const text = output?.text?.trim();\n if (!text) {\n return {\n success: false,\n error: 'Model response text is empty.',\n };\n }\n return { success: true, value: text };\n }\n\n const extractor = extractors?.[source.extractorId];\n if (!extractor) {\n return {\n success: false,\n error: `Extractor \"${source.extractorId}\" is not registered.`,\n };\n }\n\n try {\n const extractedRaw = await extractor(output || {});\n if (typeof extractedRaw !== 'string') {\n return {\n success: false,\n error: `Extractor \"${source.extractorId}\" must return a string.`,\n };\n }\n\n const extracted = extractedRaw.trim();\n if (!extracted) {\n return {\n success: false,\n error: `Extractor \"${source.extractorId}\" returned an empty value.`,\n };\n }\n\n return {\n success: true,\n value: extracted,\n };\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : `Extractor \"${source.extractorId}\" failed.`,\n };\n }\n}\n"]}
@@ -10,7 +10,7 @@ export class LLMEvaluationEngine {
10
10
  const fieldRequest = {
11
11
  testCaseId: request.testCaseId,
12
12
  question: request.question,
13
- actualResponse: request.actualResponse,
13
+ actualResponse: field.actualResponse,
14
14
  expectedOutcome: field.expectedValue,
15
15
  evaluationParameters: field.evaluationParameters,
16
16
  };