llm-testrunner-components 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/cjs/{app-chips_4.cjs.entry.js → app-chips_5.cjs.entry.js} +41 -6
  2. package/dist/cjs/app-chips_5.cjs.entry.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +235 -44
  4. package/dist/cjs/index.cjs.js.map +1 -1
  5. package/dist/cjs/llm-testrunner.cjs.js +1 -1
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/collection/collection-manifest.json +1 -0
  8. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js +22 -12
  9. package/dist/collection/components/llm-test-runner/llm-test-runner.import-export.test.js.map +1 -1
  10. package/dist/collection/components/llm-test-runner/llm-test-runner.js +91 -30
  11. package/dist/collection/components/llm-test-runner/llm-test-runner.js.map +1 -1
  12. package/dist/collection/components/llm-test-runner/test-cases/chat-history.css +101 -0
  13. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js +105 -0
  14. package/dist/collection/components/llm-test-runner/test-cases/chat-history.js.map +1 -0
  15. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js +37 -4
  16. package/dist/collection/components/llm-test-runner/test-cases/expected-outcome-renderer.js.map +1 -1
  17. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js +12 -2
  18. package/dist/collection/components/llm-test-runner/test-cases/llm-test-case-row.js.map +1 -1
  19. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js +2 -2
  20. package/dist/collection/components/llm-test-runner/test-cases/llm-test-cases.js.map +1 -1
  21. package/dist/collection/index.js.map +1 -1
  22. package/dist/collection/lib/evaluation/evaluation-service.js +14 -7
  23. package/dist/collection/lib/evaluation/evaluation-service.js.map +1 -1
  24. package/dist/collection/lib/form/components/app-chips.js +1 -1
  25. package/dist/collection/lib/form/components/app-select.js +1 -1
  26. package/dist/collection/lib/form/components/app-textarea.css +17 -0
  27. package/dist/collection/lib/form/components/app-textarea.js +4 -1
  28. package/dist/collection/lib/form/components/app-textarea.js.map +1 -1
  29. package/dist/collection/lib/import-export/test-suite-exporter.js +4 -0
  30. package/dist/collection/lib/import-export/test-suite-exporter.js.map +1 -1
  31. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js +44 -0
  32. package/dist/collection/lib/test-cases/dynamic-expected-outcome-resolver.js.map +1 -0
  33. package/dist/collection/lib/test-cases/test-case-factory.js +2 -0
  34. package/dist/collection/lib/test-cases/test-case-factory.js.map +1 -1
  35. package/dist/collection/lib/test-cases/test-case-mutations.js +35 -0
  36. package/dist/collection/lib/test-cases/test-case-mutations.js.map +1 -1
  37. package/dist/collection/schemas/expected-outcome.js +15 -1
  38. package/dist/collection/schemas/expected-outcome.js.map +1 -1
  39. package/dist/collection/schemas/test-case.js +6 -0
  40. package/dist/collection/schemas/test-case.js.map +1 -1
  41. package/dist/collection/types/expected-outcome.js.map +1 -1
  42. package/dist/collection/types/llm-test-runner.js.map +1 -1
  43. package/dist/collection/types/test-case.js.map +1 -1
  44. package/dist/components/app-chips.js +1 -1
  45. package/dist/components/app-select.js +1 -1
  46. package/dist/components/app-textarea.js +1 -1
  47. package/dist/components/chat-history.d.ts +11 -0
  48. package/dist/components/chat-history.js +2 -0
  49. package/dist/components/chat-history.js.map +1 -0
  50. package/dist/components/index.js +1 -1
  51. package/dist/components/llm-test-runner.js +1 -1
  52. package/dist/components/{p-CJBscebi.js → p-B87Lt3z4.js} +3 -3
  53. package/dist/components/p-B87Lt3z4.js.map +1 -0
  54. package/dist/components/p-Bx2jqguC.js +2 -0
  55. package/dist/components/p-Bx2jqguC.js.map +1 -0
  56. package/dist/components/p-D2qDAxFN.js +2 -0
  57. package/dist/components/p-D2qDAxFN.js.map +1 -0
  58. package/dist/components/{p-Dv7cB5FU.js → p-D4dHUFN9.js} +2 -2
  59. package/dist/components/{p-CE5-1jfZ.js → p-eN2dLrsr.js} +2 -2
  60. package/dist/esm/{app-chips_4.entry.js → app-chips_5.entry.js} +41 -7
  61. package/dist/esm/app-chips_5.entry.js.map +1 -0
  62. package/dist/esm/index.js +235 -44
  63. package/dist/esm/index.js.map +1 -1
  64. package/dist/esm/llm-testrunner.js +1 -1
  65. package/dist/esm/loader.js +1 -1
  66. package/dist/llm-testrunner/index.esm.js +2 -2
  67. package/dist/llm-testrunner/index.esm.js.map +1 -1
  68. package/dist/llm-testrunner/llm-testrunner.esm.js +1 -1
  69. package/dist/llm-testrunner/p-21202f12.entry.js +2 -0
  70. package/dist/llm-testrunner/p-21202f12.entry.js.map +1 -0
  71. package/dist/react/components.d.ts +6 -1
  72. package/dist/react/components.d.ts.map +1 -1
  73. package/dist/react/components.js +9 -0
  74. package/dist/types/components/llm-test-runner/llm-test-runner.d.ts +6 -0
  75. package/dist/types/components/llm-test-runner/test-cases/chat-history.d.ts +14 -0
  76. package/dist/types/components/llm-test-runner/test-cases/expected-outcome-renderer.d.ts +1 -0
  77. package/dist/types/components/llm-test-runner/test-cases/llm-test-case-row.d.ts +6 -0
  78. package/dist/types/components/llm-test-runner/test-cases/llm-test-cases.d.ts +3 -0
  79. package/dist/types/components.d.ts +55 -0
  80. package/dist/types/index.d.ts +1 -1
  81. package/dist/types/lib/import-export/test-suite-exporter.d.ts +4 -0
  82. package/dist/types/lib/test-cases/dynamic-expected-outcome-resolver.d.ts +7 -0
  83. package/dist/types/lib/test-cases/test-case-mutations.d.ts +9 -1
  84. package/dist/types/schemas/expected-outcome.d.ts +16 -1
  85. package/dist/types/schemas/test-case.d.ts +34 -2
  86. package/dist/types/types/expected-outcome.d.ts +1 -1
  87. package/dist/types/types/llm-test-runner.d.ts +3 -2
  88. package/dist/types/types/test-case.d.ts +1 -1
  89. package/package.json +1 -1
  90. package/dist/cjs/app-chips_4.cjs.entry.js.map +0 -1
  91. package/dist/components/p-BZrzx5jG.js +0 -2
  92. package/dist/components/p-BZrzx5jG.js.map +0 -1
  93. package/dist/components/p-CJBscebi.js.map +0 -1
  94. package/dist/esm/app-chips_4.entry.js.map +0 -1
  95. package/dist/llm-testrunner/p-2cc09217.entry.js +0 -2
  96. package/dist/llm-testrunner/p-2cc09217.entry.js.map +0 -1
  97. /package/dist/components/{p-Dv7cB5FU.js.map → p-D4dHUFN9.js.map} +0 -0
  98. /package/dist/components/{p-CE5-1jfZ.js.map → p-eN2dLrsr.js.map} +0 -0
