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.
- package/dist/cjs/{app-chips_4.cjs.entry.js → app-chips_5.cjs.entry.js} +41 -6
- package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
- package/dist/cjs/index.cjs.js +235 -44
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/cjs/llm-testrunner.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +22 -12
- package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
- package/dist/collection/components/llm-test-runner/llm-test-runner.js +91 -30
- package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/chat-history.css +101 -0
- package/dist/collection/components/llm-test-runner/test-cases/chat-history.js +105 -0
- package/dist/collection/components/llm-test-runner/test-cases/chat-history.js.map +1 -0
- package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +37 -4
- package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +12 -2
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
- package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/lib/evaluation/evaluation-service.js +14 -7
- package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
- package/dist/collection/lib/form/components/app-chips.js +1 -1
- package/dist/collection/lib/form/components/app-select.js +1 -1
- package/dist/collection/lib/form/components/app-textarea.css +17 -0
- package/dist/collection/lib/form/components/app-textarea.js +4 -1
- package/dist/collection/lib/form/components/app-textarea.js.map +1 -1
- package/dist/collection/lib/import-export/test-suite-exporter.js +4 -0
- package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
- package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js +44 -0
- package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js.map +1 -0
- package/dist/collection/lib/test-cases/test-case-factory.js +2 -0
- package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
- package/dist/collection/lib/test-cases/test-case-mutations.js +35 -0
- package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
- package/dist/collection/schemas/expected-outcome.js +15 -1
- package/dist/collection/schemas/expected-outcome.js.map +1 -1
- package/dist/collection/schemas/test-case.js +6 -0
- package/dist/collection/schemas/test-case.js.map +1 -1
- package/dist/collection/types/expected-outcome.js.map +1 -1
- package/dist/collection/types/llm-test-runner.js.map +1 -1
- package/dist/collection/types/test-case.js.map +1 -1
- package/dist/components/app-chips.js +1 -1
- package/dist/components/app-select.js +1 -1
- package/dist/components/app-textarea.js +1 -1
- package/dist/components/chat-history.d.ts +11 -0
- package/dist/components/chat-history.js +2 -0
- package/dist/components/chat-history.js.map +1 -0
- package/dist/components/index.js +1 -1
- package/dist/components/llm-test-runner.js +1 -1
- package/dist/components/{p-CJBscebi.js → p-B87Lt3z4.js} +3 -3
- package/dist/components/p-B87Lt3z4.js.map +1 -0
- package/dist/components/p-Bx2jqguC.js +2 -0
- package/dist/components/p-Bx2jqguC.js.map +1 -0
- package/dist/components/p-D2qDAxFN.js +2 -0
- package/dist/components/p-D2qDAxFN.js.map +1 -0
- package/dist/components/{p-Dv7cB5FU.js → p-D4dHUFN9.js} +2 -2
- package/dist/components/{p-CE5-1jfZ.js → p-eN2dLrsr.js} +2 -2
- package/dist/esm/{app-chips_4.entry.js → app-chips_5.entry.js} +41 -7
- package/dist/esm/app-chips_5.entry.js.map +1 -0
- package/dist/esm/index.js +235 -44
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/llm-testrunner.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/llm-testrunner/index.esm.js +2 -2
- package/dist/llm-testrunner/index.esm.js.map +1 -1
- package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
- package/dist/llm-testrunner/p-21202f12.entry.js +2 -0
- package/dist/llm-testrunner/p-21202f12.entry.js.map +1 -0
- package/dist/react/components.d.ts +6 -1
- package/dist/react/components.d.ts.map +1 -1
- package/dist/react/components.js +9 -0
- package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +6 -0
- package/dist/types/components/llm-test-runner/test-cases/chat-history.d.ts +14 -0
- package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +1 -0
- package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +6 -0
- package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +3 -0
- package/dist/types/components.d.ts +55 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/lib/import-export/test-suite-exporter.d.ts +4 -0
- package/dist/types/lib/test-cases/dynamic-expected-outcome-resolver.d.ts +7 -0
- package/dist/types/lib/test-cases/test-case-mutations.d.ts +9 -1
- package/dist/types/schemas/expected-outcome.d.ts +16 -1
- package/dist/types/schemas/test-case.d.ts +34 -2
- package/dist/types/types/expected-outcome.d.ts +1 -1
- package/dist/types/types/llm-test-runner.d.ts +3 -2
- package/dist/types/types/test-case.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cjs/app-chips_4.cjs.entry.js.map +0 -1
- package/dist/components/p-BZrzx5jG.js +0 -2
- package/dist/components/p-BZrzx5jG.js.map +0 -1
- package/dist/components/p-CJBscebi.js.map +0 -1
- package/dist/esm/app-chips_4.entry.js.map +0 -1
- package/dist/llm-testrunner/p-2cc09217.entry.js +0 -2
- package/dist/llm-testrunner/p-2cc09217.entry.js.map +0 -1
- /package/dist/components/{p-Dv7cB5FU.js.map → p-D4dHUFN9.js.map} +0 -0
- /package/dist/components/{p-CE5-1jfZ.js.map → p-eN2dLrsr.js.map} +0 -0
|
@@ -40,7 +40,7 @@ const AppChips = class {
|
|
|
40
40
|
name: c.name,
|
|
41
41
|
autocomplete: c.autocomplete,
|
|
42
42
|
};
|
|
43
|
-
return (index$1.h("div", { key: '
|
|
43
|
+
return (index$1.h("div", { key: 'fb7d4d5444e9c9ac33c56aec88e3e10ed103c8be', class: "app-chips" }, c.label && (index$1.h("label", { key: '2d0041b3a137fecddef2273eac3792b5e8de27ab', class: "app-chips__label", htmlFor: c.name }, c.label)), index$1.h("div", { key: 'f73b1105e567b233626073e05b9da712689e7b12', class: "app-chips__container" }, this.value.map((chip) => (index$1.h("span", { class: "app-chips__chip", key: chip }, c.type === 'url' ? (index$1.h("a", { href: chip, target: "_blank", rel: "noopener noreferrer", class: "app-chips__link" }, chip)) : (chip), index$1.h("button", { class: "app-chips__remove", type: "button", onClick: () => this.emitRemoveChip(chip) }, "\u00D7")))), index$1.h("input", { key: '7676ff95531b34d10cbf9402e72a723e7e123e0e', class: "app-chips__input", type: c.type || 'text', ...allowedAttrs, onKeyDown: (e) => {
|
|
44
44
|
if (e.key === 'Enter') {
|
|
45
45
|
const input = e.target;
|
|
46
46
|
const val = input.value.trim();
|
|
@@ -79,7 +79,7 @@ const AppSelect = class {
|
|
|
79
79
|
placeholder: c.placeholder,
|
|
80
80
|
autocomplete: c.autocomplete,
|
|
81
81
|
};
|
|
82
|
-
return (index$1.h("div", { key: '
|
|
82
|
+
return (index$1.h("div", { key: '968f0fffe1eff976ac7e00f02db6fb84aa529de4', class: "app-select" }, c.label && (index$1.h("label", { key: 'dac02d2335754ff5d6ce6ba1df5777f8b019cfae', class: "app-select__label", htmlFor: c.name }, c.label)), index$1.h("div", { key: 'c92698199479bbdde1cfd559d69fc97e54d2862a' }, index$1.h("select", { key: '6e9b27b034d057921f52fbd12653c5ef1b6af1bc', ...allowedAttrs, class: "app-select__select", onInput: (e) => {
|
|
83
83
|
const raw = e.target.value;
|
|
84
84
|
const matched = c.optionList.find(opt => String(opt) === raw);
|
|
85
85
|
this.valueChange.emit({
|
|
@@ -90,7 +90,7 @@ const AppSelect = class {
|
|
|
90
90
|
};
|
|
91
91
|
AppSelect.style = appSelectCss();
|
|
92
92
|
|
|
93
|
-
const appTextareaCss = () => `.textarea-wrapper{margin-bottom:var(--spacing-4)}.textarea-label{display:block;margin-bottom:var(--spacing-2);font-weight:var(--font-weight-medium);color:var(--foreground);font-size:var(--font-size-sm)}.textarea-element{width:95%;box-sizing:border-box;padding:var(--spacing-3);border:2px solid var(--input);border-radius:var(--radius);font-size:var(--font-size-sm);resize:vertical;outline:none;transition:border-color 0.2s ease;font-family:inherit;background:var(--background);color:var(--foreground)}.textarea-element:focus{border-color:var(--ring);box-shadow:0 0 0 3px rgba(59, 130, 246, 0.1)}.help-text{margin-top:var(--spacing-1);font-size:var(--font-size-xs);color:var(--muted-foreground, #6b7280);line-height:1.4}`;
|
|
93
|
+
const appTextareaCss = () => `.textarea-wrapper{margin-bottom:var(--spacing-4)}.textarea-label{display:block;margin-bottom:var(--spacing-2);font-weight:var(--font-weight-medium);color:var(--foreground);font-size:var(--font-size-sm)}.textarea-element{width:95%;box-sizing:border-box;padding:var(--spacing-3);border:2px solid var(--input);border-radius:var(--radius);font-size:var(--font-size-sm);resize:vertical;outline:none;transition:border-color 0.2s ease;font-family:inherit;background:var(--background);color:var(--foreground)}.textarea-element:focus{border-color:var(--ring);box-shadow:0 0 0 3px rgba(59, 130, 246, 0.1)}.textarea-wrapper--read-only .textarea-label{color:var(--muted-foreground)}.textarea-element:read-only{background:var(--muted);color:var(--muted-foreground);border-color:var(--border);cursor:not-allowed;resize:none}.textarea-element:read-only:focus{border-color:var(--border);box-shadow:none}.help-text{margin-top:var(--spacing-1);font-size:var(--font-size-xs);color:var(--muted-foreground, #6b7280);line-height:1.4}`;
|
|
94
94
|
|
|
95
95
|
const AppTextarea = class {
|
|
96
96
|
constructor(hostRef) {
|
|
@@ -118,15 +118,50 @@ const AppTextarea = class {
|
|
|
118
118
|
name: c.name,
|
|
119
119
|
autocomplete: c.autocomplete,
|
|
120
120
|
};
|
|
121
|
-
return (index$1.h("div", { key: '
|
|
121
|
+
return (index$1.h("div", { key: 'f0749b1f2badf8434272da9fb37b354b42ba988b', class: {
|
|
122
|
+
'textarea-wrapper': true,
|
|
123
|
+
'textarea-wrapper--read-only': !!c.readOnly,
|
|
124
|
+
} }, c.label && (index$1.h("label", { key: '3448c838bcf9e962df005eae8fc313d216497c35', class: "textarea-label", htmlFor: c.name }, c.label)), index$1.h("textarea", { key: 'b4ee67a24fa71b0fa042625f943b0e226a6d14b7', ...allowedAttrs, class: "textarea-element", value: this.value, onInput: this.handleChange }), c.helpText && index$1.h("p", { key: 'fb6263c32e6cc5e36dbc77344c31487d63d51a1c', class: "help-text" }, c.helpText)));
|
|
122
125
|
}
|
|
123
126
|
};
|
|
124
127
|
AppTextarea.style = appTextareaCss();
|
|
125
128
|
|
|
129
|
+
const chatHistoryCss = () => `.chat-history{display:flex;flex-direction:column;gap:var(--spacing-3);margin-top:var(--spacing-4)}.chat-history__toggle-row{display:flex;align-items:center}.chat-history__switch{position:relative;display:inline-flex;align-items:center;gap:var(--spacing-3);cursor:pointer;user-select:none}.chat-history__switch-input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.chat-history__switch-ui{position:relative;flex-shrink:0;width:2.75rem;height:1.5rem;border-radius:var(--radius-full);background:var(--muted);border:var(--border-width) solid var(--border);transition:background 0.15s ease, border-color 0.15s ease}@media (prefers-reduced-motion: reduce){.chat-history__switch-ui,.chat-history__switch-thumb{transition:none}}.chat-history__switch-thumb{position:absolute;top:2px;left:2px;width:calc(1.5rem - 6px);height:calc(1.5rem - 6px);border-radius:var(--radius-full);background:var(--background);box-shadow:var(--shadow-sm);transition:transform 0.15s ease}.chat-history__switch-input:checked+.chat-history__switch-ui{background:var(--primary);border-color:var(--primary)}.chat-history__switch-input:checked+.chat-history__switch-ui .chat-history__switch-thumb{transform:translateX(calc(2.75rem - (1.5rem - 6px) - 4px))}.chat-history__switch-input:focus-visible+.chat-history__switch-ui{outline:2px solid var(--ring);outline-offset:2px}.chat-history__switch-text{font-size:var(--font-size-sm, 0.875rem);color:var(--foreground)}.chat-history__textarea{width:100%;box-sizing:border-box;padding:var(--spacing-2) var(--spacing-3);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);font:inherit;resize:vertical;min-height:9rem;background:var(--background)}.chat-history__textarea:focus-visible{outline:2px solid var(--ring);outline-offset:2px}`;
|
|
130
|
+
|
|
131
|
+
const CHAT_HISTORY_PLACEHOLDER = `[
|
|
132
|
+
{"role": "user", "content": "How do I import a saved suite?"},
|
|
133
|
+
{"role": "model", "content": "Use Import and pick the JSON from Export suite."}
|
|
134
|
+
]`;
|
|
135
|
+
const ChatHistory = class {
|
|
136
|
+
constructor(hostRef) {
|
|
137
|
+
index$1.registerInstance(this, hostRef);
|
|
138
|
+
this.chatHistoryChange = index$1.createEvent(this, "chatHistoryChange");
|
|
139
|
+
}
|
|
140
|
+
chatHistoryEnabled = false;
|
|
141
|
+
chatHistoryValue = '';
|
|
142
|
+
chatHistoryChange;
|
|
143
|
+
emit(detail) {
|
|
144
|
+
this.chatHistoryChange.emit(detail);
|
|
145
|
+
}
|
|
146
|
+
onToggle = (e) => {
|
|
147
|
+
const checked = e.target.checked;
|
|
148
|
+
this.emit({ enabled: checked, value: this.chatHistoryValue });
|
|
149
|
+
};
|
|
150
|
+
onTextInput = (e) => {
|
|
151
|
+
const value = e.target.value;
|
|
152
|
+
this.emit({ enabled: this.chatHistoryEnabled, value });
|
|
153
|
+
};
|
|
154
|
+
render() {
|
|
155
|
+
return (index$1.h("div", { key: 'f444a4b5bd9b48df151cad67b54bef54116d11b3', class: "chat-history" }, index$1.h("div", { key: '7216d764fb905ac5e8e33209d9586525e59fa218', class: "chat-history__toggle-row" }, index$1.h("label", { key: 'd5d092c323b48543c96525d449bcb03dcaf5113b', class: "chat-history__switch" }, index$1.h("input", { key: '5104ce460686434156454fc1dfd3685ba0e0968c', type: "checkbox", class: "chat-history__switch-input", checked: this.chatHistoryEnabled, onInput: this.onToggle }), index$1.h("span", { key: 'fa2e51bce0d6ff2d3bf133383e1ce940521097b0', class: "chat-history__switch-ui", "aria-hidden": "true" }, index$1.h("span", { key: 'e0d897ca166623ece09834b44b5baa12605cb9f3', class: "chat-history__switch-thumb" })), index$1.h("span", { key: 'e769678fde5d670e634d7a8e905ef09ce936f440', class: "chat-history__switch-text" }, "Chat history"))), this.chatHistoryEnabled ? (index$1.h("textarea", { class: "chat-history__textarea", value: this.chatHistoryValue, rows: 8, placeholder: CHAT_HISTORY_PLACEHOLDER, "aria-label": "Chat history", onInput: this.onTextInput })) : null));
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
ChatHistory.style = chatHistoryCss();
|
|
159
|
+
|
|
126
160
|
exports.llm_test_runner = index.LLMTestRunner;
|
|
127
161
|
exports.app_chips = AppChips;
|
|
128
162
|
exports.app_select = AppSelect;
|
|
129
163
|
exports.app_textarea = AppTextarea;
|
|
130
|
-
|
|
164
|
+
exports.chat_history = ChatHistory;
|
|
165
|
+
//# sourceMappingURL=app-chips.app-select.app-textarea.chat-history.llm-test-runner.entry.cjs.js.map
|
|
131
166
|
|
|
132
|
-
//# sourceMappingURL=app-
|
|
167
|
+
//# sourceMappingURL=app-chips_5.cjs.entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"file":"app-chips_5.cjs.entry.js","mappings":"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","names":["h"],"sources":["src/lib/form/components/app-chips.css?tag=app-chips&encapsulation=shadow","src/lib/form/components/app-chips.tsx","src/lib/form/components/app-select.css?tag=app-select&encapsulation=shadow","src/lib/form/components/app-select.tsx","src/lib/form/components/app-textarea.css?tag=app-textarea&encapsulation=shadow","src/lib/form/components/app-textarea.tsx","src/components/llm-test-runner/test-cases/chat-history.css?tag=chat-history&encapsulation=shadow","src/components/llm-test-runner/test-cases/chat-history.tsx"],"sourcesContent":[".app-chips {\n margin-bottom: var(--spacing-4);\n}\n\n.app-chips__label {\n display: block;\n margin-bottom: var(--spacing-2);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n font-size: var(--font-size-sm);\n}\n\n.app-chips__container {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-2);\n align-items: center;\n}\n\n.app-chips__chip {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2);\n padding: var(--spacing-1) var(--spacing-2);\n font-size: var(--font-size-xs);\n font-weight: var(--font-weight-medium);\n border-radius: var(--radius-md);\n background: var(--accent);\n border: var(--border-width) solid var(--border);\n}\n\n/* Keyword-style chip override (non-URL chips) */\n.app-chips__chip:not(:has(a)) {\n background: var(--info);\n color: var(--info-foreground);\n border: none;\n border-radius: var(--radius-2xl);\n}\n\n.app-chips__link {\n color: var(--info);\n text-decoration: none;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.app-chips__link:hover {\n text-decoration: underline;\n}\n\n.app-chips__remove {\n background: none;\n border: none;\n cursor: pointer;\n font-size: var(--font-size-xs);\n padding: 0;\n width: var(--spacing-4);\n height: var(--spacing-4);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--radius-full);\n color: var(--muted-foreground);\n opacity: var(--opacity-muted);\n}\n\n.app-chips__chip:not(:has(a)) .app-chips__remove {\n color: var(--info-foreground);\n opacity: var(--opacity-hover);\n}\n\n.app-chips__remove:hover {\n opacity: 1;\n background: var(--muted);\n}\n\n.app-chips__chip:not(:has(a)) .app-chips__remove:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n\n.app-chips__input {\n border: var(--border-width) solid var(--input);\n border-radius: var(--radius-md);\n padding: var(--spacing-2);\n font-size: var(--font-size-xs);\n outline: none;\n min-width: 120px;\n background: var(--background);\n color: var(--foreground);\n}\n\n.app-chips__input:focus {\n border-color: var(--ring);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n","import { Component, Prop, h, Event, EventEmitter } from '@stencil/core';\nimport { ChipsConfig } from '../schema';\n\n@Component({\n tag: 'app-chips',\n styleUrl: 'app-chips.css',\n shadow: true,\n})\nexport class AppChips {\n @Prop() value: string[] = [];\n @Prop() config: ChipsConfig;\n\n @Event() addChip: EventEmitter<{ value: string }>;\n\n @Event() removeChip: EventEmitter<{ value: string }>;\n\n private emitAddChip(val: string) {\n this.addChip.emit({\n value: val,\n });\n }\n\n private emitRemoveChip(value: string) {\n this.removeChip.emit({\n value,\n });\n }\n\n private hasDuplicateChip(value: string): boolean {\n const normalized = value.trim().toLowerCase();\n return this.value.some(chip => chip.trim().toLowerCase() === normalized);\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 id: c.name,\n name: c.name,\n autocomplete: c.autocomplete,\n };\n\n return (\n <div class=\"app-chips\">\n {c.label && (\n <label class=\"app-chips__label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <div class=\"app-chips__container\">\n {this.value.map((chip) => (\n <span class=\"app-chips__chip\" key={chip}>\n {c.type === 'url' ? (\n <a\n href={chip}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"app-chips__link\"\n >\n {chip}\n </a>\n ) : (\n chip\n )}\n\n <button\n class=\"app-chips__remove\"\n type=\"button\"\n onClick={() => this.emitRemoveChip(chip)}\n >\n ×\n </button>\n </span>\n ))}\n\n <input\n class=\"app-chips__input\"\n type={c.type || 'text'}\n {...allowedAttrs}\n onKeyDown={(e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n const input = e.target as HTMLInputElement;\n const val = input.value.trim();\n if (!val) return;\n if (this.hasDuplicateChip(val)) {\n input.value = '';\n return;\n }\n\n this.emitAddChip(val);\n input.value = '';\n }\n }}\n />\n </div>\n </div>\n );\n }\n}\n",".app-select {\n margin-bottom: var(--spacing-4);\n}\n\n.app-select__label {\n display: block;\n margin-bottom: var(--spacing-2);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n font-size: var(--font-size-sm);\n}\n\n.app-select__select {\n border: var(--border-width) solid var(--input);\n border-radius: var(--radius-md);\n font-size: var(--font-size-sm);\n font-weight: var(--font-weight-medium);\n padding: var(--spacing-1) var(--spacing-2);\n outline: none;\n background: var(--background);\n width: 145px;\n color: var(--foreground);\n}\n\n.app-select__select:focus {\n border-color: var(--ring);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n","import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';\nimport { SelectConfig } from '../schema';\n\n@Component({\n tag: 'app-select',\n styleUrl: 'app-select.css',\n shadow: true,\n})\nexport class AppSelect {\n @Prop() value: string;\n @Prop() config: SelectConfig;\n @Event() valueChange: EventEmitter<{ value: string }>;\n\n render() {\n const c = this.config;\n const allowedAttrs = {\n id: c.name,\n name: c.name,\n disabled: c.disabled,\n required: c.required,\n readOnly: c.readOnly,\n placeholder: c.placeholder,\n autocomplete: c.autocomplete,\n };\n return (\n <div class=\"app-select\">\n {c.label && (\n <label class=\"app-select__label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <div>\n <select\n {...allowedAttrs}\n class=\"app-select__select\"\n onInput={(e: Event) => {\n const raw = (e.target as HTMLSelectElement).value;\n const matched = c.optionList.find(opt => String(opt) === raw);\n this.valueChange.emit({\n value: matched !== undefined ? matched : raw,\n });\n }}\n >\n {c.optionList?.map(option => (\n <option\n value={String(option)}\n key={String(option)}\n selected={this.value === option}\n >\n {String(option)}\n </option>\n ))}\n </select>\n </div>\n </div>\n );\n }\n}\n",".textarea-wrapper {\n margin-bottom: var(--spacing-4);\n}\n\n.textarea-label {\n display: block;\n margin-bottom: var(--spacing-2);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n font-size: var(--font-size-sm);\n}\n\n.textarea-element {\n width: 95%;\n box-sizing: border-box;\n padding: var(--spacing-3);\n border: 2px solid var(--input);\n border-radius: var(--radius);\n font-size: var(--font-size-sm);\n resize: vertical;\n outline: none;\n transition: border-color 0.2s ease;\n font-family: inherit;\n background: var(--background);\n color: var(--foreground);\n}\n\n.textarea-element:focus {\n border-color: var(--ring);\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.textarea-wrapper--read-only .textarea-label {\n color: var(--muted-foreground);\n}\n\n.textarea-element:read-only {\n background: var(--muted);\n color: var(--muted-foreground);\n border-color: var(--border);\n cursor: not-allowed;\n resize: none;\n}\n\n.textarea-element:read-only:focus {\n border-color: var(--border);\n box-shadow: none;\n}\n\n.help-text {\n margin-top: var(--spacing-1);\n font-size: var(--font-size-xs);\n color: var(--muted-foreground, #6b7280);\n line-height: 1.4;\n}\n","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",".chat-history {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3);\n margin-top: var(--spacing-4);\n}\n\n.chat-history__toggle-row {\n display: flex;\n align-items: center;\n}\n\n.chat-history__switch {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-3);\n cursor: pointer;\n user-select: none;\n}\n\n.chat-history__switch-input {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.chat-history__switch-ui {\n position: relative;\n flex-shrink: 0;\n width: 2.75rem;\n height: 1.5rem;\n border-radius: var(--radius-full);\n background: var(--muted);\n border: var(--border-width) solid var(--border);\n transition:\n background 0.15s ease,\n border-color 0.15s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chat-history__switch-ui,\n .chat-history__switch-thumb {\n transition: none;\n }\n}\n\n.chat-history__switch-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(1.5rem - 6px);\n height: calc(1.5rem - 6px);\n border-radius: var(--radius-full);\n background: var(--background);\n box-shadow: var(--shadow-sm);\n transition: transform 0.15s ease;\n}\n\n.chat-history__switch-input:checked + .chat-history__switch-ui {\n background: var(--primary);\n border-color: var(--primary);\n}\n\n.chat-history__switch-input:checked + .chat-history__switch-ui .chat-history__switch-thumb {\n /* track width − end padding (2px × 2) − thumb width */\n transform: translateX(calc(2.75rem - (1.5rem - 6px) - 4px));\n}\n\n.chat-history__switch-input:focus-visible + .chat-history__switch-ui {\n outline: 2px solid var(--ring);\n outline-offset: 2px;\n}\n\n.chat-history__switch-text {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--foreground);\n}\n\n.chat-history__textarea {\n width: 100%;\n box-sizing: border-box;\n padding: var(--spacing-2) var(--spacing-3);\n border: var(--border-width) solid var(--border);\n border-radius: var(--radius-md);\n font: inherit;\n resize: vertical;\n min-height: 9rem;\n background: var(--background);\n}\n\n.chat-history__textarea:focus-visible {\n outline: 2px solid var(--ring);\n outline-offset: 2px;\n}\n","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"],"version":3}
|
package/dist/cjs/index.cjs.js
CHANGED
|
@@ -106,6 +106,10 @@ function formatTestSuiteAsJson(testCases) {
|
|
|
106
106
|
id: testCase.id,
|
|
107
107
|
question: testCase.question,
|
|
108
108
|
expectedOutcome: testCase.expectedOutcome,
|
|
109
|
+
chatHistory: {
|
|
110
|
+
enabled: testCase.chatHistory.enabled,
|
|
111
|
+
value: testCase.chatHistory.value,
|
|
112
|
+
},
|
|
109
113
|
}));
|
|
110
114
|
return JSON.stringify(exportData, null, 2);
|
|
111
115
|
}
|
|
@@ -303,6 +307,7 @@ function createTestCase(expectedOutcomeSchema = DEFAULT_EXPECTED_OUTCOME_SCHEMA)
|
|
|
303
307
|
id: v4(),
|
|
304
308
|
question: '',
|
|
305
309
|
expectedOutcome: createExpectedOutcomeFromSchema(expectedOutcomeSchema),
|
|
310
|
+
chatHistory: { enabled: false, value: '' },
|
|
306
311
|
isRunning: false,
|
|
307
312
|
};
|
|
308
313
|
}
|
|
@@ -362,6 +367,7 @@ function createExpectedOutcomeFromSchema(expectedOutcomeSchema) {
|
|
|
362
367
|
function createTestCaseFromInput(data) {
|
|
363
368
|
return {
|
|
364
369
|
...data,
|
|
370
|
+
chatHistory: data.chatHistory ?? { enabled: false, value: '' },
|
|
365
371
|
expectedOutcome: data.expectedOutcome.map(normalizeExpectedOutcomeField),
|
|
366
372
|
};
|
|
367
373
|
}
|
|
@@ -4955,6 +4961,7 @@ const optionalPositiveInt = number().int().positive().optional();
|
|
|
4955
4961
|
const optionalString = string().optional();
|
|
4956
4962
|
const selectOptionsSchema = array(nonEmptyString).min(1);
|
|
4957
4963
|
const optionalNumber = number().optional();
|
|
4964
|
+
const expectedOutcomeModeSchema = _enum(['static', 'dynamic']);
|
|
4958
4965
|
const evaluationParametersSchema = object({
|
|
4959
4966
|
approach: _enum(EvaluationApproach),
|
|
4960
4967
|
threshold: optionalNumber,
|
|
@@ -5016,8 +5023,21 @@ const expectedOutcomeFieldSchema = discriminatedUnion('type', [
|
|
|
5016
5023
|
defaultFieldDefinitions.text.extend({
|
|
5017
5024
|
value: string(),
|
|
5018
5025
|
}),
|
|
5019
|
-
defaultFieldDefinitions.textarea
|
|
5026
|
+
defaultFieldDefinitions.textarea
|
|
5027
|
+
.extend({
|
|
5020
5028
|
value: string(),
|
|
5029
|
+
outcomeMode: expectedOutcomeModeSchema.default('static'),
|
|
5030
|
+
resolutionQuery: string().optional(),
|
|
5031
|
+
})
|
|
5032
|
+
.superRefine((field, ctx) => {
|
|
5033
|
+
if (field.outcomeMode === 'dynamic' &&
|
|
5034
|
+
(!field.resolutionQuery || field.resolutionQuery.trim().length === 0)) {
|
|
5035
|
+
ctx.addIssue({
|
|
5036
|
+
code: 'custom',
|
|
5037
|
+
path: ['resolutionQuery'],
|
|
5038
|
+
message: 'resolutionQuery is required when outcomeMode is dynamic.',
|
|
5039
|
+
});
|
|
5040
|
+
}
|
|
5021
5041
|
}),
|
|
5022
5042
|
defaultFieldDefinitions.chipsInput.extend({
|
|
5023
5043
|
value: array(string()).superRefine((values, ctx) => {
|
|
@@ -5051,16 +5071,22 @@ function validateExpectedOutcomeSchema(schema) {
|
|
|
5051
5071
|
}
|
|
5052
5072
|
}
|
|
5053
5073
|
|
|
5074
|
+
const testCaseChatHistorySchema = object({
|
|
5075
|
+
enabled: boolean(),
|
|
5076
|
+
value: string(),
|
|
5077
|
+
});
|
|
5054
5078
|
const testCaseInputSchema = object({
|
|
5055
5079
|
id: string(),
|
|
5056
5080
|
question: string(),
|
|
5057
5081
|
expectedOutcome: expectedOutcomeArraySchema,
|
|
5082
|
+
chatHistory: testCaseChatHistorySchema.optional(),
|
|
5058
5083
|
});
|
|
5059
5084
|
const testCaseInputArraySchema = array(testCaseInputSchema);
|
|
5060
5085
|
object({
|
|
5061
5086
|
id: string(),
|
|
5062
5087
|
question: string(),
|
|
5063
5088
|
expectedOutcome: expectedOutcomeArraySchema,
|
|
5089
|
+
chatHistory: testCaseChatHistorySchema,
|
|
5064
5090
|
output: string().optional(),
|
|
5065
5091
|
isRunning: boolean().optional(),
|
|
5066
5092
|
error: string().optional(),
|
|
@@ -5111,6 +5137,50 @@ function importTestSuite(jsonContent) {
|
|
|
5111
5137
|
}
|
|
5112
5138
|
}
|
|
5113
5139
|
|
|
5140
|
+
const MISSING_RESOLVER_MESSAGE = 'resolveExpectedOutcome is required when a test case has dynamic expected outcomes.';
|
|
5141
|
+
function isDynamicTextareaField(field) {
|
|
5142
|
+
return field.type === 'textarea' && field.outcomeMode === 'dynamic';
|
|
5143
|
+
}
|
|
5144
|
+
function applyResolvedDynamicValues(testCase, resolvedValues) {
|
|
5145
|
+
if (resolvedValues.length === 0) {
|
|
5146
|
+
return testCase;
|
|
5147
|
+
}
|
|
5148
|
+
const expectedOutcome = [...(testCase.expectedOutcome || [])];
|
|
5149
|
+
for (const resolved of resolvedValues) {
|
|
5150
|
+
const field = expectedOutcome[resolved.index];
|
|
5151
|
+
if (!field || !isDynamicTextareaField(field)) {
|
|
5152
|
+
continue;
|
|
5153
|
+
}
|
|
5154
|
+
expectedOutcome[resolved.index] = {
|
|
5155
|
+
...field,
|
|
5156
|
+
value: resolved.value,
|
|
5157
|
+
};
|
|
5158
|
+
}
|
|
5159
|
+
return {
|
|
5160
|
+
...testCase,
|
|
5161
|
+
expectedOutcome,
|
|
5162
|
+
};
|
|
5163
|
+
}
|
|
5164
|
+
async function resolveDynamicExpectedOutcomes(testCase, resolver) {
|
|
5165
|
+
const dynamicFields = (testCase.expectedOutcome || []).flatMap((field, index) => {
|
|
5166
|
+
if (!isDynamicTextareaField(field)) {
|
|
5167
|
+
return [];
|
|
5168
|
+
}
|
|
5169
|
+
return [{ field, index }];
|
|
5170
|
+
});
|
|
5171
|
+
if (dynamicFields.length === 0) {
|
|
5172
|
+
return testCase;
|
|
5173
|
+
}
|
|
5174
|
+
if (!resolver) {
|
|
5175
|
+
throw new Error(MISSING_RESOLVER_MESSAGE);
|
|
5176
|
+
}
|
|
5177
|
+
const resolvedValues = await Promise.all(dynamicFields.map(async ({ field, index }) => ({
|
|
5178
|
+
index,
|
|
5179
|
+
value: await resolver(field.resolutionQuery || '', { testCase, fieldIndex: index }),
|
|
5180
|
+
})));
|
|
5181
|
+
return applyResolvedDynamicValues(testCase, resolvedValues);
|
|
5182
|
+
}
|
|
5183
|
+
|
|
5114
5184
|
function applyExpectedOutcomeChange(testCase, change) {
|
|
5115
5185
|
const { index } = change;
|
|
5116
5186
|
const expectedOutcome = [...(testCase.expectedOutcome || [])];
|
|
@@ -5123,6 +5193,9 @@ function applyExpectedOutcomeChange(testCase, change) {
|
|
|
5123
5193
|
if (target.type === 'chips-input') {
|
|
5124
5194
|
return testCase;
|
|
5125
5195
|
}
|
|
5196
|
+
if (target.type === 'textarea' && target.outcomeMode === 'dynamic') {
|
|
5197
|
+
return testCase;
|
|
5198
|
+
}
|
|
5126
5199
|
expectedOutcome[index] = {
|
|
5127
5200
|
...target,
|
|
5128
5201
|
value: change.value,
|
|
@@ -5151,6 +5224,38 @@ function applyExpectedOutcomeChange(testCase, change) {
|
|
|
5151
5224
|
}
|
|
5152
5225
|
case 'set-evaluation-approach':
|
|
5153
5226
|
return updateExpectedOutcomeFieldApproach(testCase, index, change.value);
|
|
5227
|
+
case 'set-outcome-mode': {
|
|
5228
|
+
if (target.type !== 'textarea') {
|
|
5229
|
+
return testCase;
|
|
5230
|
+
}
|
|
5231
|
+
const mode = change.value;
|
|
5232
|
+
if (mode === 'static') {
|
|
5233
|
+
const { resolutionQuery: _, ...rest } = target;
|
|
5234
|
+
expectedOutcome[index] = {
|
|
5235
|
+
...rest,
|
|
5236
|
+
outcomeMode: 'static',
|
|
5237
|
+
value: '',
|
|
5238
|
+
};
|
|
5239
|
+
}
|
|
5240
|
+
else {
|
|
5241
|
+
expectedOutcome[index] = {
|
|
5242
|
+
...target,
|
|
5243
|
+
outcomeMode: 'dynamic',
|
|
5244
|
+
value: '',
|
|
5245
|
+
};
|
|
5246
|
+
}
|
|
5247
|
+
return { ...testCase, expectedOutcome };
|
|
5248
|
+
}
|
|
5249
|
+
case 'set-resolution-query': {
|
|
5250
|
+
if (target.type !== 'textarea' || target.outcomeMode !== 'dynamic') {
|
|
5251
|
+
return testCase;
|
|
5252
|
+
}
|
|
5253
|
+
expectedOutcome[index] = {
|
|
5254
|
+
...target,
|
|
5255
|
+
resolutionQuery: change.value,
|
|
5256
|
+
};
|
|
5257
|
+
return { ...testCase, expectedOutcome };
|
|
5258
|
+
}
|
|
5154
5259
|
}
|
|
5155
5260
|
}
|
|
5156
5261
|
/**
|
|
@@ -30018,13 +30123,20 @@ class EvaluationService {
|
|
|
30018
30123
|
console.warn('⚠️ No output to evaluate for test case:', testCase.id);
|
|
30019
30124
|
return;
|
|
30020
30125
|
}
|
|
30021
|
-
const fields = (testCase.expectedOutcome || []).
|
|
30022
|
-
|
|
30023
|
-
|
|
30024
|
-
|
|
30025
|
-
|
|
30026
|
-
|
|
30027
|
-
|
|
30126
|
+
const fields = (testCase.expectedOutcome || []).flatMap((field, index) => {
|
|
30127
|
+
if (field.type === 'textarea' && field.outcomeMode === 'dynamic') {
|
|
30128
|
+
return [];
|
|
30129
|
+
}
|
|
30130
|
+
return [
|
|
30131
|
+
{
|
|
30132
|
+
index,
|
|
30133
|
+
label: field.label,
|
|
30134
|
+
type: field.type,
|
|
30135
|
+
expectedValue: getFieldExpectedValue(field),
|
|
30136
|
+
evaluationParameters: normalizeEvaluationParametersForField(field.type, field.evaluationParameters),
|
|
30137
|
+
},
|
|
30138
|
+
];
|
|
30139
|
+
});
|
|
30028
30140
|
const evaluationRequest = {
|
|
30029
30141
|
testCaseId: testCase.id,
|
|
30030
30142
|
question: testCase.question,
|
|
@@ -30119,7 +30231,7 @@ var FormFieldType;
|
|
|
30119
30231
|
FormFieldType["SELECT"] = "select";
|
|
30120
30232
|
})(FormFieldType || (FormFieldType = {}));
|
|
30121
30233
|
|
|
30122
|
-
const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange, }) => {
|
|
30234
|
+
const ExpectedOutcomeRenderer = ({ testCaseId, fields, dynamicResolutionSupported = false, onExpectedOutcomeChange, }) => {
|
|
30123
30235
|
const emit = (detail) => onExpectedOutcomeChange({
|
|
30124
30236
|
detail,
|
|
30125
30237
|
});
|
|
@@ -30132,6 +30244,23 @@ const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange,
|
|
|
30132
30244
|
optionList,
|
|
30133
30245
|
defaultValue: EvaluationApproach.EXACT,
|
|
30134
30246
|
});
|
|
30247
|
+
const buildOutcomeModeConfig = (index) => ({
|
|
30248
|
+
name: `expectedOutcomeMode-${index}`,
|
|
30249
|
+
fieldType: FormFieldType.SELECT,
|
|
30250
|
+
label: 'Outcome Mode',
|
|
30251
|
+
placeholder: 'Select outcome mode',
|
|
30252
|
+
required: true,
|
|
30253
|
+
optionList: ['static', 'dynamic'],
|
|
30254
|
+
defaultValue: 'static',
|
|
30255
|
+
});
|
|
30256
|
+
const buildResolutionQueryConfig = (index) => ({
|
|
30257
|
+
name: `expectedOutcomeResolutionQuery-${index}`,
|
|
30258
|
+
fieldType: FormFieldType.TEXT_AREA,
|
|
30259
|
+
label: 'Resolution Query',
|
|
30260
|
+
placeholder: 'Query used to resolve expected value',
|
|
30261
|
+
required: false,
|
|
30262
|
+
rows: 2,
|
|
30263
|
+
});
|
|
30135
30264
|
const renderEvaluationSelector = (field, index$1) => {
|
|
30136
30265
|
const optionList = getAllowedApproachesForFieldType(field.type);
|
|
30137
30266
|
return (index.h("app-select", { config: buildEvaluationConfig(index$1, optionList), value: field.evaluationParameters?.approach, onValueChange: (e) => emit({
|
|
@@ -30143,12 +30272,17 @@ const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange,
|
|
|
30143
30272
|
};
|
|
30144
30273
|
return (index.h("div", { class: "expected-outcome-renderer" }, (fields || []).map((field, index$1) => {
|
|
30145
30274
|
if (field.type === 'textarea') {
|
|
30275
|
+
const isDynamic = dynamicResolutionSupported && field.outcomeMode === 'dynamic';
|
|
30146
30276
|
const config = {
|
|
30147
30277
|
name: `expectedOutcome-${index$1}`,
|
|
30148
30278
|
fieldType: FormFieldType.TEXT_AREA,
|
|
30149
30279
|
label: field.label,
|
|
30150
|
-
placeholder: field.placeholder,
|
|
30151
|
-
required:
|
|
30280
|
+
placeholder: isDynamic ? 'Resolved on run' : field.placeholder,
|
|
30281
|
+
required: !isDynamic,
|
|
30282
|
+
readOnly: isDynamic,
|
|
30283
|
+
helpText: isDynamic
|
|
30284
|
+
? 'Filled automatically when the test is run'
|
|
30285
|
+
: undefined,
|
|
30152
30286
|
rows: field.rows || 2,
|
|
30153
30287
|
};
|
|
30154
30288
|
return (index.h("div", { class: "expected-outcome-renderer__group" }, index.h("app-textarea", { config: config, value: field.value, onValueChange: (e) => emit({
|
|
@@ -30156,7 +30290,18 @@ const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange,
|
|
|
30156
30290
|
index: index$1,
|
|
30157
30291
|
operation: 'set-value',
|
|
30158
30292
|
value: e.detail.value,
|
|
30159
|
-
}) }),
|
|
30293
|
+
}) }), dynamicResolutionSupported && (index.h("app-select", { config: buildOutcomeModeConfig(index$1), value: field.outcomeMode || 'static', onValueChange: (e) => emit({
|
|
30294
|
+
testCaseId,
|
|
30295
|
+
index: index$1,
|
|
30296
|
+
operation: 'set-outcome-mode',
|
|
30297
|
+
value: e.detail.value,
|
|
30298
|
+
}) })), dynamicResolutionSupported &&
|
|
30299
|
+
field.outcomeMode === 'dynamic' && (index.h("app-textarea", { config: buildResolutionQueryConfig(index$1), value: field.resolutionQuery || '', onValueChange: (e) => emit({
|
|
30300
|
+
testCaseId,
|
|
30301
|
+
index: index$1,
|
|
30302
|
+
operation: 'set-resolution-query',
|
|
30303
|
+
value: e.detail.value,
|
|
30304
|
+
}) })), !isDynamic && renderEvaluationSelector(field, index$1)));
|
|
30160
30305
|
}
|
|
30161
30306
|
if (field.type === 'chips-input') {
|
|
30162
30307
|
const config = {
|
|
@@ -30203,7 +30348,7 @@ const ExpectedOutcomeRenderer = ({ testCaseId, fields, onExpectedOutcomeChange,
|
|
|
30203
30348
|
})));
|
|
30204
30349
|
};
|
|
30205
30350
|
|
|
30206
|
-
const LLMTestCaseRow = ({ testCase, onRun, onDelete, handleTestCaseChange, onExpectedOutcomeChange, }) => {
|
|
30351
|
+
const LLMTestCaseRow = ({ testCase, dynamicResolutionSupported = false, onRun, onDelete, handleTestCaseChange, onExpectedOutcomeChange, onChatHistoryChange, }) => {
|
|
30207
30352
|
const questionConfig = {
|
|
30208
30353
|
name: 'question',
|
|
30209
30354
|
fieldType: FormFieldType.TEXT_AREA,
|
|
@@ -30219,11 +30364,21 @@ const LLMTestCaseRow = ({ testCase, onRun, onDelete, handleTestCaseChange, onExp
|
|
|
30219
30364
|
key: 'question',
|
|
30220
30365
|
value: e.detail.value,
|
|
30221
30366
|
},
|
|
30222
|
-
}) }), index.h(
|
|
30367
|
+
}) }), index.h("chat-history", { chatHistoryEnabled: testCase.chatHistory?.enabled ?? false, chatHistoryValue: testCase.chatHistory?.value ?? '', onChatHistoryChange: (e) => {
|
|
30368
|
+
const { enabled, value } = e
|
|
30369
|
+
.detail;
|
|
30370
|
+
onChatHistoryChange({
|
|
30371
|
+
detail: {
|
|
30372
|
+
testCaseId: testCase.id,
|
|
30373
|
+
enabled,
|
|
30374
|
+
value,
|
|
30375
|
+
},
|
|
30376
|
+
});
|
|
30377
|
+
} }), index.h(ExpectedOutcomeRenderer, { testCaseId: testCase.id, fields: testCase.expectedOutcome || [], dynamicResolutionSupported: dynamicResolutionSupported, onExpectedOutcomeChange: onExpectedOutcomeChange })), index.h(ResponseOutput, { output: testCase.output, isRunning: testCase.isRunning }), index.h(EvaluationSummary, { result: testCase.evaluationResult, isRunning: testCase.isRunning }), index.h(RowActions, { isRunning: testCase.isRunning, canRun: !!testCase.question.trim(), onRun: () => onRun(testCase), onDelete: () => onDelete(testCase.id) })));
|
|
30223
30378
|
};
|
|
30224
30379
|
|
|
30225
|
-
const LLMTestCases = ({ testCases, onRun, onDelete, onAddTestCase, handleTestCaseChange, onExpectedOutcomeChange, }) => {
|
|
30226
|
-
return (index.h("div", { class: "test-cases" }, index.h("div", { class: "test-cases__column-headers" }, index.h("div", { class: "test-cases__column-header" }, "Input"), index.h("div", { class: "test-cases__column-header" }, "Output"), index.h("div", { class: "test-cases__column-header" }, "Evaluation"), index.h("div", { class: "test-cases__column-header" }, "Actions")), testCases.map(testCase => (index.h(LLMTestCaseRow, { testCase: testCase, onRun: onRun, onDelete: onDelete, handleTestCaseChange: handleTestCaseChange, onExpectedOutcomeChange: onExpectedOutcomeChange }))), index.h("div", { class: "test-cases__add-section" }, index.h(Button, { variant: "outline", size: "md", onClick: onAddTestCase }, "+ Add Question"))));
|
|
30380
|
+
const LLMTestCases = ({ testCases, dynamicResolutionSupported = false, onRun, onDelete, onAddTestCase, handleTestCaseChange, onExpectedOutcomeChange, onChatHistoryChange, }) => {
|
|
30381
|
+
return (index.h("div", { class: "test-cases" }, index.h("div", { class: "test-cases__column-headers" }, index.h("div", { class: "test-cases__column-header" }, "Input"), index.h("div", { class: "test-cases__column-header" }, "Output"), index.h("div", { class: "test-cases__column-header" }, "Evaluation"), index.h("div", { class: "test-cases__column-header" }, "Actions")), testCases.map(testCase => (index.h(LLMTestCaseRow, { testCase: testCase, dynamicResolutionSupported: dynamicResolutionSupported, onRun: onRun, onDelete: onDelete, handleTestCaseChange: handleTestCaseChange, onExpectedOutcomeChange: onExpectedOutcomeChange, onChatHistoryChange: onChatHistoryChange }))), index.h("div", { class: "test-cases__add-section" }, index.h(Button, { variant: "outline", size: "md", onClick: onAddTestCase }, "+ Add Question"))));
|
|
30227
30382
|
};
|
|
30228
30383
|
|
|
30229
30384
|
const tokensCss = () => `:host{--spacing:0.25rem;--spacing-1:calc(var(--spacing) * 1);--spacing-2:calc(var(--spacing) * 2);--spacing-3:calc(var(--spacing) * 3);--spacing-4:calc(var(--spacing) * 4);--spacing-5:calc(var(--spacing) * 5);--spacing-6:calc(var(--spacing) * 6);--spacing-8:calc(var(--spacing) * 8);--spacing-10:calc(var(--spacing) * 10);--spacing-12:calc(var(--spacing) * 12);--spacing-16:calc(var(--spacing) * 16);--spacing-20:calc(var(--spacing) * 20);--spacing-24:calc(var(--spacing) * 24);--radius-none:0;--radius-sm:0.125rem;--radius-md:0.375rem;--radius-lg:0.5rem;--radius-xl:0.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-full:9999px;--radius:var(--radius-lg);--font-size-xs:0.75rem;--font-size-sm:0.875rem;--font-size-base:1rem;--font-size-lg:1.125rem;--font-size-xl:1.25rem;--font-size-2xl:1.5rem;--font-size-3xl:1.875rem;--font-size-4xl:2.25rem;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-none:1;--line-height-tight:1.25;--line-height-snug:1.375;--line-height-normal:1.5;--line-height-relaxed:1.625;--line-height-loose:2;--letter-spacing-tight:-0.025em;--letter-spacing-normal:0;--letter-spacing-wide:0.05em;--shadow-sm:0 1px 2px 0 rgba(0, 0, 0, 0.05);--shadow-md:0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);--shadow-lg:0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);--shadow-xl:0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);--shadow-2xl:0 25px 50px -12px rgba(0, 0, 0, 0.25);--border-width:1px;--z-base:0;--z-dropdown:1000;--z-sticky:1100;--z-modal:1200;--z-popover:1300;--z-tooltip:1400;--opacity-disabled:0.5;--opacity-hover:0.8;--opacity-muted:0.6;--max-w-sm:24rem;--max-w-md:28rem;--max-w-lg:32rem;--max-w-xl:42rem;--max-w-2xl:48rem;--max-w-full:100%;--breakpoint-sm:640px;--breakpoint-md:768px;--breakpoint-lg:1024px;--breakpoint-xl:1280px;--breakpoint-2xl:1536px;--background:#ffffff;--foreground:#0a0a0a;--card:#ffffff;--card-foreground:#0a0a0a;--popover:#ffffff;--popover-foreground:#0a0a0a;--primary:#0a0a0a;--primary-foreground:#fafafa;--secondary:#f4f4f5;--secondary-foreground:#0a0a0a;--muted:#f4f4f5;--muted-foreground:#71717a;--accent:#f4f4f5;--accent-foreground:#0a0a0a;--destructive:#ef4444;--destructive-foreground:#fafafa;--border:#e4e4e7;--input:#e4e4e7;--ring:#3b82f6;--success:#10b981;--success-foreground:#fafafa;--warning:#f59e0b;--warning-foreground:#fafafa;--info:#3b82f6;--info-foreground:#fafafa}:host([data-theme='dark']){--background:#0a0a0a;--foreground:#fafafa;--card:#171717;--card-foreground:#fafafa;--popover:#171717;--popover-foreground:#fafafa;--primary:#fafafa;--primary-foreground:#0a0a0a;--secondary:#27272a;--secondary-foreground:#fafafa;--muted:#27272a;--muted-foreground:#a1a1aa;--accent:#27272a;--accent-foreground:#fafafa;--destructive:#dc2626;--destructive-foreground:#fafafa;--border:#27272a;--input:#27272a;--ring:#3b82f6;--success:#059669;--success-foreground:#fafafa;--warning:#d97706;--warning-foreground:#fafafa;--info:#2563eb;--info-foreground:#fafafa}`;
|
|
@@ -30259,6 +30414,7 @@ const LLMTestRunner = class {
|
|
|
30259
30414
|
delayMs = 500;
|
|
30260
30415
|
useSave = false;
|
|
30261
30416
|
usePromptEditor = false;
|
|
30417
|
+
resolveExpectedOutcome;
|
|
30262
30418
|
initialTestCases;
|
|
30263
30419
|
defaultExpectedOutcomeSchema;
|
|
30264
30420
|
testCases = [
|
|
@@ -30272,6 +30428,7 @@ const LLMTestRunner = class {
|
|
|
30272
30428
|
value: '',
|
|
30273
30429
|
},
|
|
30274
30430
|
],
|
|
30431
|
+
chatHistory: { enabled: false, value: '' },
|
|
30275
30432
|
isRunning: false,
|
|
30276
30433
|
},
|
|
30277
30434
|
];
|
|
@@ -30329,6 +30486,12 @@ const LLMTestRunner = class {
|
|
|
30329
30486
|
const { testCaseId, key, value } = event.detail;
|
|
30330
30487
|
this.testCases = this.testCases.map(tc => tc.id === testCaseId ? { ...tc, [key]: value } : tc);
|
|
30331
30488
|
};
|
|
30489
|
+
handleChatHistoryChange = (event) => {
|
|
30490
|
+
const { testCaseId, enabled, value } = event.detail;
|
|
30491
|
+
this.updateTestCase(testCaseId, {
|
|
30492
|
+
chatHistory: { enabled, value },
|
|
30493
|
+
});
|
|
30494
|
+
};
|
|
30332
30495
|
addNewTestCase() {
|
|
30333
30496
|
try {
|
|
30334
30497
|
const schema = this.getResolvedExpectedOutcomeSchema();
|
|
@@ -30345,38 +30508,66 @@ const LLMTestRunner = class {
|
|
|
30345
30508
|
updateTestCase(id, updates) {
|
|
30346
30509
|
this.testCases = this.testCases.map(tc => tc.id === id ? { ...tc, ...updates } : tc);
|
|
30347
30510
|
}
|
|
30511
|
+
requestLlmText(testCase) {
|
|
30512
|
+
return new Promise((resolve, reject) => {
|
|
30513
|
+
const payload = {
|
|
30514
|
+
prompt: testCase.question,
|
|
30515
|
+
resolve,
|
|
30516
|
+
reject,
|
|
30517
|
+
};
|
|
30518
|
+
if (testCase.chatHistory?.enabled) {
|
|
30519
|
+
payload.chatHistory = testCase.chatHistory.value;
|
|
30520
|
+
}
|
|
30521
|
+
this.llmRequest.emit(payload);
|
|
30522
|
+
});
|
|
30523
|
+
}
|
|
30524
|
+
throwError(reason) {
|
|
30525
|
+
throw reason instanceof Error ? reason : new Error(String(reason));
|
|
30526
|
+
}
|
|
30527
|
+
addErrorMessage(reason, fallback) {
|
|
30528
|
+
return reason instanceof Error ? reason.message : fallback;
|
|
30529
|
+
}
|
|
30348
30530
|
async runSingleTest(testCase) {
|
|
30349
30531
|
const startTime = Date.now();
|
|
30350
30532
|
this.updateTestCase(testCase.id, { isRunning: true });
|
|
30351
|
-
|
|
30352
|
-
this.
|
|
30353
|
-
|
|
30354
|
-
|
|
30355
|
-
|
|
30356
|
-
|
|
30357
|
-
|
|
30358
|
-
|
|
30359
|
-
|
|
30360
|
-
|
|
30361
|
-
|
|
30362
|
-
});
|
|
30363
|
-
await this.evaluateResponse({
|
|
30364
|
-
...testCase,
|
|
30365
|
-
output: aiResponse,
|
|
30366
|
-
responseTime: responseTime,
|
|
30367
|
-
});
|
|
30368
|
-
resolve();
|
|
30369
|
-
},
|
|
30370
|
-
reject: (error) => {
|
|
30371
|
-
this.updateTestCase(testCase.id, {
|
|
30372
|
-
isRunning: false,
|
|
30373
|
-
output: null,
|
|
30374
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
30375
|
-
});
|
|
30376
|
-
reject(error);
|
|
30377
|
-
},
|
|
30533
|
+
const [llmSettled, resolutionSettled] = await Promise.allSettled([
|
|
30534
|
+
this.requestLlmText(testCase),
|
|
30535
|
+
resolveDynamicExpectedOutcomes(testCase, this.resolveExpectedOutcome),
|
|
30536
|
+
]);
|
|
30537
|
+
const responseTime = Date.now() - startTime;
|
|
30538
|
+
if (llmSettled.status === 'rejected') {
|
|
30539
|
+
this.updateTestCase(testCase.id, {
|
|
30540
|
+
isRunning: false,
|
|
30541
|
+
output: null,
|
|
30542
|
+
error: this.addErrorMessage(llmSettled.reason, 'Unknown error'),
|
|
30543
|
+
responseTime,
|
|
30378
30544
|
});
|
|
30545
|
+
this.throwError(llmSettled.reason);
|
|
30546
|
+
}
|
|
30547
|
+
const aiResponse = llmSettled.value;
|
|
30548
|
+
if (resolutionSettled.status === 'rejected') {
|
|
30549
|
+
this.updateTestCase(testCase.id, {
|
|
30550
|
+
isRunning: false,
|
|
30551
|
+
output: aiResponse,
|
|
30552
|
+
error: this.addErrorMessage(resolutionSettled.reason, 'Failed to resolve dynamic expected outcome.'),
|
|
30553
|
+
responseTime,
|
|
30554
|
+
});
|
|
30555
|
+
this.throwError(resolutionSettled.reason);
|
|
30556
|
+
}
|
|
30557
|
+
const resolvedTestCase = resolutionSettled.value;
|
|
30558
|
+
const forEvaluationTestCase = {
|
|
30559
|
+
...resolvedTestCase,
|
|
30560
|
+
output: aiResponse,
|
|
30561
|
+
responseTime,
|
|
30562
|
+
};
|
|
30563
|
+
this.updateTestCase(testCase.id, {
|
|
30564
|
+
isRunning: false,
|
|
30565
|
+
output: aiResponse,
|
|
30566
|
+
error: null,
|
|
30567
|
+
responseTime,
|
|
30568
|
+
expectedOutcome: forEvaluationTestCase.expectedOutcome,
|
|
30379
30569
|
});
|
|
30570
|
+
await this.evaluateResponse(forEvaluationTestCase);
|
|
30380
30571
|
}
|
|
30381
30572
|
deleteTestCase(id) {
|
|
30382
30573
|
this.testCases = this.testCases.filter(tc => tc.id !== id);
|
|
@@ -30487,7 +30678,7 @@ const LLMTestRunner = class {
|
|
|
30487
30678
|
}
|
|
30488
30679
|
}
|
|
30489
30680
|
render() {
|
|
30490
|
-
return (index.h("div", { key: '
|
|
30681
|
+
return (index.h("div", { key: 'cc808096f929b2e1c570c53144aab195d177c187', class: "test-runner-container" }, index.h(LLMTestRunnerHeader, { key: 'b91cf3df7df0e95bfd4908a2f91c7310b5b7a09a', isExportingTestSuite: this.isExportingTestSuite, isExportingTestResults: this.isExportingTestResults, isRunningAll: this.isRunningAll, useSave: this.useSave, isSaving: this.isSaving, usePromptEditor: this.usePromptEditor, onImport: file => this.handleImport(file), onExportSuite: () => this.handleExportTestSuite(), onExportResults: () => this.handleExportTestResults(), onRunAll: () => this.runAllTests(), onSave: () => this.handleSave() }), index.h(ErrorMessage, { key: 'c7991497173fa9843e7aa42f5283d0897ddff2e2', message: this.error, onClear: () => (this.error = '') }), index.h("div", { key: '2b57132564442b8047d8672c6adcba62cdc9ae87', class: "test-runner-container__content" }, index.h(LLMTestCases, { key: '146e9d8c76a34980a2a274dd856887c22e1ed0e9', testCases: this.testCases, dynamicResolutionSupported: !!this.resolveExpectedOutcome, onRun: testCase => this.runSingleTest(testCase).catch(() => { }), onDelete: id => this.deleteTestCase(id), onAddTestCase: () => this.addNewTestCase(), handleTestCaseChange: this.handleTestCaseChange, onExpectedOutcomeChange: this.handleExpectedOutcomeChange, onChatHistoryChange: this.handleChatHistoryChange }))));
|
|
30491
30682
|
}
|
|
30492
30683
|
};
|
|
30493
30684
|
LLMTestRunner.style = tokensCss() + (llmTestRunnerCss() + (llmTestRunnerHeaderCss() + (llmTestCasesCss() + (llmTestCaseRowCss() + (rowActionsCss() + (evaluationSummaryCss() + (responseOutputCss() + (errorMessageCss() + (buttonCss() + iconButtonCss())))))))));
|