@@ -1,2 +1,2 @@
1
- import{p as e,b as t}from"./p-DxzhGhec.js";export{s as setNonce}from"./p-DxzhGhec.js";import{g as a}from"./p-GQwFOmwJ.js";var r=()=>{const s=import.meta.url;const t={};if(s!==""){t.resourcesUrl=new URL(".",s).href}return e(t)};r().then((async e=>{await a();return t([["p-2cc09217",[[513,"llm-test-runner",{delayMs:[2,"delay-ms"],useSave:[4,"use-save"],usePromptEditor:[4,"use-prompt-editor"],initialTestCases:[16],defaultExpectedOutcomeSchema:[16],testCases:[32],isRunningAll:[32],error:[32],isExportingTestSuite:[32],isExportingTestResults:[32],isSaving:[32],resetSavingState:[64],getTestCases:[64]}],[513,"app-chips",{value:[16],config:[16]}],[513,"app-select",{value:[1],config:[16]}],[513,"app-textarea",{value:[1],config:[16]}]]]],e)}));
1
+ import{p as e,b as t}from"./p-DxzhGhec.js";export{s as setNonce}from"./p-DxzhGhec.js";import{g as a}from"./p-GQwFOmwJ.js";var r=()=>{const t=import.meta.url;const s={};if(t!==""){s.resourcesUrl=new URL(".",t).href}return e(s)};r().then((async e=>{await a();return t([["p-21202f12",[[513,"llm-test-runner",{delayMs:[2,"delay-ms"],useSave:[4,"use-save"],usePromptEditor:[4,"use-prompt-editor"],resolveExpectedOutcome:[16],initialTestCases:[16],defaultExpectedOutcomeSchema:[16],testCases:[32],isRunningAll:[32],error:[32],isExportingTestSuite:[32],isExportingTestResults:[32],isSaving:[32],resetSavingState:[64],getTestCases:[64]}],[513,"app-chips",{value:[16],config:[16]}],[513,"app-select",{value:[1],config:[16]}],[513,"app-textarea",{value:[1],config:[16]}],[513,"chat-history",{chatHistoryEnabled:[4,"chat-history-enabled"],chatHistoryValue:[1,"chat-history-value"]}]]]],e)}));
2
2
  //# sourceMappingURL=llm-testrunner.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{r as e,c as a,h as r}from"./p-DxzhGhec.js";export{LLMTestRunner as llm_test_runner}from"./index.esm.js";const t=()=>`.app-chips{margin-bottom:var(--spacing-4)}.app-chips__label{display:block;margin-bottom:var(--spacing-2);font-weight:var(--font-weight-medium);color:var(--foreground);font-size:var(--font-size-sm)}.app-chips__container{display:flex;flex-wrap:wrap;gap:var(--spacing-2);align-items:center}.app-chips__chip{display:inline-flex;align-items:center;gap:var(--spacing-2);padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);border-radius:var(--radius-md);background:var(--accent);border:var(--border-width) solid var(--border)}.app-chips__chip:not(:has(a)){background:var(--info);color:var(--info-foreground);border:none;border-radius:var(--radius-2xl)}.app-chips__link{color:var(--info);text-decoration:none;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-chips__link:hover{text-decoration:underline}.app-chips__remove{background:none;border:none;cursor:pointer;font-size:var(--font-size-xs);padding:0;width:var(--spacing-4);height:var(--spacing-4);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-full);color:var(--muted-foreground);opacity:var(--opacity-muted)}.app-chips__chip:not(:has(a)) .app-chips__remove{color:var(--info-foreground);opacity:var(--opacity-hover)}.app-chips__remove:hover{opacity:1;background:var(--muted)}.app-chips__chip:not(:has(a)) .app-chips__remove:hover{background:rgba(255, 255, 255, 0.2)}.app-chips__input{border:var(--border-width) solid var(--input);border-radius:var(--radius-md);padding:var(--spacing-2);font-size:var(--font-size-xs);outline:none;min-width:120px;background:var(--background);color:var(--foreground)}.app-chips__input:focus{border-color:var(--ring);box-shadow:0 0 0 2px rgba(59, 130, 246, 0.1)}`;const o=class{constructor(r){e(this,r);this.addChip=a(this,"addChip");this.removeChip=a(this,"removeChip")}value=[];config;addChip;removeChip;emitAddChip(e){this.addChip.emit({value:e})}emitRemoveChip(e){this.removeChip.emit({value:e})}hasDuplicateChip(e){const a=e.trim().toLowerCase();return this.value.some((e=>e.trim().toLowerCase()===a))}render(){const e=this.config;const a={placeholder:e.placeholder,required:e.required,disabled:e.disabled,readOnly:e.readOnly,id:e.name,name:e.name,autocomplete:e.autocomplete};return r("div",{key:"fb7d4d5444e9c9ac33c56aec88e3e10ed103c8be",class:"app-chips"},e.label&&r("label",{key:"2d0041b3a137fecddef2273eac3792b5e8de27ab",class:"app-chips__label",htmlFor:e.name},e.label),r("div",{key:"f73b1105e567b233626073e05b9da712689e7b12",class:"app-chips__container"},this.value.map((a=>r("span",{class:"app-chips__chip",key:a},e.type==="url"?r("a",{href:a,target:"_blank",rel:"noopener noreferrer",class:"app-chips__link"},a):a,r("button",{class:"app-chips__remove",type:"button",onClick:()=>this.emitRemoveChip(a)},"×")))),r("input",{key:"7676ff95531b34d10cbf9402e72a723e7e123e0e",class:"app-chips__input",type:e.type||"text",...a,onKeyDown:e=>{if(e.key==="Enter"){const a=e.target;const r=a.value.trim();if(!r)return;if(this.hasDuplicateChip(r)){a.value="";return}this.emitAddChip(r);a.value=""}}})))}};o.style=t();const i=()=>`.app-select{margin-bottom:var(--spacing-4)}.app-select__label{display:block;margin-bottom:var(--spacing-2);font-weight:var(--font-weight-medium);color:var(--foreground);font-size:var(--font-size-sm)}.app-select__select{border:var(--border-width) solid var(--input);border-radius:var(--radius-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);padding:var(--spacing-1) var(--spacing-2);outline:none;background:var(--background);width:145px;color:var(--foreground)}.app-select__select:focus{border-color:var(--ring);box-shadow:0 0 0 2px rgba(59, 130, 246, 0.1)}`;const s=class{constructor(r){e(this,r);this.valueChange=a(this,"valueChange")}value;config;valueChange;render(){const e=this.config;const a={id:e.name,name:e.name,disabled:e.disabled,required:e.required,readOnly:e.readOnly,placeholder:e.placeholder,autocomplete:e.autocomplete};return r("div",{key:"968f0fffe1eff976ac7e00f02db6fb84aa529de4",class:"app-select"},e.label&&r("label",{key:"dac02d2335754ff5d6ce6ba1df5777f8b019cfae",class:"app-select__label",htmlFor:e.name},e.label),r("div",{key:"c92698199479bbdde1cfd559d69fc97e54d2862a"},r("select",{key:"6e9b27b034d057921f52fbd12653c5ef1b6af1bc",...a,class:"app-select__select",onInput:a=>{const r=a.target.value;const t=e.optionList.find((e=>String(e)===r));this.valueChange.emit({value:t!==undefined?t:r})}},e.optionList?.map((e=>r("option",{value:String(e),key:String(e),selected:this.value===e},String(e)))))))}};s.style=i();const n=()=>`.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}`;const c=class{constructor(r){e(this,r);this.valueChange=a(this,"valueChange")}value;config;valueChange;handleChange=e=>{const a=e.target;this.valueChange.emit({value:a.value})};render(){const e=this.config;const a={placeholder:e.placeholder,required:e.required,disabled:e.disabled,readOnly:e.readOnly,rows:e.rows,id:e.name,name:e.name,autocomplete:e.autocomplete};return r("div",{key:"f0749b1f2badf8434272da9fb37b354b42ba988b",class:{"textarea-wrapper":true,"textarea-wrapper--read-only":!!e.readOnly}},e.label&&r("label",{key:"3448c838bcf9e962df005eae8fc313d216497c35",class:"textarea-label",htmlFor:e.name},e.label),r("textarea",{key:"b4ee67a24fa71b0fa042625f943b0e226a6d14b7",...a,class:"textarea-element",value:this.value,onInput:this.handleChange}),e.helpText&&r("p",{key:"fb6263c32e6cc5e36dbc77344c31487d63d51a1c",class:"help-text"},e.helpText))}};c.style=n();const d=()=>`.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}`;const h=`[\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]`;const p=class{constructor(r){e(this,r);this.chatHistoryChange=a(this,"chatHistoryChange")}chatHistoryEnabled=false;chatHistoryValue="";chatHistoryChange;emit(e){this.chatHistoryChange.emit(e)}onToggle=e=>{const a=e.target.checked;this.emit({enabled:a,value:this.chatHistoryValue})};onTextInput=e=>{const a=e.target.value;this.emit({enabled:this.chatHistoryEnabled,value:a})};render(){return r("div",{key:"f444a4b5bd9b48df151cad67b54bef54116d11b3",class:"chat-history"},r("div",{key:"7216d764fb905ac5e8e33209d9586525e59fa218",class:"chat-history__toggle-row"},r("label",{key:"d5d092c323b48543c96525d449bcb03dcaf5113b",class:"chat-history__switch"},r("input",{key:"5104ce460686434156454fc1dfd3685ba0e0968c",type:"checkbox",class:"chat-history__switch-input",checked:this.chatHistoryEnabled,onInput:this.onToggle}),r("span",{key:"fa2e51bce0d6ff2d3bf133383e1ce940521097b0",class:"chat-history__switch-ui","aria-hidden":"true"},r("span",{key:"e0d897ca166623ece09834b44b5baa12605cb9f3",class:"chat-history__switch-thumb"})),r("span",{key:"e769678fde5d670e634d7a8e905ef09ce936f440",class:"chat-history__switch-text"},"Chat history"))),this.chatHistoryEnabled?r("textarea",{class:"chat-history__textarea",value:this.chatHistoryValue,rows:8,placeholder:h,"aria-label":"Chat history",onInput:this.onTextInput}):null)}};p.style=d();export{o as app_chips,s as app_select,c as app_textarea,p as chat_history};
2
+ //# sourceMappingURL=p-21202f12.entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["appChipsCss","AppChips","value","config","addChip","removeChip","emitAddChip","val","this","emit","emitRemoveChip","hasDuplicateChip","normalized","trim","toLowerCase","some","chip","render","c","allowedAttrs","placeholder","required","disabled","readOnly","id","name","autocomplete","h","key","class","label","htmlFor","map","type","href","target","rel","onClick","onKeyDown","e","input","appSelectCss","AppSelect","valueChange","onInput","raw","matched","optionList","find","opt","String","undefined","option","selected","appTextareaCss","AppTextarea","handleChange","rows","helpText","chatHistoryCss","CHAT_HISTORY_PLACEHOLDER","ChatHistory","chatHistoryEnabled","chatHistoryValue","chatHistoryChange","detail","onToggle","checked","enabled","onTextInput"],"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"],"mappings":"+GAAA,MAAMA,EAAc,IAAM,ouD,MCQbC,EAAQ,M,6FACXC,MAAkB,GAClBC,OAECC,QAEAC,WAED,WAAAC,CAAYC,GAClBC,KAAKJ,QAAQK,KAAK,CAChBP,MAAOK,G,CAIH,cAAAG,CAAeR,GACrBM,KAAKH,WAAWI,KAAK,CACnBP,S,CAII,gBAAAS,CAAiBT,GACvB,MAAMU,EAAaV,EAAMW,OAAOC,cAChC,OAAON,KAAKN,MAAMa,MAAKC,GAAQA,EAAKH,OAAOC,gBAAkBF,G,CAG/D,MAAAK,GACE,MAAMC,EAAIV,KAAKL,OAEf,MAAMgB,EAAe,CACnBC,YAAaF,EAAEE,YACfC,SAAUH,EAAEG,SACZC,SAAUJ,EAAEI,SACZC,SAAUL,EAAEK,SACZC,GAAIN,EAAEO,KACNA,KAAMP,EAAEO,KACRC,aAAcR,EAAEQ,cAGlB,OACEC,EAAA,OAAAC,IAAA,2CAAKC,MAAM,aACRX,EAAEY,OACDH,EAAA,SAAAC,IAAA,2CAAOC,MAAM,mBAAmBE,QAASb,EAAEO,MACxCP,EAAEY,OAIPH,EAAA,OAAAC,IAAA,2CAAKC,MAAM,wBACRrB,KAAKN,MAAM8B,KAAKhB,GACfW,EAAA,QAAME,MAAM,kBAAkBD,IAAKZ,GAChCE,EAAEe,OAAS,MACVN,EAAA,KACEO,KAAMlB,EACNmB,OAAO,SACPC,IAAI,sBACJP,MAAM,mBAELb,GACC,EAKNW,EAAA,UACEE,MAAM,oBACNI,KAAK,SACLI,QAAS,IAAM7B,KAAKE,eAAeM,IAAK,QAO9CW,EAAA,SAAAC,IAAA,2CACEC,MAAM,mBACNI,KAAMf,EAAEe,MAAQ,UACZd,EACJmB,UAAYC,IACV,GAAIA,EAAEX,MAAQ,QAAS,CACrB,MAAMY,EAAQD,EAAEJ,OAChB,MAAM5B,EAAMiC,EAAMtC,MAAMW,OACxB,IAAKN,EAAK,OACV,GAAIC,KAAKG,iBAAiBJ,GAAM,CAC9BiC,EAAMtC,MAAQ,GACd,M,CAGFM,KAAKF,YAAYC,GACjBiC,EAAMtC,MAAQ,E,qBC/F9B,MAAMuC,EAAe,IAAM,ukB,MCQdC,EAAS,M,gEACZxC,MACAC,OACCwC,YAET,MAAA1B,GACE,MAAMC,EAAIV,KAAKL,OACf,MAAMgB,EAAe,CACnBK,GAAIN,EAAEO,KACNA,KAAMP,EAAEO,KACRH,SAAUJ,EAAEI,SACZD,SAAUH,EAAEG,SACZE,SAAUL,EAAEK,SACZH,YAAaF,EAAEE,YACfM,aAAcR,EAAEQ,cAElB,OACEC,EAAA,OAAAC,IAAA,2CAAKC,MAAM,cACRX,EAAEY,OACDH,EAAA,SAAAC,IAAA,2CAAOC,MAAM,oBAAoBE,QAASb,EAAEO,MACzCP,EAAEY,OAIPH,EAAA,OAAAC,IAAA,4CACED,EAAA,UAAAC,IAAA,8CACMT,EACJU,MAAM,qBACNe,QAAUL,IACR,MAAMM,EAAON,EAAEJ,OAA6BjC,MAC5C,MAAM4C,EAAU5B,EAAE6B,WAAWC,MAAKC,GAAOC,OAAOD,KAASJ,IACzDrC,KAAKmC,YAAYlC,KAAK,CACpBP,MAAO4C,IAAYK,UAAYL,EAAUD,GACzC,GAGH3B,EAAE6B,YAAYf,KAAIoB,GACjBzB,EAAA,UACEzB,MAAOgD,OAAOE,GACdxB,IAAKsB,OAAOE,GACZC,SAAU7C,KAAKN,QAAUkD,GAExBF,OAAOE,Q,eClDxB,MAAME,EAAiB,IAAM,s/B,MCQhBC,EAAW,M,gEACdrD,MACAC,OAECwC,YAEDa,aAAgBjB,IACtB,MAAMJ,EAASI,EAAEJ,OAEjB3B,KAAKmC,YAAYlC,KAAK,CACpBP,MAAOiC,EAAOjC,OACd,EAGJ,MAAAe,GACE,MAAMC,EAAIV,KAAKL,OAEf,MAAMgB,EAAe,CACnBC,YAAaF,EAAEE,YACfC,SAAUH,EAAEG,SACZC,SAAUJ,EAAEI,SACZC,SAAUL,EAAEK,SACZkC,KAAMvC,EAAEuC,KACRjC,GAAIN,EAAEO,KACNA,KAAMP,EAAEO,KACRC,aAAcR,EAAEQ,cAGlB,OACEC,EAAA,OAAAC,IAAA,2CACEC,MAAO,CACL,mBAAoB,KACpB,gCAAiCX,EAAEK,WAGpCL,EAAEY,OACDH,EAAA,SAAAC,IAAA,2CAAOC,MAAM,iBAAiBE,QAASb,EAAEO,MACtCP,EAAEY,OAIPH,EAAA,YAAAC,IAAA,8CACMT,EACJU,MAAM,mBACN3B,MAAOM,KAAKN,MACZ0C,QAASpC,KAAKgD,eAGftC,EAAEwC,UAAY/B,EAAA,KAAAC,IAAA,2CAAGC,MAAM,aAAaX,EAAEwC,U,eCxD/C,MAAMC,EAAiB,IAAM,2zDCE7B,MAAMC,EAA2B,4J,MAepBC,EAAW,M,4EACdC,mBAAqB,MACrBC,iBAAmB,GAG3BC,kBAEQ,IAAAvD,CAAKwD,GACXzD,KAAKwD,kBAAkBvD,KAAKwD,E,CAGtBC,SAAY3B,IAClB,MAAM4B,EAAW5B,EAAEJ,OAA4BgC,QAC/C3D,KAAKC,KAAK,CAAE2D,QAASD,EAASjE,MAAOM,KAAKuD,kBAAmB,EAGvDM,YAAe9B,IACrB,MAAMrC,EAASqC,EAAEJ,OAA+BjC,MAChDM,KAAKC,KAAK,CAAE2D,QAAS5D,KAAKsD,mBAAoB5D,SAAQ,EAGxD,MAAAe,GACE,OACEU,EAAA,OAAAC,IAAA,2CAAKC,MAAM,gBACTF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,4BACTF,EAAA,SAAAC,IAAA,2CAAOC,MAAM,wBACXF,EAAA,SAAAC,IAAA,2CACEK,KAAK,WACLJ,MAAM,6BACNsC,QAAS3D,KAAKsD,mBACdlB,QAASpC,KAAK0D,WAEhBvC,EAAA,QAAAC,IAAA,2CAAMC,MAAM,0BAAyB,cAAa,QAChDF,EAAA,QAAAC,IAAA,2CAAMC,MAAM,gCAEdF,EAAA,QAAAC,IAAA,2CAAMC,MAAM,6BAA2B,kBAG1CrB,KAAKsD,mBACJnC,EAAA,YACEE,MAAM,yBACN3B,MAAOM,KAAKuD,iBACZN,KAAM,EACNrC,YAAawC,EAAwB,aAC1B,eACXhB,QAASpC,KAAK6D,cAEd,K","ignoreList":[]}
@@ -3,10 +3,11 @@
3
3
  * Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
4
4
  */
5
5
  import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
6
- import { type AppChipsCustomEvent, type AppSelectCustomEvent, type AppTextareaCustomEvent, type LLMRequestPayload, type LlmTestRunnerCustomEvent, type SavePayload } from "llm-testrunner-components";
6
+ import { type AppChipsCustomEvent, type AppSelectCustomEvent, type AppTextareaCustomEvent, type ChatHistoryChangeDetail, type ChatHistoryCustomEvent, type LLMRequestPayload, type LlmTestRunnerCustomEvent, type SavePayload } from "llm-testrunner-components";
7
7
  import { AppChips as AppChipsElement } from "llm-testrunner-components/./dist/components/app-chips.js";
8
8
  import { AppSelect as AppSelectElement } from "llm-testrunner-components/./dist/components/app-select.js";
9
9
  import { AppTextarea as AppTextareaElement } from "llm-testrunner-components/./dist/components/app-textarea.js";
10
+ import { ChatHistory as ChatHistoryElement } from "llm-testrunner-components/./dist/components/chat-history.js";
10
11
  import { LlmTestRunner as LlmTestRunnerElement } from "llm-testrunner-components/./dist/components/llm-test-runner.js";
11
12
  export type AppChipsEvents = {
12
13
  onAddChip: EventName<AppChipsCustomEvent<{
@@ -29,6 +30,10 @@ export type AppTextareaEvents = {
29
30
  }>>;
30
31
  };
31
32
  export declare const AppTextarea: StencilReactComponent<AppTextareaElement, AppTextareaEvents>;
33
+ export type ChatHistoryEvents = {
34
+ onChatHistoryChange: EventName<ChatHistoryCustomEvent<ChatHistoryChangeDetail>>;
35
+ };
36
+ export declare const ChatHistory: StencilReactComponent<ChatHistoryElement, ChatHistoryEvents>;
32
37
  export type LlmTestRunnerEvents = {
33
38
  onLlmRequest: EventName<LlmTestRunnerCustomEvent<LLMRequestPayload>>;
34
39
  onSave: EventName<LlmTestRunnerCustomEvent<SavePayload>>;
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../generated/react/components.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7F,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACtM,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAyC,MAAM,0DAA0D,CAAC;AAC9I,OAAO,EAAE,SAAS,IAAI,gBAAgB,EAA0C,MAAM,2DAA2D,CAAC;AAClJ,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAA4C,MAAM,6DAA6D,CAAC;AAC1J,OAAO,EAAE,aAAa,IAAI,oBAAoB,EAA8C,MAAM,gEAAgE,CAAC;AAGnK,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,SAAS,CAAC,mBAAmB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC7D,YAAY,EAAE,SAAS,CAAC,mBAAmB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAClE,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,qBAAqB,CAAC,eAAe,EAAE,cAAc,CAU1E,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG;IAAE,aAAa,EAAE,SAAS,CAAC,oBAAoB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAAE,CAAC;AAEpG,eAAO,MAAM,SAAS,EAAE,qBAAqB,CAAC,gBAAgB,EAAE,eAAe,CAO7E,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAAE,aAAa,EAAE,SAAS,CAAC,sBAAsB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAAE,CAAC;AAExG,eAAO,MAAM,WAAW,EAAE,qBAAqB,CAAC,kBAAkB,EAAE,iBAAiB,CAOnF,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAC9B,YAAY,EAAE,SAAS,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,SAAS,CAAC,wBAAwB,CAAC,WAAW,CAAC,CAAC,CAAA;CAC3D,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,qBAAqB,CAAC,oBAAoB,EAAE,mBAAmB,CAUzF,CAAC"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../generated/react/components.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7F,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,KAAK,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACjQ,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAyC,MAAM,0DAA0D,CAAC;AAC9I,OAAO,EAAE,SAAS,IAAI,gBAAgB,EAA0C,MAAM,2DAA2D,CAAC;AAClJ,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAA4C,MAAM,6DAA6D,CAAC;AAC1J,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAA4C,MAAM,6DAA6D,CAAC;AAC1J,OAAO,EAAE,aAAa,IAAI,oBAAoB,EAA8C,MAAM,gEAAgE,CAAC;AAGnK,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,SAAS,CAAC,mBAAmB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC7D,YAAY,EAAE,SAAS,CAAC,mBAAmB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAClE,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,qBAAqB,CAAC,eAAe,EAAE,cAAc,CAU1E,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG;IAAE,aAAa,EAAE,SAAS,CAAC,oBAAoB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAAE,CAAC;AAEpG,eAAO,MAAM,SAAS,EAAE,qBAAqB,CAAC,gBAAgB,EAAE,eAAe,CAO7E,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAAE,aAAa,EAAE,SAAS,CAAC,sBAAsB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAAE,CAAC;AAExG,eAAO,MAAM,WAAW,EAAE,qBAAqB,CAAC,kBAAkB,EAAE,iBAAiB,CAOnF,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAAE,mBAAmB,EAAE,SAAS,CAAC,sBAAsB,CAAC,uBAAuB,CAAC,CAAC,CAAA;CAAE,CAAC;AAEpH,eAAO,MAAM,WAAW,EAAE,qBAAqB,CAAC,kBAAkB,EAAE,iBAAiB,CAOnF,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAC9B,YAAY,EAAE,SAAS,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,SAAS,CAAC,wBAAwB,CAAC,WAAW,CAAC,CAAC,CAAA;CAC3D,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,qBAAqB,CAAC,oBAAoB,EAAE,mBAAmB,CAUzF,CAAC"}
@@ -3,6 +3,7 @@ import { createComponent } from '@stencil/react-output-target/runtime';
3
3
  import { AppChips as AppChipsElement, defineCustomElement as defineAppChips } from "llm-testrunner-components/./dist/components/app-chips.js";
4
4
  import { AppSelect as AppSelectElement, defineCustomElement as defineAppSelect } from "llm-testrunner-components/./dist/components/app-select.js";
5
5
  import { AppTextarea as AppTextareaElement, defineCustomElement as defineAppTextarea } from "llm-testrunner-components/./dist/components/app-textarea.js";
6
+ import { ChatHistory as ChatHistoryElement, defineCustomElement as defineChatHistory } from "llm-testrunner-components/./dist/components/chat-history.js";
6
7
  import { LlmTestRunner as LlmTestRunnerElement, defineCustomElement as defineLlmTestRunner } from "llm-testrunner-components/./dist/components/llm-test-runner.js";
7
8
  import React from 'react';
8
9
  export const AppChips = /*@__PURE__*/ createComponent({
@@ -32,6 +33,14 @@ export const AppTextarea = /*@__PURE__*/ createComponent({
32
33
  events: { onValueChange: 'valueChange' },
33
34
  defineCustomElement: defineAppTextarea
34
35
  });
36
+ export const ChatHistory = /*@__PURE__*/ createComponent({
37
+ tagName: 'chat-history',
38
+ elementClass: ChatHistoryElement,
39
+ // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
40
+ react: React,
41
+ events: { onChatHistoryChange: 'chatHistoryChange' },
42
+ defineCustomElement: defineChatHistory
43
+ });
35
44
  export const LlmTestRunner = /*@__PURE__*/ createComponent({
36
45
  tagName: 'llm-test-runner',
37
46
  elementClass: LlmTestRunnerElement,
@@ -1,11 +1,13 @@
1
1
  import { EventEmitter } from '../../stencil-public-runtime';
2
2
  import { ExpectedOutcomeSchema, TestCase, LLMRequestPayload, SavePayload } from '../../types/llm-test-runner';
3
+ import { type ExpectedOutcomeResolver } from '../../lib/test-cases/dynamic-expected-outcome-resolver';
3
4
  export declare class LLMTestRunner {
4
5
  llmRequest: EventEmitter<LLMRequestPayload>;
5
6
  save: EventEmitter<SavePayload>;
6
7
  delayMs?: number;
7
8
  useSave?: boolean;
8
9
  usePromptEditor?: boolean;
10
+ resolveExpectedOutcome?: ExpectedOutcomeResolver;
9
11
  initialTestCases?: TestCase[];
10
12
  defaultExpectedOutcomeSchema?: ExpectedOutcomeSchema;
11
13
  testCases: TestCase[];
@@ -22,8 +24,12 @@ export declare class LLMTestRunner {
22
24
  resetSavingState(): Promise<void>;
23
25
  getTestCases(): Promise<TestCase[]>;
24
26
  private handleTestCaseChange;
27
+ private handleChatHistoryChange;
25
28
  private addNewTestCase;
26
29
  private updateTestCase;
30
+ private requestLlmText;
31
+ private throwError;
32
+ private addErrorMessage;
27
33
  private runSingleTest;
28
34
  private deleteTestCase;
29
35
  private handleExpectedOutcomeChange;
@@ -0,0 +1,14 @@
1
+ import { EventEmitter } from '../../../stencil-public-runtime';
2
+ export type ChatHistoryChangeDetail = {
3
+ enabled: boolean;
4
+ value: string;
5
+ };
6
+ export declare class ChatHistory {
7
+ chatHistoryEnabled: boolean;
8
+ chatHistoryValue: string;
9
+ chatHistoryChange: EventEmitter<ChatHistoryChangeDetail>;
10
+ private emit;
11
+ private onToggle;
12
+ private onTextInput;
13
+ render(): any;
14
+ }
@@ -7,6 +7,7 @@ export type ExpectedOutcomeChangeDetail = {
7
7
  interface ExpectedOutcomeRendererProps {
8
8
  testCaseId: string;
9
9
  fields: ExpectedOutcomeField[];
10
+ dynamicResolutionSupported?: boolean;
10
11
  onExpectedOutcomeChange: (e: CustomEvent<ExpectedOutcomeChangeDetail>) => void;
11
12
  }
12
13
  export declare const ExpectedOutcomeRenderer: FunctionalComponent<ExpectedOutcomeRendererProps>;
@@ -1,8 +1,13 @@
1
1
  import { FunctionalComponent } from '../../../stencil-public-runtime';
2
2
  import { TestCase } from '../../../types/llm-test-runner';
3
3
  import { ExpectedOutcomeChangeDetail } from './expected-outcome-renderer';
4
+ import type { ChatHistoryChangeDetail } from './chat-history';
5
+ export type ChatHistoryRowChangeDetail = {
6
+ testCaseId: string;
7
+ } & ChatHistoryChangeDetail;
4
8
  export interface LLMTestCaseRowProps {
5
9
  testCase: TestCase;
10
+ dynamicResolutionSupported?: boolean;
6
11
  onRun: (testCase: TestCase) => void;
7
12
  onDelete: (id: string) => void;
8
13
  handleTestCaseChange: (e: CustomEvent<{
@@ -11,5 +16,6 @@ export interface LLMTestCaseRowProps {
11
16
  value: string;
12
17
  }>) => void;
13
18
  onExpectedOutcomeChange: (e: CustomEvent<ExpectedOutcomeChangeDetail>) => void;
19
+ onChatHistoryChange: (e: CustomEvent<ChatHistoryRowChangeDetail>) => void;
14
20
  }
15
21
  export declare const LLMTestCaseRow: FunctionalComponent<LLMTestCaseRowProps>;
@@ -1,8 +1,10 @@
1
1
  import { FunctionalComponent } from '../../../stencil-public-runtime';
2
2
  import { TestCase } from '../../../types/llm-test-runner';
3
+ import { ChatHistoryRowChangeDetail } from './llm-test-case-row';
3
4
  import { ExpectedOutcomeChangeDetail } from './expected-outcome-renderer';
4
5
  export interface LLMTestCasesProps {
5
6
  testCases: TestCase[];
7
+ dynamicResolutionSupported?: boolean;
6
8
  onRun: (testCase: TestCase) => void;
7
9
  onDelete: (id: string) => void;
8
10
  onAddTestCase: () => void;
@@ -12,5 +14,6 @@ export interface LLMTestCasesProps {
12
14
  value: string;
13
15
  }>) => void;
14
16
  onExpectedOutcomeChange: (e: CustomEvent<ExpectedOutcomeChangeDetail>) => void;
17
+ onChatHistoryChange: (e: CustomEvent<ChatHistoryRowChangeDetail>) => void;
15
18
  }
16
19
  export declare const LLMTestCases: FunctionalComponent<LLMTestCasesProps>;
@@ -6,9 +6,13 @@
6
6
  */
7
7
  import { HTMLStencilElement, JSXBase } from "./stencil-public-runtime";
8
8
  import { ChipsConfig, SelectConfig, TextAreaConfig } from "./lib/form/schema";
9
+ import { ChatHistoryChangeDetail } from "./components/llm-test-runner/test-cases/chat-history";
10
+ import { ExpectedOutcomeResolver } from "./lib/test-cases/dynamic-expected-outcome-resolver";
9
11
  import { ExpectedOutcomeSchema, LLMRequestPayload, SavePayload, TestCase } from "./types/llm-test-runner";
10
12
  import { EvaluationResult } from "./lib/evaluation/types";
11
13
  export { ChipsConfig, SelectConfig, TextAreaConfig } from "./lib/form/schema";
14
+ export { ChatHistoryChangeDetail } from "./components/llm-test-runner/test-cases/chat-history";
15
+ export { ExpectedOutcomeResolver } from "./lib/test-cases/dynamic-expected-outcome-resolver";
12
16
  export { ExpectedOutcomeSchema, LLMRequestPayload, SavePayload, TestCase } from "./types/llm-test-runner";
13
17
  export { EvaluationResult } from "./lib/evaluation/types";
14
18
  export namespace Components {
@@ -27,6 +31,16 @@ export namespace Components {
27
31
  "config": TextAreaConfig;
28
32
  "value": string;
29
33
  }
34
+ interface ChatHistory {
35
+ /**
36
+ * @default false
37
+ */
38
+ "chatHistoryEnabled": boolean;
39
+ /**
40
+ * @default ''
41
+ */
42
+ "chatHistoryValue": string;
43
+ }
30
44
  interface LlmTestRunner {
31
45
  "defaultExpectedOutcomeSchema"?: ExpectedOutcomeSchema;
32
46
  /**
@@ -36,6 +50,7 @@ export namespace Components {
36
50
  "getTestCases": () => Promise<TestCase[]>;
37
51
  "initialTestCases"?: TestCase[];
38
52
  "resetSavingState": () => Promise<void>;
53
+ "resolveExpectedOutcome"?: ExpectedOutcomeResolver;
39
54
  /**
40
55
  * @default false
41
56
  */
@@ -58,6 +73,10 @@ export interface AppTextareaCustomEvent<T> extends CustomEvent<T> {
58
73
  detail: T;
59
74
  target: HTMLAppTextareaElement;
60
75
  }
76
+ export interface ChatHistoryCustomEvent<T> extends CustomEvent<T> {
77
+ detail: T;
78
+ target: HTMLChatHistoryElement;
79
+ }
61
80
  export interface LlmTestRunnerCustomEvent<T> extends CustomEvent<T> {
62
81
  detail: T;
63
82
  target: HTMLLlmTestRunnerElement;
@@ -115,6 +134,23 @@ declare global {
115
134
  prototype: HTMLAppTextareaElement;
116
135
  new (): HTMLAppTextareaElement;
117
136
  };
137
+ interface HTMLChatHistoryElementEventMap {
138
+ "chatHistoryChange": ChatHistoryChangeDetail;
139
+ }
140
+ interface HTMLChatHistoryElement extends Components.ChatHistory, HTMLStencilElement {
141
+ addEventListener<K extends keyof HTMLChatHistoryElementEventMap>(type: K, listener: (this: HTMLChatHistoryElement, ev: ChatHistoryCustomEvent<HTMLChatHistoryElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
142
+ addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
143
+ addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
144
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
145
+ removeEventListener<K extends keyof HTMLChatHistoryElementEventMap>(type: K, listener: (this: HTMLChatHistoryElement, ev: ChatHistoryCustomEvent<HTMLChatHistoryElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
146
+ removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
147
+ removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
148
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
149
+ }
150
+ var HTMLChatHistoryElement: {
151
+ prototype: HTMLChatHistoryElement;
152
+ new (): HTMLChatHistoryElement;
153
+ };
118
154
  interface HTMLLlmTestRunnerElementEventMap {
119
155
  "llmRequest": LLMRequestPayload;
120
156
  "save": SavePayload;
@@ -137,6 +173,7 @@ declare global {
137
173
  "app-chips": HTMLAppChipsElement;
138
174
  "app-select": HTMLAppSelectElement;
139
175
  "app-textarea": HTMLAppTextareaElement;
176
+ "chat-history": HTMLChatHistoryElement;
140
177
  "llm-test-runner": HTMLLlmTestRunnerElement;
141
178
  }
142
179
  }
@@ -160,6 +197,17 @@ declare namespace LocalJSX {
160
197
  "onValueChange"?: (event: AppTextareaCustomEvent<{ value: string }>) => void;
161
198
  "value"?: string;
162
199
  }
200
+ interface ChatHistory {
201
+ /**
202
+ * @default false
203
+ */
204
+ "chatHistoryEnabled"?: boolean;
205
+ /**
206
+ * @default ''
207
+ */
208
+ "chatHistoryValue"?: string;
209
+ "onChatHistoryChange"?: (event: ChatHistoryCustomEvent<ChatHistoryChangeDetail>) => void;
210
+ }
163
211
  interface LlmTestRunner {
164
212
  "defaultExpectedOutcomeSchema"?: ExpectedOutcomeSchema;
165
213
  /**
@@ -169,6 +217,7 @@ declare namespace LocalJSX {
169
217
  "initialTestCases"?: TestCase[];
170
218
  "onLlmRequest"?: (event: LlmTestRunnerCustomEvent<LLMRequestPayload>) => void;
171
219
  "onSave"?: (event: LlmTestRunnerCustomEvent<SavePayload>) => void;
220
+ "resolveExpectedOutcome"?: ExpectedOutcomeResolver;
172
221
  /**
173
222
  * @default false
174
223
  */
@@ -185,6 +234,10 @@ declare namespace LocalJSX {
185
234
  interface AppTextareaAttributes {
186
235
  "value": string;
187
236
  }
237
+ interface ChatHistoryAttributes {
238
+ "chatHistoryEnabled": boolean;
239
+ "chatHistoryValue": string;
240
+ }
188
241
  interface LlmTestRunnerAttributes {
189
242
  "delayMs": number;
190
243
  "useSave": boolean;
@@ -195,6 +248,7 @@ declare namespace LocalJSX {
195
248
  "app-chips": AppChips;
196
249
  "app-select": Omit<AppSelect, keyof AppSelectAttributes> & { [K in keyof AppSelect & keyof AppSelectAttributes]?: AppSelect[K] } & { [K in keyof AppSelect & keyof AppSelectAttributes as `attr:${K}`]?: AppSelectAttributes[K] } & { [K in keyof AppSelect & keyof AppSelectAttributes as `prop:${K}`]?: AppSelect[K] };
197
250
  "app-textarea": Omit<AppTextarea, keyof AppTextareaAttributes> & { [K in keyof AppTextarea & keyof AppTextareaAttributes]?: AppTextarea[K] } & { [K in keyof AppTextarea & keyof AppTextareaAttributes as `attr:${K}`]?: AppTextareaAttributes[K] } & { [K in keyof AppTextarea & keyof AppTextareaAttributes as `prop:${K}`]?: AppTextarea[K] };
251
+ "chat-history": Omit<ChatHistory, keyof ChatHistoryAttributes> & { [K in keyof ChatHistory & keyof ChatHistoryAttributes]?: ChatHistory[K] } & { [K in keyof ChatHistory & keyof ChatHistoryAttributes as `attr:${K}`]?: ChatHistoryAttributes[K] } & { [K in keyof ChatHistory & keyof ChatHistoryAttributes as `prop:${K}`]?: ChatHistory[K] };
198
252
  "llm-test-runner": Omit<LlmTestRunner, keyof LlmTestRunnerAttributes> & { [K in keyof LlmTestRunner & keyof LlmTestRunnerAttributes]?: LlmTestRunner[K] } & { [K in keyof LlmTestRunner & keyof LlmTestRunnerAttributes as `attr:${K}`]?: LlmTestRunnerAttributes[K] } & { [K in keyof LlmTestRunner & keyof LlmTestRunnerAttributes as `prop:${K}`]?: LlmTestRunner[K] };
199
253
  }
200
254
  }
@@ -205,6 +259,7 @@ declare module "@stencil/core" {
205
259
  "app-chips": LocalJSX.IntrinsicElements["app-chips"] & JSXBase.HTMLAttributes<HTMLAppChipsElement>;
206
260
  "app-select": LocalJSX.IntrinsicElements["app-select"] & JSXBase.HTMLAttributes<HTMLAppSelectElement>;
207
261
  "app-textarea": LocalJSX.IntrinsicElements["app-textarea"] & JSXBase.HTMLAttributes<HTMLAppTextareaElement>;
262
+ "chat-history": LocalJSX.IntrinsicElements["chat-history"] & JSXBase.HTMLAttributes<HTMLChatHistoryElement>;
208
263
  "llm-test-runner": LocalJSX.IntrinsicElements["llm-test-runner"] & JSXBase.HTMLAttributes<HTMLLlmTestRunnerElement>;
209
264
  }
210
265
  }
@@ -1,3 +1,3 @@
1
1
  export { LLMTestRunner } from './components/llm-test-runner/llm-test-runner';
2
- export type { TestCase, LLMRequestPayload } from './types/llm-test-runner';
2
+ export type { TestCase, TestCaseChatHistory, LLMRequestPayload, } from './types/llm-test-runner';
3
3
  export type * from './components.d.ts';
@@ -3,6 +3,10 @@ export interface TestSuiteExportData {
3
3
  id: string;
4
4
  question: string;
5
5
  expectedOutcome: ExpectedOutcomeField[];
6
+ chatHistory: {
7
+ enabled: boolean;
8
+ value: string;
9
+ };
6
10
  }
7
11
  /**
8
12
  * Formats test cases as a JSON string suitable for saving as a test suite
@@ -0,0 +1,7 @@
1
+ import { TestCase } from '../../types/llm-test-runner';
2
+ export type ExpectedOutcomeResolver = (resolutionQuery: string, context: {
3
+ testCase: TestCase;
4
+ fieldIndex: number;
5
+ }) => Promise<string>;
6
+ export declare const MISSING_RESOLVER_MESSAGE = "resolveExpectedOutcome is required when a test case has dynamic expected outcomes.";
7
+ export declare function resolveDynamicExpectedOutcomes(testCase: TestCase, resolver?: ExpectedOutcomeResolver): Promise<TestCase>;
@@ -1,4 +1,4 @@
1
- import { TestCase } from '../../types/llm-test-runner';
1
+ import { TestCase, type ExpectedOutcomeMode } from '../../types/llm-test-runner';
2
2
  import { EvaluationApproach } from '../evaluation/constants';
3
3
  export type ExpectedOutcomeChange = {
4
4
  index: number;
@@ -16,6 +16,14 @@ export type ExpectedOutcomeChange = {
16
16
  index: number;
17
17
  operation: 'set-evaluation-approach';
18
18
  value: EvaluationApproach;
19
+ } | {
20
+ index: number;
21
+ operation: 'set-outcome-mode';
22
+ value: ExpectedOutcomeMode;
23
+ } | {
24
+ index: number;
25
+ operation: 'set-resolution-query';
26
+ value: string;
19
27
  };
20
28
  export declare function applyExpectedOutcomeChange(testCase: TestCase, change: ExpectedOutcomeChange): TestCase;
21
29
  /**
@@ -1,5 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { EvaluationApproach } from '../lib/evaluation/constants';
3
+ export declare const expectedOutcomeModeSchema: z.ZodEnum<{
4
+ static: "static";
5
+ dynamic: "dynamic";
6
+ }>;
7
+ export type ExpectedOutcomeMode = z.infer<typeof expectedOutcomeModeSchema>;
3
8
  declare const defaultExpectedOutcomeBaseSchema: z.ZodObject<{
4
9
  label: z.ZodString;
5
10
  placeholder: z.ZodOptional<z.ZodString>;
@@ -93,6 +98,11 @@ export declare const expectedOutcomeFieldSchema: z.ZodDiscriminatedUnion<[z.ZodO
93
98
  threshold: z.ZodOptional<z.ZodNumber>;
94
99
  }, z.core.$strip>>;
95
100
  value: z.ZodString;
101
+ outcomeMode: z.ZodDefault<z.ZodEnum<{
102
+ static: "static";
103
+ dynamic: "dynamic";
104
+ }>>;
105
+ resolutionQuery: z.ZodOptional<z.ZodString>;
96
106
  }, z.core.$strip>, z.ZodObject<{
97
107
  label: z.ZodString;
98
108
  placeholder: z.ZodOptional<z.ZodString>;
@@ -132,6 +142,11 @@ export declare const expectedOutcomeArraySchema: z.ZodArray<z.ZodDiscriminatedUn
132
142
  threshold: z.ZodOptional<z.ZodNumber>;
133
143
  }, z.core.$strip>>;
134
144
  value: z.ZodString;
145
+ outcomeMode: z.ZodDefault<z.ZodEnum<{
146
+ static: "static";
147
+ dynamic: "dynamic";
148
+ }>>;
149
+ resolutionQuery: z.ZodOptional<z.ZodString>;
135
150
  }, z.core.$strip>, z.ZodObject<{
136
151
  label: z.ZodString;
137
152
  placeholder: z.ZodOptional<z.ZodString>;
@@ -154,7 +169,7 @@ export declare const expectedOutcomeArraySchema: z.ZodArray<z.ZodDiscriminatedUn
154
169
  }, z.core.$strip>], "type">>;
155
170
  export type ExpectedOutcomeSchemaField = z.infer<typeof expectedOutcomeSchemaFieldSchema>;
156
171
  export type ExpectedOutcomeSchema = z.infer<typeof expectedOutcomeSchemaSchema>;
157
- export type ExpectedOutcomeField = z.infer<typeof expectedOutcomeFieldSchema>;
172
+ export type ExpectedOutcomeField = z.input<typeof expectedOutcomeFieldSchema>;
158
173
  export type ExpectedOutcomeFieldType = ExpectedOutcomeField['type'];
159
174
  export type ExpectedOutcomeBase = z.infer<typeof defaultExpectedOutcomeBaseSchema>;
160
175
  export type TextExpectedOutcomeSchemaField = Extract<ExpectedOutcomeSchemaField, {
@@ -1,5 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import type { EvaluationResult } from '../lib/evaluation/types';
3
+ export declare const testCaseChatHistorySchema: z.ZodObject<{
4
+ enabled: z.ZodBoolean;
5
+ value: z.ZodString;
6
+ }, z.core.$strip>;
3
7
  export declare const testCaseInputSchema: z.ZodObject<{
4
8
  id: z.ZodString;
5
9
  question: z.ZodString;
@@ -22,6 +26,11 @@ export declare const testCaseInputSchema: z.ZodObject<{
22
26
  threshold: z.ZodOptional<z.ZodNumber>;
23
27
  }, z.core.$strip>>;
24
28
  value: z.ZodString;
29
+ outcomeMode: z.ZodDefault<z.ZodEnum<{
30
+ static: "static";
31
+ dynamic: "dynamic";
32
+ }>>;
33
+ resolutionQuery: z.ZodOptional<z.ZodString>;
25
34
  }, z.core.$strip>, z.ZodObject<{
26
35
  label: z.ZodString;
27
36
  placeholder: z.ZodOptional<z.ZodString>;
@@ -42,6 +51,10 @@ export declare const testCaseInputSchema: z.ZodObject<{
42
51
  }, z.core.$strip>>;
43
52
  value: z.ZodString;
44
53
  }, z.core.$strip>], "type">>;
54
+ chatHistory: z.ZodOptional<z.ZodObject<{
55
+ enabled: z.ZodBoolean;
56
+ value: z.ZodString;
57
+ }, z.core.$strip>>;
45
58
  }, z.core.$strip>;
46
59
  export declare const testCaseInputArraySchema: z.ZodArray<z.ZodObject<{
47
60
  id: z.ZodString;
@@ -65,6 +78,11 @@ export declare const testCaseInputArraySchema: z.ZodArray<z.ZodObject<{
65
78
  threshold: z.ZodOptional<z.ZodNumber>;
66
79
  }, z.core.$strip>>;
67
80
  value: z.ZodString;
81
+ outcomeMode: z.ZodDefault<z.ZodEnum<{
82
+ static: "static";
83
+ dynamic: "dynamic";
84
+ }>>;
85
+ resolutionQuery: z.ZodOptional<z.ZodString>;
68
86
  }, z.core.$strip>, z.ZodObject<{
69
87
  label: z.ZodString;
70
88
  placeholder: z.ZodOptional<z.ZodString>;
@@ -85,6 +103,10 @@ export declare const testCaseInputArraySchema: z.ZodArray<z.ZodObject<{
85
103
  }, z.core.$strip>>;
86
104
  value: z.ZodString;
87
105
  }, z.core.$strip>], "type">>;
106
+ chatHistory: z.ZodOptional<z.ZodObject<{
107
+ enabled: z.ZodBoolean;
108
+ value: z.ZodString;
109
+ }, z.core.$strip>>;
88
110
  }, z.core.$strip>>;
89
111
  export declare const testCaseSchema: z.ZodObject<{
90
112
  id: z.ZodString;
@@ -108,6 +130,11 @@ export declare const testCaseSchema: z.ZodObject<{
108
130
  threshold: z.ZodOptional<z.ZodNumber>;
109
131
  }, z.core.$strip>>;
110
132
  value: z.ZodString;
133
+ outcomeMode: z.ZodDefault<z.ZodEnum<{
134
+ static: "static";
135
+ dynamic: "dynamic";
136
+ }>>;
137
+ resolutionQuery: z.ZodOptional<z.ZodString>;
111
138
  }, z.core.$strip>, z.ZodObject<{
112
139
  label: z.ZodString;
113
140
  placeholder: z.ZodOptional<z.ZodString>;
@@ -128,13 +155,18 @@ export declare const testCaseSchema: z.ZodObject<{
128
155
  }, z.core.$strip>>;
129
156
  value: z.ZodString;
130
157
  }, z.core.$strip>], "type">>;
158
+ chatHistory: z.ZodObject<{
159
+ enabled: z.ZodBoolean;
160
+ value: z.ZodString;
161
+ }, z.core.$strip>;
131
162
  output: z.ZodOptional<z.ZodString>;
132
163
  isRunning: z.ZodOptional<z.ZodBoolean>;
133
164
  error: z.ZodOptional<z.ZodString>;
134
165
  evaluationResult: z.ZodOptional<z.ZodCustom<EvaluationResult, EvaluationResult>>;
135
166
  responseTime: z.ZodOptional<z.ZodNumber>;
136
167
  }, z.core.$strip>;
137
- export type TestCaseInput = z.infer<typeof testCaseInputSchema>;
138
- export type TestCase = z.infer<typeof testCaseSchema>;
168
+ export type TestCaseChatHistory = z.infer<typeof testCaseChatHistorySchema>;
169
+ export type TestCaseInput = z.input<typeof testCaseInputSchema>;
170
+ export type TestCase = z.input<typeof testCaseSchema>;
139
171
  export declare function validateTestCaseInput(data: unknown): asserts data is TestCaseInput;
140
172
  export declare function validateTestCaseInputArray(data: unknown): asserts data is TestCaseInput[];
@@ -1 +1 @@
1
- export type { ExpectedOutcomeSchemaField, ExpectedOutcomeSchema, ExpectedOutcomeField, ExpectedOutcomeFieldType, ExpectedOutcomeBase, TextExpectedOutcomeSchemaField, TextareaExpectedOutcomeSchemaField, ChipsExpectedOutcomeSchemaField, SelectExpectedOutcomeSchemaField, TextExpectedOutcomeField, TextareaExpectedOutcomeField, ChipsExpectedOutcomeField, SelectExpectedOutcomeField, } from '../schemas/expected-outcome';
1
+ export type { ExpectedOutcomeMode, ExpectedOutcomeSchemaField, ExpectedOutcomeSchema, ExpectedOutcomeField, ExpectedOutcomeFieldType, ExpectedOutcomeBase, TextExpectedOutcomeSchemaField, TextareaExpectedOutcomeSchemaField, ChipsExpectedOutcomeSchemaField, SelectExpectedOutcomeSchemaField, TextExpectedOutcomeField, TextareaExpectedOutcomeField, ChipsExpectedOutcomeField, SelectExpectedOutcomeField, } from '../schemas/expected-outcome';
@@ -1,8 +1,9 @@
1
1
  import type { TestCase } from './test-case';
2
- export type { ExpectedOutcomeFieldType, ExpectedOutcomeBase, ExpectedOutcomeSchema, ExpectedOutcomeSchemaField, ExpectedOutcomeField, TextExpectedOutcomeSchemaField, TextareaExpectedOutcomeSchemaField, ChipsExpectedOutcomeSchemaField, SelectExpectedOutcomeSchemaField, TextExpectedOutcomeField, TextareaExpectedOutcomeField, ChipsExpectedOutcomeField, SelectExpectedOutcomeField, } from './expected-outcome';
3
- export type { TestCase, TestCaseInput, } from './test-case';
2
+ export type { ExpectedOutcomeMode, ExpectedOutcomeFieldType, ExpectedOutcomeBase, ExpectedOutcomeSchema, ExpectedOutcomeSchemaField, ExpectedOutcomeField, TextExpectedOutcomeSchemaField, TextareaExpectedOutcomeSchemaField, ChipsExpectedOutcomeSchemaField, SelectExpectedOutcomeSchemaField, TextExpectedOutcomeField, TextareaExpectedOutcomeField, ChipsExpectedOutcomeField, SelectExpectedOutcomeField, } from './expected-outcome';
3
+ export type { TestCaseChatHistory, TestCase, TestCaseInput, } from './test-case';
4
4
  export interface LLMRequestPayload {
5
5
  prompt: string;
6
+ chatHistory?: string;
6
7
  resolve: (result: string) => void;
7
8
  reject: (err: Error | unknown) => void;
8
9
  }
@@ -1 +1 @@
1
- export type { TestCaseInput, TestCase, } from '../schemas/test-case';
1
+ export type { TestCaseChatHistory, TestCaseInput, TestCase, } from '../schemas/test-case';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-testrunner-components",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "A Stencil web component library for LLM test runner functionality",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -1 +0,0 @@
1
- {"file":"app-chips_4.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"],"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.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 class=\"textarea-wrapper\">\n {c.label && (\n <label class=\"textarea-label\" htmlFor={c.name}>\n {c.label}\n </label>\n )}\n\n <textarea\n {...allowedAttrs}\n class=\"textarea-element\"\n value={this.value}\n onInput={this.handleChange}\n ></textarea>\n\n {c.helpText && <p class=\"help-text\">{c.helpText}</p>}\n </div>\n );\n }\n}\n"],"version":3}