llmxray 0.2.1 → 0.3.1

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 (50) hide show
  1. package/dist/assets/AITrainingPage-BmiTLvwB.js +1 -0
  2. package/dist/assets/{BenchmarkPage-yZ1Kt8KK.js → BenchmarkPage-CwCXzzrb.js} +2 -2
  3. package/dist/assets/ComparisonPage-nfG681cT.js +1 -0
  4. package/dist/assets/DashboardPage-CKQaBKDw.js +101 -0
  5. package/dist/assets/EmbeddingsPage-DJdyD65Q.js +1 -0
  6. package/dist/assets/EmbeddingsPage-DtEKy4qg.css +1 -0
  7. package/dist/assets/{GoogleCallbackPage-DqfqxXhg.js → GoogleCallbackPage-2hfuqKEi.js} +1 -1
  8. package/dist/assets/{JsonTreeNode-BE6Ps90W.js → JsonTreeNode-DckR4Nv8.js} +2 -2
  9. package/dist/assets/ModelCapabilityIcons.vue_vue_type_script_setup_true_lang-DUHfiPBt.js +1 -0
  10. package/dist/assets/RAGPage-jMq_Sg9F.js +1 -0
  11. package/dist/assets/SessionPage-C6jIbcq2.js +14 -0
  12. package/dist/assets/SettingsPage-CpDVuxxG.js +1 -0
  13. package/dist/assets/StatusBadge.vue_vue_type_script_setup_true_lang-D24kGmB6.js +1 -0
  14. package/dist/assets/StorageGauge.vue_vue_type_style_index_0_lang-CLdARZMv.js +1 -0
  15. package/dist/assets/SystemPage-BbfTFebq.js +2 -0
  16. package/dist/assets/{TabBar.vue_vue_type_script_setup_true_lang-CnQ8vq8x.js → TabBar.vue_vue_type_script_setup_true_lang-BV7bRKLd.js} +1 -1
  17. package/dist/assets/{TokenStreamDisplay.vue_vue_type_script_setup_true_lang-CJW7ndOY.js → TokenStreamDisplay.vue_vue_type_script_setup_true_lang-Cilrzwrg.js} +1 -1
  18. package/dist/assets/{ToolWorkshopPage-gO5DvECk.css → ToolWorkshopPage-7TRbWVVL.css} +1 -1
  19. package/dist/assets/{ToolWorkshopPage-DoVwZp_3.js → ToolWorkshopPage-BEFjvNVE.js} +88 -88
  20. package/dist/assets/{agent-store-_RIMRfEn.js → agent-store-tglPObkH.js} +1 -1
  21. package/dist/assets/generate-service-UqpNGQas.js +3 -0
  22. package/dist/assets/{google-auth-store-BnEs-xLw.js → google-auth-store-pjk41Wop.js} +1 -1
  23. package/dist/assets/index-CCnJ2vPZ.css +1 -0
  24. package/dist/assets/{index-D87kMEMb.js → index-Cq76cPsM.js} +1 -1
  25. package/dist/assets/index-DVvWJgFn.js +6 -0
  26. package/dist/assets/{metrics-store-HzdMIV8O.js → metrics-store-oAZX_4PZ.js} +1 -1
  27. package/dist/assets/{rag-store-VWnttX_x.js → rag-store-D6KNr_hW.js} +1 -1
  28. package/dist/assets/{storage-store-B1XevdC4.js → storage-store-D4WuNdQB.js} +1 -1
  29. package/dist/assets/{stream-handler-29OjEvbo.js → stream-handler-_fccIkW6.js} +2 -2
  30. package/dist/assets/{tool-workshop-store-Btx8DDqg.js → tool-workshop-store-Dz7QH2FM.js} +1 -1
  31. package/dist/assets/{toolcall-store-BumXt8DE.js → toolcall-store-BFoy2Mdx.js} +1 -1
  32. package/dist/assets/trash-2-CbznmmWI.js +1 -0
  33. package/dist/index.html +2 -2
  34. package/dist/social-card.svg +150 -0
  35. package/package.json +5 -2
  36. package/dist/assets/AITrainingPage-BbRryhHe.js +0 -1
  37. package/dist/assets/ComparisonPage-BnBp-VsC.js +0 -1
  38. package/dist/assets/DashboardPage-DTXPIpEx.js +0 -101
  39. package/dist/assets/EmbeddingsPage-Bo3g8-qN.css +0 -1
  40. package/dist/assets/EmbeddingsPage-CghkdGEr.js +0 -1
  41. package/dist/assets/ModelCapabilityIcons.vue_vue_type_script_setup_true_lang-CsL7aDHj.js +0 -1
  42. package/dist/assets/RAGPage-B_c1Nogo.js +0 -1
  43. package/dist/assets/SessionPage-lWGESxx3.js +0 -14
  44. package/dist/assets/SettingsPage-k9HWgy9B.js +0 -1
  45. package/dist/assets/StatusBadge.vue_vue_type_script_setup_true_lang-f9O-U2FX.js +0 -1
  46. package/dist/assets/StorageGauge.vue_vue_type_style_index_0_lang-hO4dId5t.js +0 -1
  47. package/dist/assets/SystemPage-BgwBHFJB.js +0 -2
  48. package/dist/assets/generate-service-mPYQA7Xh.js +0 -3
  49. package/dist/assets/index-BqB3FY2M.js +0 -4
  50. package/dist/assets/index-C0qd34Zo.css +0 -1
@@ -1 +1 @@
1
- import{d as T,r as i,c as f}from"./index-BqB3FY2M.js";const M=T("metrics",()=>{const s=i(new Map),a=i({totalSessions:0,avgTtftMs:0,avgTps:0,avgTotalDurationMs:0,totalTokensGenerated:0,totalPromptsEvaluated:0,modelsUsed:[]}),d=f(()=>[...s.value.values()].sort((t,e)=>t.startedAt-e.startedAt));function g(t){return s.value.get(t)??null}function m(t,e){s.value.set(t,e)}function v(){const t=[...s.value.values()];if(t.length===0)return;const e=new Set;let n=0,l=0,r=0,u=0,c=0;for(const o of t)e.add(o.model),n+=o.ttftMs,l+=o.tokensPerSecond,r+=o.totalDurationMs,u+=o.completionTokenCount,c+=o.promptTokenCount;a.value={totalSessions:t.length,avgTtftMs:n/t.length,avgTps:l/t.length,avgTotalDurationMs:r/t.length,totalTokensGenerated:u,totalPromptsEvaluated:c,modelsUsed:[...e]}}return{metricsBySession:s,aggregate:a,metricsHistory:d,getMetrics:g,recordMetrics:m,recalculateAggregate:v}});export{M as u};
1
+ import{d as T,r as i,a as f}from"./index-DVvWJgFn.js";const M=T("metrics",()=>{const s=i(new Map),a=i({totalSessions:0,avgTtftMs:0,avgTps:0,avgTotalDurationMs:0,totalTokensGenerated:0,totalPromptsEvaluated:0,modelsUsed:[]}),d=f(()=>[...s.value.values()].sort((t,e)=>t.startedAt-e.startedAt));function g(t){return s.value.get(t)??null}function m(t,e){s.value.set(t,e)}function v(){const t=[...s.value.values()];if(t.length===0)return;const e=new Set;let n=0,l=0,r=0,u=0,c=0;for(const o of t)e.add(o.model),n+=o.ttftMs,l+=o.tokensPerSecond,r+=o.totalDurationMs,u+=o.completionTokenCount,c+=o.promptTokenCount;a.value={totalSessions:t.length,avgTtftMs:n/t.length,avgTps:l/t.length,avgTotalDurationMs:r/t.length,totalTokensGenerated:u,totalPromptsEvaluated:c,modelsUsed:[...e]}}return{metricsBySession:s,aggregate:a,metricsHistory:d,getMetrics:g,recordMetrics:m,recalculateAggregate:v}});export{M as u};
@@ -1,5 +1,5 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DoAHVxX6.js","assets/_commonjsHelpers-DsqdWQfm.js","assets/papaparse.min-3s4OkBbM.js"])))=>i.map(i=>d[i]);
2
- import{_ as y,n as x,o as _,d as $,r as f,c as b}from"./index-BqB3FY2M.js";import{vectorDB as w}from"./vector-db-ChAzHl5A.js";async function I(e,o){switch(o){case"pdf":return O(e);case"docx":return j(e);case"csv":return R(e);case"txt":case"md":return e.text();default:throw new Error(`Unsupported format: ${o}`)}}async function O(e){const o=await y(()=>import("./pdf-vkbVaD7t.js"),[]);o.GlobalWorkerOptions.workerSrc=new URL("/assets/pdf.worker-CliDBb4N.mjs",import.meta.url).toString();const c=await e.arrayBuffer(),n=await o.getDocument({data:c}).promise,r=[];for(let a=1;a<=n.numPages;a++){const l=(await(await n.getPage(a)).getTextContent()).items.map(s=>"str"in s?s.str:"").join(" ");r.push(l)}return r.join(`
2
+ import{_ as y,n as x,o as _,d as $,r as f,a as b}from"./index-DVvWJgFn.js";import{vectorDB as w}from"./vector-db-ChAzHl5A.js";async function I(e,o){switch(o){case"pdf":return O(e);case"docx":return j(e);case"csv":return R(e);case"txt":case"md":return e.text();default:throw new Error(`Unsupported format: ${o}`)}}async function O(e){const o=await y(()=>import("./pdf-vkbVaD7t.js"),[]);o.GlobalWorkerOptions.workerSrc=new URL("/assets/pdf.worker-CliDBb4N.mjs",import.meta.url).toString();const c=await e.arrayBuffer(),n=await o.getDocument({data:c}).promise,r=[];for(let a=1;a<=n.numPages;a++){const l=(await(await n.getPage(a)).getTextContent()).items.map(s=>"str"in s?s.str:"").join(" ");r.push(l)}return r.join(`
3
3
 
4
4
  `)}async function j(e){const o=await y(()=>import("./index-DoAHVxX6.js").then(r=>r.i),__vite__mapDeps([0,1])),c=await e.arrayBuffer();return(await o.extractRawText({arrayBuffer:c})).value}async function R(e){const o=await y(()=>import("./papaparse.min-3s4OkBbM.js").then(n=>n.p),__vite__mapDeps([2,1])),c=await e.text();return new Promise((n,r)=>{o.default.parse(c,{header:!0,complete(a){const t=a.data.filter(u=>Object.values(u).some(l=>l!==""&&l!=null)).map((u,l)=>{const s=Object.entries(u).map(([d,m])=>`${d}: ${m}`).join(", ");return`Row ${l+1}: ${s}`});n(t.join(`
5
5
  `))},error(a){r(a)}})})}function T(e){switch(e.split(".").pop()?.toLowerCase()){case"pdf":return"pdf";case"docx":return"docx";case"txt":return"txt";case"md":return"md";case"csv":return"csv";default:return null}}const z={chunkSize:1e3,chunkOverlap:200,separator:`
@@ -1 +1 @@
1
- import{d as g,r as d,c as f}from"./index-BqB3FY2M.js";const b=[{id:"rag",dbName:"llmxray-rag",label:"Knowledge Base",icon:"📚",stores:["chunks","documents"]},{id:"conversations",dbName:"llmxray-conversations",label:"Conversations",icon:"💬",stores:["conversations","messages","sessions","tokens"]},{id:"benchmarks",dbName:"llmxray-benchmarks",label:"Benchmarks",icon:"⏱",stores:["results","custom-suites"]},{id:"message-memory",dbName:"llmxray-message-memory",label:"Message Memory",icon:"🧠",stores:["messages"]},{id:"canvas-ai",dbName:"llmxray-canvas-ai",label:"AI Training",icon:"🎨",stores:["training-pairs"]}];async function p(){if(!navigator.storage?.estimate)return{usage:0,quota:0,persisted:!1};const s=await navigator.storage.estimate(),e=await navigator.storage.persisted?.()??!1;return{usage:s.usage??0,quota:s.quota??0,persisted:e}}function y(s){if(s==null)return 0;if(typeof s!="object")return String(s).length*2;const e=s;let t=0;for(const o of Object.keys(e)){t+=o.length*2;const n=e[o];Array.isArray(n)&&n.length>0&&typeof n[0]=="number"?t+=n.length*8:typeof n=="string"?t+=n.length*2:typeof n=="number"?t+=8:typeof n=="boolean"?t+=4:n!=null&&typeof n=="object"&&(t+=y(n))}return t}function v(s){return new Promise(e=>{const t=indexedDB.open(s);t.onupgradeneeded=()=>{t.transaction?.abort(),e(null)},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null)})}function h(s,e){return new Promise(t=>{if(!s.objectStoreNames.contains(e)){t({name:e,bytes:0,count:0});return}const n=s.transaction(e,"readonly").objectStore(e);let c=0,r=0;const i=n.openCursor();i.onsuccess=()=>{const l=i.result;l?(c+=y(l.value),r++,l.continue()):t({name:e,bytes:c,count:r})},i.onerror=()=>t({name:e,bytes:0,count:0})})}async function w(s,e){const t=await v(s);if(!t)return{totalBytes:0,recordCount:0,stores:e.map(o=>({name:o,bytes:0,count:0}))};try{const o=[];for(const r of e)o.push(await h(t,r));const n=o.reduce((r,i)=>r+i.bytes,0),c=o.reduce((r,i)=>r+i.count,0);return{totalBytes:n,recordCount:c,stores:o}}finally{t.close()}}async function S(){const s=[];for(const e of b){const{totalBytes:t,recordCount:o,stores:n}=await w(e.dbName,e.stores);s.push({id:e.id,label:e.label,icon:e.icon,type:"indexeddb",totalBytes:t,recordCount:o,stores:n})}return s}const B=g("storage",()=>{const s=d(null),e=d([]),t=d(!1),o=d(null),n=f(()=>e.value.reduce((a,u)=>a+u.totalBytes,0)),c=f(()=>!s.value||s.value.quota===0?0:Math.round(s.value.usage/s.value.quota*100)),r=f(()=>e.value.reduce((a,u)=>a+u.recordCount,0));function i(a){return e.value.find(u=>u.id===a)}async function l(){t.value=!0;try{const[a,u]=await Promise.all([p(),S()]);s.value=a,e.value=u,o.value=Date.now()}catch(a){console.error("Failed to estimate storage:",a)}finally{t.value=!1}}async function m(a=3e4){(!o.value||Date.now()-o.value>a)&&await l()}return{origin:s,databases:e,loading:t,lastUpdated:o,totalUsedBytes:n,usedPercent:c,totalRecordCount:r,getDatabaseById:i,refresh:l,refreshIfStale:m}});export{B as u};
1
+ import{d as g,r as d,a as f}from"./index-DVvWJgFn.js";const b=[{id:"rag",dbName:"llmxray-rag",label:"Knowledge Base",icon:"📚",stores:["chunks","documents"]},{id:"conversations",dbName:"llmxray-conversations",label:"Conversations",icon:"💬",stores:["conversations","messages","sessions","tokens"]},{id:"benchmarks",dbName:"llmxray-benchmarks",label:"Benchmarks",icon:"⏱",stores:["results","custom-suites"]},{id:"message-memory",dbName:"llmxray-message-memory",label:"Message Memory",icon:"🧠",stores:["messages"]},{id:"canvas-ai",dbName:"llmxray-canvas-ai",label:"AI Training",icon:"🎨",stores:["training-pairs"]}];async function p(){if(!navigator.storage?.estimate)return{usage:0,quota:0,persisted:!1};const s=await navigator.storage.estimate(),e=await navigator.storage.persisted?.()??!1;return{usage:s.usage??0,quota:s.quota??0,persisted:e}}function y(s){if(s==null)return 0;if(typeof s!="object")return String(s).length*2;const e=s;let t=0;for(const a of Object.keys(e)){t+=a.length*2;const n=e[a];Array.isArray(n)&&n.length>0&&typeof n[0]=="number"?t+=n.length*8:typeof n=="string"?t+=n.length*2:typeof n=="number"?t+=8:typeof n=="boolean"?t+=4:n!=null&&typeof n=="object"&&(t+=y(n))}return t}function v(s){return new Promise(e=>{const t=indexedDB.open(s);t.onupgradeneeded=()=>{t.transaction?.abort(),e(null)},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null)})}function h(s,e){return new Promise(t=>{if(!s.objectStoreNames.contains(e)){t({name:e,bytes:0,count:0});return}const n=s.transaction(e,"readonly").objectStore(e);let c=0,r=0;const i=n.openCursor();i.onsuccess=()=>{const l=i.result;l?(c+=y(l.value),r++,l.continue()):t({name:e,bytes:c,count:r})},i.onerror=()=>t({name:e,bytes:0,count:0})})}async function w(s,e){const t=await v(s);if(!t)return{totalBytes:0,recordCount:0,stores:e.map(a=>({name:a,bytes:0,count:0}))};try{const a=[];for(const r of e)a.push(await h(t,r));const n=a.reduce((r,i)=>r+i.bytes,0),c=a.reduce((r,i)=>r+i.count,0);return{totalBytes:n,recordCount:c,stores:a}}finally{t.close()}}async function S(){const s=[];for(const e of b){const{totalBytes:t,recordCount:a,stores:n}=await w(e.dbName,e.stores);s.push({id:e.id,label:e.label,icon:e.icon,type:"indexeddb",totalBytes:t,recordCount:a,stores:n})}return s}const B=g("storage",()=>{const s=d(null),e=d([]),t=d(!1),a=d(null),n=f(()=>e.value.reduce((o,u)=>o+u.totalBytes,0)),c=f(()=>!s.value||s.value.quota===0?0:Math.round(s.value.usage/s.value.quota*100)),r=f(()=>e.value.reduce((o,u)=>o+u.recordCount,0));function i(o){return e.value.find(u=>u.id===o)}async function l(){t.value=!0;try{const[o,u]=await Promise.all([p(),S()]);s.value=o,e.value=u,a.value=Date.now()}catch(o){console.error("Failed to estimate storage:",o)}finally{t.value=!1}}async function m(o=3e4){(!a.value||Date.now()-a.value>o)&&await l()}return{origin:s,databases:e,loading:t,lastUpdated:a,totalUsedBytes:n,usedPercent:c,totalRecordCount:r,getDatabaseById:i,refresh:l,refreshIfStale:m}});export{B as u};
@@ -1,4 +1,4 @@
1
- import{n as u,z as O}from"./index-BqB3FY2M.js";import{u as G,a as q}from"./toolcall-store-BumXt8DE.js";import{a as R,b as E,u as J}from"./agent-store-_RIMRfEn.js";import{u as $}from"./metrics-store-HzdMIV8O.js";const B=1e6;function F(t,n,a,e,c){const s=(e.total_duration??0)/B,o=(e.load_duration??0)/B,i=(e.prompt_eval_duration??0)/B,l=(e.eval_duration??0)/B,p=e.prompt_eval_count??0,r=e.eval_count??0,h=l>0?r/l*1e3:0,f=i>0?p/i*1e3:0,d=c.length>0?c[0]:0;return{sessionId:t,model:n,startedAt:a,completedAt:Date.now(),ttftMs:d,totalDurationMs:s,loadDurationMs:o,promptEvalDurationMs:i,evalDurationMs:l,tokensPerSecond:h,promptTokensPerSecond:f,promptTokenCount:p,completionTokenCount:r,totalTokenCount:p+r,tokenLatencies:c}}class V{constructor(n){this.stepIndex=0,this.activeStep=null,this.inThinkBlock=!1,this.completedSteps=[],this.lastProcessedLineIndex=-1,this.thinkBlockProcessed=!1,this.enablePatternDetection=n?.patternDetection??!0}get isThinking(){return this.inThinkBlock}get thinkingContent(){return this.inThinkBlock&&this.activeStep?this.activeStep.content:""}processToken(n,a){if(!this.inThinkBlock&&!this.thinkBlockProcessed&&a.includes("<think>")){this.inThinkBlock=!0;const i=a.split("<think>").pop()??"";return this.activeStep={type:"thought",content:i,startTokenIndex:n.index,startTimestamp:n.timestamp},null}if(this.inThinkBlock&&a.includes("</think>")){if(this.inThinkBlock=!1,this.thinkBlockProcessed=!0,this.activeStep){const i=a.match(/<think>([\s\S]*?)<\/think>/);if(i?this.activeStep.content=i[1]?.trim()??this.activeStep.content.trim():this.activeStep.content=this.activeStep.content.replace(/<\/think>[\s\S]*$/,"").trim(),this.activeStep.content)return this.finalizeStep(n);this.activeStep=null}return null}if(this.inThinkBlock&&this.activeStep)return this.activeStep.content+=n.text,null;if(!this.enablePatternDetection)return null;const e=a.split(`
1
+ import{n as u,A as z}from"./index-DVvWJgFn.js";import{u as G,a as q}from"./toolcall-store-BFoy2Mdx.js";import{a as R,b as E,u as J}from"./agent-store-tglPObkH.js";import{u as $}from"./metrics-store-oAZX_4PZ.js";const B=1e6;function F(t,n,a,e,c){const s=(e.total_duration??0)/B,o=(e.load_duration??0)/B,i=(e.prompt_eval_duration??0)/B,l=(e.eval_duration??0)/B,p=e.prompt_eval_count??0,r=e.eval_count??0,h=l>0?r/l*1e3:0,f=i>0?p/i*1e3:0,d=c.length>0?c[0]:0;return{sessionId:t,model:n,startedAt:a,completedAt:Date.now(),ttftMs:d,totalDurationMs:s,loadDurationMs:o,promptEvalDurationMs:i,evalDurationMs:l,tokensPerSecond:h,promptTokensPerSecond:f,promptTokenCount:p,completionTokenCount:r,totalTokenCount:p+r,tokenLatencies:c}}class V{constructor(n){this.stepIndex=0,this.activeStep=null,this.inThinkBlock=!1,this.completedSteps=[],this.lastProcessedLineIndex=-1,this.thinkBlockProcessed=!1,this.enablePatternDetection=n?.patternDetection??!0}get isThinking(){return this.inThinkBlock}get thinkingContent(){return this.inThinkBlock&&this.activeStep?this.activeStep.content:""}processToken(n,a){if(!this.inThinkBlock&&!this.thinkBlockProcessed&&a.includes("<think>")){this.inThinkBlock=!0;const i=a.split("<think>").pop()??"";return this.activeStep={type:"thought",content:i,startTokenIndex:n.index,startTimestamp:n.timestamp},null}if(this.inThinkBlock&&a.includes("</think>")){if(this.inThinkBlock=!1,this.thinkBlockProcessed=!0,this.activeStep){const i=a.match(/<think>([\s\S]*?)<\/think>/);if(i?this.activeStep.content=i[1]?.trim()??this.activeStep.content.trim():this.activeStep.content=this.activeStep.content.replace(/<\/think>[\s\S]*$/,"").trim(),this.activeStep.content)return this.finalizeStep(n);this.activeStep=null}return null}if(this.inThinkBlock&&this.activeStep)return this.activeStep.content+=n.text,null;if(!this.enablePatternDetection)return null;const e=a.split(`
2
2
  `);if(e.length<2)return null;const c=e.length-2;if(c<=this.lastProcessedLineIndex)return null;this.lastProcessedLineIndex=c;const s=e[c]?.trim()??"";if(!s)return null;const o=K(s);if(o){let i=null;return this.activeStep&&(i=this.finalizeStep(n)),this.activeStep={type:o.type,content:o.content,startTokenIndex:n.index,startTimestamp:n.timestamp},i}return this.activeStep&&(this.activeStep.content+=n.text),null}finalize(){if(this.activeStep){const n={id:u(),index:this.stepIndex++,type:this.activeStep.type,content:this.activeStep.content.trim(),startTokenIndex:this.activeStep.startTokenIndex,endTokenIndex:this.activeStep.startTokenIndex,timestamp:this.activeStep.startTimestamp,durationMs:Date.now()-this.activeStep.startTimestamp};if(this.activeStep=null,n.content)return this.completedSteps.push(n),n}return null}finalizeStep(n){const a={id:u(),index:this.stepIndex++,type:this.activeStep.type,content:this.activeStep.content.trim(),startTokenIndex:this.activeStep.startTokenIndex,endTokenIndex:n.index,timestamp:this.activeStep.startTimestamp,durationMs:n.timestamp-this.activeStep.startTimestamp};return this.completedSteps.push(a),this.activeStep=null,a}}const H=[{regex:/^(?:Step\s+\d+[:.]\s*)(.+)/i,type:"thought"},{regex:/^(?:Thought[:.]\s*)(.+)/i,type:"thought"},{regex:/^(?:Observation[:.]\s*)(.+)/i,type:"observation"},{regex:/^(?:Action[:.]\s*)(.+)/i,type:"action"},{regex:/^(?:Conclusion[:.]\s*)(.+)/i,type:"conclusion"},{regex:/^(?:Therefore[,:.]\s*)(.+)/i,type:"conclusion"}];function K(t){const n=t.trim();for(const{regex:a,type:e}of H){const c=n.match(a);if(c)return{type:e,content:c[1]??n}}return null}async function Z(t,n,a){const e=t.getReader(),c=new TextDecoder;let s="";try{for(;!a?.aborted;){const{done:o,value:i}=await e.read();if(o)break;s+=c.decode(i,{stream:!0});const l=s.split(`
3
3
  `);s=l.pop()??"";for(const p of l){const r=p.trim();if(!r||!r.startsWith("data: "))continue;const h=r.slice(6);if(h==="[DONE]")return;try{const f=JSON.parse(h);n(f)}catch{}}}}finally{e.releaseLock()}}async function W(t,n,a){const e=t.getReader(),c=new TextDecoder;let s="";try{for(;!a?.aborted;){const{done:o,value:i}=await e.read();if(o)break;s+=c.decode(i,{stream:!0});const l=s.split(`
4
- `);s=l.pop()??"";for(const p of l){const r=p.trim();if(r)try{const h=JSON.parse(r);n(h)}catch{}}}if(s.trim())try{const o=JSON.parse(s.trim());n(o)}catch{}}finally{e.releaseLock()}}async function I(t,n,a){const e=G(),c=R(),s=$(),o=E(),i=J(),l=Date.now();let p=0,r=l,h="";const f=[],d=O(),b=e.sessionById(t),y=b?d.isThinkingModel(b.model):!1,x=new V({patternDetection:y});i.initGraph(t),i.addNode(t,{id:u(),type:"start",label:"Generation Start",sessionId:t,stepIndex:0,state:{},timestamp:l}),e.updateSessionStatus(t,"streaming"),await W(n,g=>{const M=Date.now(),D=M-r;h+=g.response;const C=j(D,f),v={id:u(),index:p++,text:g.response,timestamp:M,confidence:C,cumulativeText:h,interTokenLatencyMs:D};c.pushToken(t,v),e.appendOutput(t,g.response),f.push(D),r=M;const k=x.processToken(v,h);if(o.setThinking(t,x.isThinking,x.thinkingContent),k&&(o.addStep(t,k),i.addNode(t,{id:u(),type:"decision",label:`${k.type}: ${k.content.slice(0,40)}...`,sessionId:t,stepIndex:k.index,state:{reasoning:k.type},timestamp:k.timestamp})),g.done){x.finalize(),o.setThinking(t,!1,""),g.done_reason&&e.setDoneReason(t,g.done_reason);const m=e.sessionById(t);if(m){const T=F(t,m.model,l,g,f);s.recordMetrics(t,T),e.finalizeSession(t,T),s.recalculateAggregate()}i.addNode(t,{id:u(),type:"output",label:"Generation Complete",sessionId:t,stepIndex:p,state:{tokenCount:p},timestamp:Date.now()})}},a)}async function tt(t,n,a){const e=G(),c=R(),s=$(),o=E(),i=q(),l=J(),p=Date.now();let r=0,h=p,f="",d="",b="",y=!1;const x=[],g=[],M=O(),D=e.sessionById(t),C=D?M.isThinkingModel(D.model):!1,v=new V({patternDetection:C});l.initGraph(t);const k=l.getGraph(t);return(!k||k.nodes.length===0)&&l.addNode(t,{id:u(),type:"start",label:"Chat Start",sessionId:t,stepIndex:0,state:{},timestamp:p}),e.updateSessionStatus(t,"streaming"),await W(n,m=>{const T=Date.now(),w=T-h,z=m.message.thinking;if(z){y=!0,d+=z,o.setThinking(t,!0,d),x.push(w),h=T;return}y&&d&&!m.done&&(o.setThinking(t,!1,d),d.trim()&&o.addStep(t,{id:u(),index:0,type:"thought",content:d.trim(),startTokenIndex:0,endTokenIndex:r,timestamp:T,durationMs:T-p}),b=d,d="");const N=m.message.content;f+=N;let P,L;m.logprobs&&m.logprobs.length>0?(L=m.logprobs[0].logprob,P=Math.exp(L)):P=j(w,x);const A={id:u(),index:r++,text:N,timestamp:T,confidence:P,logprob:L,cumulativeText:f,interTokenLatencyMs:w};if(c.pushToken(t,A),e.appendOutput(t,N),x.push(w),h=T,!y){const S=v.processToken(A,f);o.setThinking(t,v.isThinking,v.thinkingContent),S&&o.addStep(t,S)}if(m.message.tool_calls)for(const S of m.message.tool_calls){g.push(S);const _={id:u(),sessionId:t,index:i.getToolCalls(t).length,functionName:S.function.name,arguments:S.function.arguments,status:"pending",startedAt:T,tokenIndexStart:r};i.addToolCall(t,_),l.addNode(t,{id:u(),type:"tool_call",label:`Tool: ${S.function.name}`,sessionId:t,stepIndex:r,state:{tool:S.function.name,args:S.function.arguments},timestamp:T})}if(m.done&&(y&&d.trim()&&(b=d,o.addStep(t,{id:u(),index:0,type:"thought",content:d.trim(),startTokenIndex:0,endTokenIndex:r,timestamp:Date.now(),durationMs:Date.now()-p})),v.finalize(),o.setThinking(t,!1,y?b:""),m.done_reason&&e.setDoneReason(t,m.done_reason),g.length===0)){const S=e.sessionById(t);if(S){const _=F(t,S.model,p,m,x);s.recordMetrics(t,_),e.finalizeSession(t,_),s.recalculateAggregate()}l.addNode(t,{id:u(),type:"output",label:"Chat Complete",sessionId:t,stepIndex:r,state:{tokenCount:r},timestamp:Date.now()})}},a),{toolCalls:g}}function j(t,n){if(n.length<2)return .5;const a=[...n].sort((o,i)=>o-i),e=a[Math.floor(a.length/2)];if(e<=0)return .5;const c=t/e,s=Math.max(0,Math.min(1,1-(c-.5)/2));return Math.round(s*100)/100}export{I as a,tt as e,Z as r};
4
+ `);s=l.pop()??"";for(const p of l){const r=p.trim();if(r)try{const h=JSON.parse(r);n(h)}catch{}}}if(s.trim())try{const o=JSON.parse(s.trim());n(o)}catch{}}finally{e.releaseLock()}}async function I(t,n,a){const e=G(),c=R(),s=$(),o=E(),i=J(),l=Date.now();let p=0,r=l,h="";const f=[],d=z(),b=e.sessionById(t),y=b?d.isThinkingModel(b.model):!1,x=new V({patternDetection:y});i.initGraph(t),i.addNode(t,{id:u(),type:"start",label:"Generation Start",sessionId:t,stepIndex:0,state:{},timestamp:l}),e.updateSessionStatus(t,"streaming"),await W(n,g=>{const M=Date.now(),D=M-r;h+=g.response;const C=j(D,f),v={id:u(),index:p++,text:g.response,timestamp:M,confidence:C,cumulativeText:h,interTokenLatencyMs:D};c.pushToken(t,v),e.appendOutput(t,g.response),f.push(D),r=M;const k=x.processToken(v,h);if(o.setThinking(t,x.isThinking,x.thinkingContent),k&&(o.addStep(t,k),i.addNode(t,{id:u(),type:"decision",label:`${k.type}: ${k.content.slice(0,40)}...`,sessionId:t,stepIndex:k.index,state:{reasoning:k.type},timestamp:k.timestamp})),g.done){x.finalize(),o.setThinking(t,!1,""),g.done_reason&&e.setDoneReason(t,g.done_reason);const m=e.sessionById(t);if(m){const T=F(t,m.model,l,g,f);s.recordMetrics(t,T),e.finalizeSession(t,T),s.recalculateAggregate()}i.addNode(t,{id:u(),type:"output",label:"Generation Complete",sessionId:t,stepIndex:p,state:{tokenCount:p},timestamp:Date.now()})}},a)}async function tt(t,n,a){const e=G(),c=R(),s=$(),o=E(),i=q(),l=J(),p=Date.now();let r=0,h=p,f="",d="",b="",y=!1;const x=[],g=[],M=z(),D=e.sessionById(t),C=D?M.isThinkingModel(D.model):!1,v=new V({patternDetection:C});l.initGraph(t);const k=l.getGraph(t);return(!k||k.nodes.length===0)&&l.addNode(t,{id:u(),type:"start",label:"Chat Start",sessionId:t,stepIndex:0,state:{},timestamp:p}),e.updateSessionStatus(t,"streaming"),await W(n,m=>{const T=Date.now(),w=T-h,A=m.message.thinking;if(A){y=!0,d+=A,o.setThinking(t,!0,d),x.push(w),h=T;return}y&&d&&!m.done&&(o.setThinking(t,!1,d),d.trim()&&o.addStep(t,{id:u(),index:0,type:"thought",content:d.trim(),startTokenIndex:0,endTokenIndex:r,timestamp:T,durationMs:T-p}),b=d,d="");const N=m.message.content;f+=N;let P,L;m.logprobs&&m.logprobs.length>0?(L=m.logprobs[0].logprob,P=Math.exp(L)):P=j(w,x);const O={id:u(),index:r++,text:N,timestamp:T,confidence:P,logprob:L,cumulativeText:f,interTokenLatencyMs:w};if(c.pushToken(t,O),e.appendOutput(t,N),x.push(w),h=T,!y){const S=v.processToken(O,f);o.setThinking(t,v.isThinking,v.thinkingContent),S&&o.addStep(t,S)}if(m.message.tool_calls)for(const S of m.message.tool_calls){g.push(S);const _={id:u(),sessionId:t,index:i.getToolCalls(t).length,functionName:S.function.name,arguments:S.function.arguments,status:"pending",startedAt:T,tokenIndexStart:r};i.addToolCall(t,_),l.addNode(t,{id:u(),type:"tool_call",label:`Tool: ${S.function.name}`,sessionId:t,stepIndex:r,state:{tool:S.function.name,args:S.function.arguments},timestamp:T})}if(m.done&&(y&&d.trim()&&(b=d,o.addStep(t,{id:u(),index:0,type:"thought",content:d.trim(),startTokenIndex:0,endTokenIndex:r,timestamp:Date.now(),durationMs:Date.now()-p})),v.finalize(),o.setThinking(t,!1,y?b:""),m.done_reason&&e.setDoneReason(t,m.done_reason),g.length===0)){const S=e.sessionById(t);if(S){const _=F(t,S.model,p,m,x);s.recordMetrics(t,_),e.finalizeSession(t,_),s.recalculateAggregate()}l.addNode(t,{id:u(),type:"output",label:"Chat Complete",sessionId:t,stepIndex:r,state:{tokenCount:r},timestamp:Date.now()})}},a),{toolCalls:g}}function j(t,n){if(n.length<2)return .5;const a=[...n].sort((o,i)=>o-i),e=a[Math.floor(a.length/2)];if(e<=0)return .5;const c=t/e,s=Math.max(0,Math.min(1,1-(c-.5)/2));return Math.round(s*100)/100}export{I as a,tt as e,Z as r};
@@ -1 +1 @@
1
- import{d as k,r as f,c as i,n as x}from"./index-BqB3FY2M.js";function m(){return{mode:"code",blocks:[],code:""}}const v="llmxray-workshop-tools",D="llmxray-tool-definitions",_=k("tool-workshop",()=>{const n=f({}),a=f(null);function p(){try{const e=localStorage.getItem(v);if(e){const t=JSON.parse(e),o={};for(const l of t)o[l.id]=l;n.value=o;return}g()}catch{}}function g(){try{const e=localStorage.getItem(D);if(!e)return;const t=JSON.parse(e),o={};for(const l of t){const d={id:l.id,definition:l.definition,implementation:m(),enabled:l.enabled,category:"custom",createdAt:l.createdAt,updatedAt:l.updatedAt,lastTestedAt:null,testResult:null};o[d.id]=d}n.value=o,c()}catch{}}function c(){const e=Object.values(n.value);localStorage.setItem(v,JSON.stringify(e))}p();const u=i(()=>Object.values(n.value)),r=i(()=>u.value.filter(e=>e.enabled)),y=i(()=>r.value.map(e=>e.definition)),b=i(()=>{const e={};for(const t of u.value){const o=t.category||"custom";e[o]||(e[o]=[]),e[o].push(t)}return e}),S=i(()=>a.value?n.value[a.value]??null:null);function s(e){const t=x(),o=Date.now(),l={id:t,definition:e.definition,implementation:e.implementation??m(),enabled:e.enabled??!1,category:e.category??"custom",createdAt:o,updatedAt:o,lastTestedAt:null,testResult:null};return n.value[t]=l,c(),t}function O(e,t){const o=n.value[e];o&&(n.value[e]={...o,...t,updatedAt:Date.now()},c())}function T(e){delete n.value[e],a.value===e&&(a.value=null),c()}function A(){n.value={},a.value=null,c()}function w(e){const t=n.value[e];if(!t)return null;const o=JSON.parse(JSON.stringify(t.definition));return o.function.name=`${o.function.name}_copy`,s({definition:o,implementation:JSON.parse(JSON.stringify(t.implementation)),category:t.category})}function N(e){const t=n.value[e];t&&(n.value[e]={...t,enabled:!t.enabled},c())}function J(){for(const e of Object.keys(n.value))n.value[e]={...n.value[e],enabled:!1};c()}function h(e){a.value=e}function E(e){return n.value[e]}function I(e){return u.value.find(t=>t.definition.function.name===e)}return{tools:n,selectedToolId:a,allTools:u,enabledTools:r,enabledDefinitions:y,toolsByCategory:b,selectedTool:S,addTool:s,updateTool:O,removeTool:T,clearAll:A,duplicateTool:w,toggleEnabled:N,disableAll:J,selectTool:h,getById:E,findByFunctionName:I}});export{_ as u};
1
+ import{d as k,r as f,a as u,n as x}from"./index-DVvWJgFn.js";function m(){return{mode:"code",blocks:[],code:""}}const v="llmxray-workshop-tools",D="llmxray-tool-definitions",_=k("tool-workshop",()=>{const n=f({}),a=f(null);function p(){try{const e=localStorage.getItem(v);if(e){const t=JSON.parse(e),o={};for(const l of t)o[l.id]=l;n.value=o;return}g()}catch{}}function g(){try{const e=localStorage.getItem(D);if(!e)return;const t=JSON.parse(e),o={};for(const l of t){const d={id:l.id,definition:l.definition,implementation:m(),enabled:l.enabled,category:"custom",createdAt:l.createdAt,updatedAt:l.updatedAt,lastTestedAt:null,testResult:null};o[d.id]=d}n.value=o,i()}catch{}}function i(){const e=Object.values(n.value);localStorage.setItem(v,JSON.stringify(e))}p();const c=u(()=>Object.values(n.value)),r=u(()=>c.value.filter(e=>e.enabled)),y=u(()=>r.value.map(e=>e.definition)),b=u(()=>{const e={};for(const t of c.value){const o=t.category||"custom";e[o]||(e[o]=[]),e[o].push(t)}return e}),S=u(()=>a.value?n.value[a.value]??null:null);function s(e){const t=x(),o=Date.now(),l={id:t,definition:e.definition,implementation:e.implementation??m(),enabled:e.enabled??!1,category:e.category??"custom",createdAt:o,updatedAt:o,lastTestedAt:null,testResult:null};return n.value[t]=l,i(),t}function O(e,t){const o=n.value[e];o&&(n.value[e]={...o,...t,updatedAt:Date.now()},i())}function T(e){delete n.value[e],a.value===e&&(a.value=null),i()}function A(){n.value={},a.value=null,i()}function w(e){const t=n.value[e];if(!t)return null;const o=JSON.parse(JSON.stringify(t.definition));return o.function.name=`${o.function.name}_copy`,s({definition:o,implementation:JSON.parse(JSON.stringify(t.implementation)),category:t.category})}function N(e){const t=n.value[e];t&&(n.value[e]={...t,enabled:!t.enabled},i())}function J(){for(const e of Object.keys(n.value))n.value[e]={...n.value[e],enabled:!1};i()}function h(e){a.value=e}function E(e){return n.value[e]}function I(e){return c.value.find(t=>t.definition.function.name===e)}return{tools:n,selectedToolId:a,allTools:c,enabledTools:r,enabledDefinitions:y,toolsByCategory:b,selectedTool:S,addTool:s,updateTool:O,removeTool:T,clearAll:A,duplicateTool:w,toggleEnabled:N,disableAll:J,selectTool:h,getById:E,findByFunctionName:I}});export{_ as u};
@@ -1 +1 @@
1
- import{d as m,r as f,c as S,n as M,H as x}from"./index-BqB3FY2M.js";const B=m("sessions",()=>{const n=f(new Map),u=f(null),l=f(new Map),v=S(()=>u.value?n.value.get(u.value)??null:null),d=S(()=>[...n.value.values()].sort((e,s)=>s.createdAt-e.createdAt));function o(e){return n.value.get(e)}function a(e){const s=M(),t={id:s,mode:e.mode,model:e.model,status:"idle",createdAt:Date.now(),prompt:e.prompt,messages:e.messages??[],options:e.options??{},outputText:"",metrics:null};return n.value.set(s,t),s}function i(e,s){l.value.set(e,s)}function c(e,s){const t=n.value.get(e);t&&(t.status=s)}function r(e,s){const t=n.value.get(e);t&&(t.outputText+=s)}function g(e,s){const t=n.value.get(e);if(t){t.status="completed",t.metrics=s;const p=l.value.get(e);p&&x.saveSession(t,p).catch(console.error)}}function C(e,s){const t=n.value.get(e);t&&(t.status="error",t.error=s)}function T(e){const s=n.value.get(e);s&&(s.status="cancelled")}function w(e,s){const t=n.value.get(e);t&&(t.doneReason=s)}function A(e){u.value=e}return{sessions:n,activeSessionId:u,activeSession:v,recentSessions:d,sessionConversationMap:l,sessionById:o,createSession:a,linkSessionToConversation:i,updateSessionStatus:c,appendOutput:r,finalizeSession:g,setSessionError:C,cancelSession:T,setDoneReason:w,setActiveSession:A}}),D=m("toolcalls",()=>{const n=f(new Map);function u(o){return n.value.get(o)??[]}function l(o){return u(o).filter(a=>a.status==="pending")}function v(o,a){let i=n.value.get(o);i||(i=[],n.value.set(o,i)),i.push(a)}function d(o,a,i){const c=n.value.get(o);if(!c)return;const r=c.find(g=>g.id===a);r&&Object.assign(r,i)}return{callsBySession:n,getToolCalls:u,getPendingCalls:l,addToolCall:v,updateToolCall:d}});export{D as a,B as u};
1
+ import{d as m,r as f,a as S,n as M,J as x}from"./index-DVvWJgFn.js";const B=m("sessions",()=>{const n=f(new Map),u=f(null),l=f(new Map),v=S(()=>u.value?n.value.get(u.value)??null:null),d=S(()=>[...n.value.values()].sort((e,s)=>s.createdAt-e.createdAt));function o(e){return n.value.get(e)}function a(e){const s=M(),t={id:s,mode:e.mode,model:e.model,status:"idle",createdAt:Date.now(),prompt:e.prompt,messages:e.messages??[],options:e.options??{},outputText:"",metrics:null};return n.value.set(s,t),s}function i(e,s){l.value.set(e,s)}function c(e,s){const t=n.value.get(e);t&&(t.status=s)}function r(e,s){const t=n.value.get(e);t&&(t.outputText+=s)}function g(e,s){const t=n.value.get(e);if(t){t.status="completed",t.metrics=s;const p=l.value.get(e);p&&x.saveSession(t,p).catch(console.error)}}function C(e,s){const t=n.value.get(e);t&&(t.status="error",t.error=s)}function T(e){const s=n.value.get(e);s&&(s.status="cancelled")}function w(e,s){const t=n.value.get(e);t&&(t.doneReason=s)}function A(e){u.value=e}return{sessions:n,activeSessionId:u,activeSession:v,recentSessions:d,sessionConversationMap:l,sessionById:o,createSession:a,linkSessionToConversation:i,updateSessionStatus:c,appendOutput:r,finalizeSession:g,setSessionError:C,cancelSession:T,setDoneReason:w,setActiveSession:A}}),D=m("toolcalls",()=>{const n=f(new Map);function u(o){return n.value.get(o)??[]}function l(o){return u(o).filter(a=>a.status==="pending")}function v(o,a){let i=n.value.get(o);i||(i=[],n.value.set(o,i)),i.push(a)}function d(o,a,i){const c=n.value.get(o);if(!c)return;const r=c.find(g=>g.id===a);r&&Object.assign(r,i)}return{callsBySession:n,getToolCalls:u,getPendingCalls:l,addToolCall:v,updateToolCall:d}});export{D as a,B as u};
@@ -0,0 +1 @@
1
+ import{c as a}from"./index-DVvWJgFn.js";const e=a("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);export{e as T};
package/dist/index.html CHANGED
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>LLMxRay — Local LLM Observatory</title>
8
- <script type="module" crossorigin src="/assets/index-BqB3FY2M.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-C0qd34Zo.css">
8
+ <script type="module" crossorigin src="/assets/index-DVvWJgFn.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-CCnJ2vPZ.css">
10
10
  </head>
11
11
  <body>
12
12
  <script>
@@ -0,0 +1,150 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1280" height="640" viewBox="0 0 1280 640">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
4
+ <stop offset="0%" stop-color="#0f0a2e"/>
5
+ <stop offset="50%" stop-color="#1e1b4b"/>
6
+ <stop offset="100%" stop-color="#0f172a"/>
7
+ </linearGradient>
8
+ <linearGradient id="pulse" x1="0" y1="0" x2="1" y2="0">
9
+ <stop offset="0%" stop-color="#7c3aed" stop-opacity="0.3"/>
10
+ <stop offset="30%" stop-color="#a855f7"/>
11
+ <stop offset="70%" stop-color="#c084fc"/>
12
+ <stop offset="100%" stop-color="#e9d5ff"/>
13
+ </linearGradient>
14
+ <linearGradient id="chipStroke" x1="0" y1="0" x2="1" y2="1">
15
+ <stop offset="0%" stop-color="#a855f7"/>
16
+ <stop offset="100%" stop-color="#6d28d9"/>
17
+ </linearGradient>
18
+ <filter id="pulseGlow">
19
+ <feGaussianBlur in="SourceGraphic" stdDeviation="3"/>
20
+ </filter>
21
+ <filter id="textGlow">
22
+ <feGaussianBlur in="SourceGraphic" stdDeviation="8"/>
23
+ </filter>
24
+ </defs>
25
+
26
+ <!-- Background -->
27
+ <rect width="1280" height="640" fill="url(#bg)"/>
28
+
29
+ <!-- Subtle grid pattern -->
30
+ <g stroke="#a855f7" stroke-width="0.5" opacity="0.04">
31
+ <line x1="0" y1="80" x2="1280" y2="80"/><line x1="0" y1="160" x2="1280" y2="160"/>
32
+ <line x1="0" y1="240" x2="1280" y2="240"/><line x1="0" y1="320" x2="1280" y2="320"/>
33
+ <line x1="0" y1="400" x2="1280" y2="400"/><line x1="0" y1="480" x2="1280" y2="480"/>
34
+ <line x1="0" y1="560" x2="1280" y2="560"/>
35
+ <line x1="160" y1="0" x2="160" y2="640"/><line x1="320" y1="0" x2="320" y2="640"/>
36
+ <line x1="480" y1="0" x2="480" y2="640"/><line x1="640" y1="0" x2="640" y2="640"/>
37
+ <line x1="800" y1="0" x2="800" y2="640"/><line x1="960" y1="0" x2="960" y2="640"/>
38
+ <line x1="1120" y1="0" x2="1120" y2="640"/>
39
+ </g>
40
+
41
+ <!-- Large ambient glow behind icon -->
42
+ <circle cx="640" cy="240" r="200" fill="#a855f7" opacity="0.06"/>
43
+ <circle cx="640" cy="240" r="120" fill="#7c3aed" opacity="0.08"/>
44
+
45
+ <!-- === FAVICON ICON (centered, scaled up) === -->
46
+ <g transform="translate(576, 150) scale(1.0)">
47
+ <!-- Chip outline -->
48
+ <rect x="34" y="34" width="60" height="60" rx="6" fill="none" stroke="url(#chipStroke)" stroke-width="2.5" opacity="0.55"/>
49
+
50
+ <!-- Chip pins — top -->
51
+ <g stroke="#8b5cf6" stroke-width="2.5" stroke-linecap="round" opacity="0.35">
52
+ <line x1="50" y1="22" x2="50" y2="34"/>
53
+ <line x1="64" y1="18" x2="64" y2="34"/>
54
+ <line x1="78" y1="22" x2="78" y2="34"/>
55
+ </g>
56
+ <!-- Chip pins — bottom -->
57
+ <g stroke="#8b5cf6" stroke-width="2.5" stroke-linecap="round" opacity="0.35">
58
+ <line x1="50" y1="94" x2="50" y2="106"/>
59
+ <line x1="64" y1="94" x2="64" y2="110"/>
60
+ <line x1="78" y1="94" x2="78" y2="106"/>
61
+ </g>
62
+ <!-- Chip pins — left -->
63
+ <g stroke="#8b5cf6" stroke-width="2.5" stroke-linecap="round" opacity="0.35">
64
+ <line x1="22" y1="50" x2="34" y2="50"/>
65
+ <line x1="18" y1="64" x2="34" y2="64"/>
66
+ <line x1="22" y1="78" x2="34" y2="78"/>
67
+ </g>
68
+ <!-- Chip pins — right -->
69
+ <g stroke="#8b5cf6" stroke-width="2.5" stroke-linecap="round" opacity="0.35">
70
+ <line x1="94" y1="50" x2="106" y2="50"/>
71
+ <line x1="94" y1="64" x2="110" y2="64"/>
72
+ <line x1="94" y1="78" x2="106" y2="78"/>
73
+ </g>
74
+
75
+ <!-- Grid inside chip -->
76
+ <g stroke="#a855f7" stroke-width="0.5" opacity="0.08">
77
+ <line x1="38" y1="44" x2="90" y2="44"/><line x1="38" y1="54" x2="90" y2="54"/>
78
+ <line x1="38" y1="74" x2="90" y2="74"/><line x1="38" y1="84" x2="90" y2="84"/>
79
+ <line x1="48" y1="36" x2="48" y2="92"/><line x1="58" y1="36" x2="58" y2="92"/>
80
+ <line x1="68" y1="36" x2="68" y2="92"/><line x1="78" y1="36" x2="78" y2="92"/>
81
+ </g>
82
+
83
+ <!-- Circuit traces -->
84
+ <g stroke="#c084fc" stroke-width="1" opacity="0.15" stroke-linecap="round">
85
+ <polyline points="44,44 56,44 56,52" fill="none"/>
86
+ <polyline points="72,44 84,44 84,52" fill="none"/>
87
+ <polyline points="44,84 56,84 56,76" fill="none"/>
88
+ <polyline points="72,84 84,84 84,76" fill="none"/>
89
+ </g>
90
+
91
+ <!-- Pulse glow -->
92
+ <polyline
93
+ points="12,64 32,64 40,64 47,48 52,76 57,38 63,82 69,42 75,78 81,50 88,64 96,64 116,64"
94
+ fill="none" stroke="#a855f7" stroke-width="6"
95
+ stroke-linecap="round" stroke-linejoin="round"
96
+ opacity="0.15" filter="url(#pulseGlow)"
97
+ />
98
+ <!-- Main pulse -->
99
+ <polyline
100
+ points="12,64 32,64 40,64 47,48 52,76 57,38 63,82 69,42 75,78 81,50 88,64 96,64 116,64"
101
+ fill="none" stroke="url(#pulse)" stroke-width="3"
102
+ stroke-linecap="round" stroke-linejoin="round"
103
+ />
104
+ <!-- Pulse dot -->
105
+ <circle cx="116" cy="64" r="4" fill="#c084fc" opacity="0.4"/>
106
+ <circle cx="116" cy="64" r="2.5" fill="#e9d5ff"/>
107
+ </g>
108
+
109
+ <!-- === PROJECT NAME === -->
110
+ <!-- Glow behind text -->
111
+ <text x="640" y="370" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="800" fill="#a855f7" opacity="0.15" filter="url(#textGlow)">LLMxRay</text>
112
+ <!-- Main text -->
113
+ <text x="640" y="370" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="800">
114
+ <tspan fill="#f1f5f9">LLM</tspan><tspan fill="#a855f7" font-family="'Courier New', monospace">xR</tspan><tspan fill="#f1f5f9">ay</tspan>
115
+ </text>
116
+
117
+ <!-- === TAGLINE === -->
118
+ <text x="640" y="420" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="24" fill="#94a3b8" font-weight="400">
119
+ Local LLM Observatory
120
+ </text>
121
+
122
+ <!-- === SUBTITLE === -->
123
+ <text x="640" y="470" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="18" fill="#64748b" font-weight="300">
124
+ See what your AI is actually doing — token by token, layer by layer.
125
+ </text>
126
+
127
+ <!-- === BOTTOM PILLS === -->
128
+ <!-- Vue pill -->
129
+ <rect x="370" y="530" width="80" height="28" rx="14" fill="#42b883" opacity="0.15"/>
130
+ <text x="410" y="549" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" fill="#42b883" font-weight="500">Vue 3</text>
131
+
132
+ <!-- TypeScript pill -->
133
+ <rect x="470" y="530" width="110" height="28" rx="14" fill="#3178c6" opacity="0.15"/>
134
+ <text x="525" y="549" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" fill="#3178c6" font-weight="500">TypeScript</text>
135
+
136
+ <!-- Ollama pill -->
137
+ <rect x="600" y="530" width="85" height="28" rx="14" fill="#f1f5f9" opacity="0.1"/>
138
+ <text x="642" y="549" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" fill="#94a3b8" font-weight="500">Ollama</text>
139
+
140
+ <!-- Free pill -->
141
+ <rect x="705" y="530" width="65" height="28" rx="14" fill="#4ade80" opacity="0.15"/>
142
+ <text x="737" y="549" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" fill="#4ade80" font-weight="500">Free</text>
143
+
144
+ <!-- Local pill -->
145
+ <rect x="790" y="530" width="70" height="28" rx="14" fill="#c084fc" opacity="0.15"/>
146
+ <text x="825" y="549" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" fill="#c084fc" font-weight="500">Local</text>
147
+
148
+ <!-- Subtle border -->
149
+ <rect x="0" y="0" width="1280" height="640" rx="0" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.1"/>
150
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmxray",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Local LLM Observatory — See what your AI is actually doing, token by token.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -37,7 +37,9 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "express": "^5.1.0",
40
- "http-proxy-middleware": "^3.0.3"
40
+ "http-proxy-middleware": "^3.0.3",
41
+ "lucide-vue-next": "^0.577.0",
42
+ "vue-i18n": "^10.0.8"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@babel/parser": "^7.29.0",
@@ -46,6 +48,7 @@
46
48
  "@codemirror/theme-one-dark": "^6.1.3",
47
49
  "@fontsource/fira-code": "^5.2.7",
48
50
  "@fontsource/inter": "^5.2.8",
51
+ "@intlify/unplugin-vue-i18n": "^11.0.7",
49
52
  "@playwright/test": "^1.58.2",
50
53
  "@tailwindcss/vite": "^4.2.1",
51
54
  "@types/d3": "^7.4.3",
@@ -1 +0,0 @@
1
- import{d as H,r as h,c as I,a as D,e as p,f as e,t as m,m as R,u,i as $,k as Q,F as A,j as S,b as c,g as w,h as j,B as E,C as L,p as N,v as X,M as V,A as Y,s as Z,ab as _}from"./index-BqB3FY2M.js";import{canvasAiDB as P}from"./canvas-ai-db-BolM-_G7.js";import{b as ee,d as z}from"./format-BqVZ9rwM.js";import{_ as te}from"./StorageGauge.vue_vue_type_style_index_0_lang-hO4dId5t.js";const se=H("training",()=>{const s=h([]),l=h(!1),g=h(new Set),o=h(null),f=h({phase:null,model:null,accepted:null,toolName:null,tag:null,search:"",sortBy:"timestamp",sortDir:"desc"}),n=I(()=>{let r=[...s.value];const i=f.value;if(i.phase&&(r=r.filter(x=>x.phase===i.phase)),i.model&&(r=r.filter(x=>x.model===i.model)),i.accepted!==null&&(r=r.filter(x=>x.accepted===i.accepted)),i.toolName&&(r=r.filter(x=>x.toolName===i.toolName)),i.tag&&(r=r.filter(x=>x.tags?.includes(i.tag)??!1)),i.search){const x=i.search.toLowerCase();r=r.filter(v=>v.userPrompt.toLowerCase().includes(x)||v.response.toLowerCase().includes(x)||v.toolName.toLowerCase().includes(x))}return r.sort((x,v)=>{let k=0;return i.sortBy==="timestamp"?k=x.timestamp-v.timestamp:i.sortBy==="phase"?k=x.phase.localeCompare(v.phase):i.sortBy==="model"&&(k=x.model.localeCompare(v.model)),i.sortDir==="desc"?-k:k}),r}),d=I(()=>{const r=s.value,i=new Map,x=new Map;let v=0,k=0;for(const T of r)T.accepted&&v++,i.set(T.phase,(i.get(T.phase)??0)+1),x.set(T.model,(x.get(T.model)??0)+1),k+=T.systemPrompt.length+T.userPrompt.length+T.response.length;return{total:r.length,accepted:v,rejected:r.length-v,phaseBreakdown:i,modelBreakdown:x,estimatedBytes:k*2}}),t=I(()=>{const r=new Set;for(const i of s.value)for(const x of i.tags??[])r.add(x);return[...r].sort()}),a=I(()=>[...new Set(s.value.map(r=>r.model))].sort()),b=I(()=>[...new Set(s.value.map(r=>r.toolName))].sort());async function C(){l.value=!0;try{s.value=await P.getAllPairs()}catch(r){console.error("Failed to load training pairs:",r)}finally{l.value=!1}}async function M(r,i){await P.updatePairResponse(r,i);const x=s.value.find(v=>v.id===r);x&&(x.response=i)}async function U(r,i){await P.updatePairTags(r,i);const x=s.value.find(v=>v.id===r);x&&(x.tags=i)}async function y(r){const i=s.value.find(v=>v.id===r);if(!i)return;const x=!i.accepted;await P.updateAccepted(r,x),i.accepted=x}async function B(r){await P.deletePairs(r);const i=new Set(r);s.value=s.value.filter(x=>!i.has(x.id));for(const x of r)g.value.delete(x);o.value&&i.has(o.value)&&(o.value=null)}async function F(r,i){for(const x of r){await P.updateAccepted(x,i);const v=s.value.find(k=>k.id===x);v&&(v.accepted=i)}}async function K(r,i){for(const x of r){const v=s.value.find(T=>T.id===x);if(!v)continue;const k=[...v.tags??[]];k.includes(i)||(k.push(i),await P.updatePairTags(x,k),v.tags=k)}}function J(r){P.exportSelectedAsJsonl(r)}function O(r){const i=new Set(g.value);i.has(r)?i.delete(r):i.add(r),g.value=i}function W(){g.value=new Set(n.value.map(r=>r.id))}function q(){g.value=new Set}function G(r){o.value=o.value===r?null:r}return{pairs:s,loading:l,selectedIds:g,expandedId:o,filters:f,filteredPairs:n,stats:d,allTags:t,allModels:a,allToolNames:b,loadPairs:C,updateResponse:M,updateTags:U,toggleAccepted:y,deletePairs:B,bulkSetAccepted:F,bulkAddTag:K,exportSelected:J,toggleSelection:O,selectAll:W,deselectAll:q,setExpanded:G}}),oe={class:"grid grid-cols-2 gap-3 lg:grid-cols-4"},ae={class:"rounded-lg border border-border-default bg-surface-raised p-3 space-y-2"},le={class:"text-xl font-bold text-text-primary"},ne={class:"rounded-lg border border-border-default bg-surface-raised p-3 space-y-2"},re={class:"text-xl font-bold text-text-primary"},de={class:"flex items-center gap-2 text-[10px]"},ie={class:"text-success"},ue={class:"text-error"},ce={key:0,class:"h-1.5 rounded-full bg-surface-overlay overflow-hidden"},xe={class:"rounded-lg border border-border-default bg-surface-raised p-3 space-y-2"},pe={class:"flex flex-wrap gap-1.5"},me={class:"rounded-lg border border-border-default bg-surface-raised p-3 space-y-2"},ge={key:0,class:"space-y-1"},fe={class:"text-text-secondary truncate"},ve={class:"text-text-muted shrink-0"},be={key:1,class:"text-[10px] text-text-muted italic"},ye=D({__name:"TrainingDashboard",props:{stats:{}},setup(s){const l=s,g=I(()=>["draft","insights","automap","fix"].map(t=>({key:t,count:l.stats.phaseBreakdown.get(t)??0}))),o=I(()=>[...l.stats.modelBreakdown.entries()].sort((d,t)=>t[1]-d[1]).slice(0,3)),f=I(()=>l.stats.total>0?Math.round(l.stats.accepted/l.stats.total*100):0),n={draft:"bg-blue-500/20 text-blue-400",insights:"bg-amber-500/20 text-amber-400",automap:"bg-emerald-500/20 text-emerald-400",fix:"bg-rose-500/20 text-rose-400"};return(d,t)=>(c(),p("div",oe,[e("div",ae,[t[0]||(t[0]=e("p",{class:"text-[10px] text-text-muted uppercase tracking-wider"},"Training Pairs",-1)),e("p",le,m(s.stats.total),1),s.stats.estimatedBytes>0?(c(),R(te,{key:0,used:s.stats.estimatedBytes,total:s.stats.estimatedBytes*5,compact:"",label:`~${u(ee)(s.stats.estimatedBytes)} dataset`},null,8,["used","total","label"])):$("",!0)]),e("div",ne,[t[2]||(t[2]=e("p",{class:"text-[10px] text-text-muted uppercase tracking-wider"},"Acceptance Rate",-1)),e("p",re,m(f.value)+"%",1),e("div",de,[e("span",ie,m(s.stats.accepted)+" accepted",1),t[1]||(t[1]=e("span",{class:"text-text-muted"},"/",-1)),e("span",ue,m(s.stats.rejected)+" rejected",1)]),s.stats.total>0?(c(),p("div",ce,[e("div",{class:"h-full rounded-full bg-success transition-all duration-500",style:Q({width:`${f.value}%`})},null,4)])):$("",!0)]),e("div",xe,[t[3]||(t[3]=e("p",{class:"text-[10px] text-text-muted uppercase tracking-wider"},"By Phase",-1)),e("div",pe,[(c(!0),p(A,null,S(g.value,a=>(c(),p("span",{key:a.key,class:w(["rounded-full px-2 py-0.5 text-[10px] font-medium",n[a.key]])},m(a.key)+" "+m(a.count),3))),128))])]),e("div",me,[t[4]||(t[4]=e("p",{class:"text-[10px] text-text-muted uppercase tracking-wider"},"Top Models",-1)),o.value.length>0?(c(),p("div",ge,[(c(!0),p(A,null,S(o.value,([a,b])=>(c(),p("div",{key:a,class:"flex items-center justify-between text-[10px]"},[e("span",fe,m(a),1),e("span",ve,m(b),1)]))),128))])):(c(),p("p",be,"No data"))])]))}}),ke={class:"flex flex-wrap items-center gap-2"},he=["value"],we=["value"],$e=["value"],Ce=["value"],Te=["value"],Ae=["value"],Se={class:"flex rounded-lg border border-border-default overflow-hidden"},Pe=["value"],Ie=["value"],Be=["value"],De=["value"],Ne=["title"],je=D({__name:"TrainingFilters",props:{filters:{},models:{},toolNames:{},tags:{}},emits:["update:filters"],setup(s,{emit:l}){const g=s,o=l;function f(d){o("update:filters",{...g.filters,...d})}const n=[{value:"",label:"All phases"},{value:"draft",label:"Draft"},{value:"insights",label:"Insights"},{value:"automap",label:"Auto-map"},{value:"fix",label:"Fix"}];return(d,t)=>(c(),p("div",ke,[e("select",{value:s.filters.phase??"",class:"rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary outline-none focus:border-accent",onChange:t[0]||(t[0]=a=>f({phase:a.target.value||null}))},[(c(),p(A,null,S(n,a=>e("option",{key:a.label,value:a.value},m(a.label),9,we)),64))],40,he),e("select",{value:s.filters.model??"",class:"rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary outline-none focus:border-accent",onChange:t[1]||(t[1]=a=>f({model:a.target.value||null}))},[t[10]||(t[10]=e("option",{value:""},"All models",-1)),(c(!0),p(A,null,S(s.models,a=>(c(),p("option",{key:a,value:a},m(a),9,Ce))),128))],40,$e),e("select",{value:s.filters.toolName??"",class:"rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary outline-none focus:border-accent",onChange:t[2]||(t[2]=a=>f({toolName:a.target.value||null}))},[t[11]||(t[11]=e("option",{value:""},"All tools",-1)),(c(!0),p(A,null,S(s.toolNames,a=>(c(),p("option",{key:a,value:a},m(a),9,Ae))),128))],40,Te),e("div",Se,[e("button",{class:w(["px-2.5 py-1.5 text-[10px] transition-colors",s.filters.accepted===null?"bg-accent/10 text-accent":"bg-surface text-text-muted hover:text-text-primary"]),onClick:t[3]||(t[3]=a=>f({accepted:null}))},"All",2),e("button",{class:w(["px-2.5 py-1.5 text-[10px] transition-colors border-l border-border-default",s.filters.accepted===!0?"bg-success/10 text-success":"bg-surface text-text-muted hover:text-text-primary"]),onClick:t[4]||(t[4]=a=>f({accepted:!0}))},"Accepted",2),e("button",{class:w(["px-2.5 py-1.5 text-[10px] transition-colors border-l border-border-default",s.filters.accepted===!1?"bg-error/10 text-error":"bg-surface text-text-muted hover:text-text-primary"]),onClick:t[5]||(t[5]=a=>f({accepted:!1}))},"Rejected",2)]),s.tags.length>0?(c(),p("select",{key:0,value:s.filters.tag??"",class:"rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary outline-none focus:border-accent",onChange:t[6]||(t[6]=a=>f({tag:a.target.value||null}))},[t[12]||(t[12]=e("option",{value:""},"All tags",-1)),(c(!0),p(A,null,S(s.tags,a=>(c(),p("option",{key:a,value:a},m(a),9,Ie))),128))],40,Pe)):$("",!0),e("input",{value:s.filters.search,type:"text",placeholder:"Search prompts...",class:"flex-1 min-w-[150px] rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary placeholder-text-muted outline-none focus:border-accent",onInput:t[7]||(t[7]=a=>f({search:a.target.value}))},null,40,Be),e("select",{value:s.filters.sortBy,class:"rounded-lg border border-border-default bg-surface px-2.5 py-1.5 text-xs text-text-primary outline-none focus:border-accent",onChange:t[8]||(t[8]=a=>f({sortBy:a.target.value}))},[...t[13]||(t[13]=[e("option",{value:"timestamp"},"Sort by time",-1),e("option",{value:"phase"},"Sort by phase",-1),e("option",{value:"model"},"Sort by model",-1)])],40,De),e("button",{class:"rounded-lg border border-border-default bg-surface px-2 py-1.5 text-xs text-text-muted hover:text-text-primary transition-colors",title:s.filters.sortDir==="desc"?"Newest first":"Oldest first",onClick:t[9]||(t[9]=a=>f({sortDir:s.filters.sortDir==="desc"?"asc":"desc"}))},m(s.filters.sortDir==="desc"?"↓":"↑"),9,Ne)]))}}),Me={class:"flex flex-wrap items-center gap-1.5"},Re=["onClick"],Ee=D({__name:"TrainingTagEditor",props:{tags:{},allTags:{}},emits:["update:tags"],setup(s,{emit:l}){const g=l,o=h("");function f(d,t){if(d.key==="Enter"||d.key===","){d.preventDefault();const a=o.value.trim().toLowerCase();a&&!t.includes(a)&&g("update:tags",[...t,a]),o.value=""}}function n(d,t){g("update:tags",d.filter(a=>a!==t))}return(d,t)=>(c(),p("div",Me,[(c(!0),p(A,null,S(s.tags,a=>(c(),p("span",{key:a,class:"flex items-center gap-1 rounded-full bg-accent/10 px-2 py-0.5 text-[10px] text-accent"},[j(m(a)+" ",1),e("button",{class:"text-accent/60 hover:text-accent transition-colors",onClick:b=>n(s.tags,a)},[...t[2]||(t[2]=[e("svg",{class:"h-2.5 w-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3"},[e("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),e("line",{x1:"6",y1:"6",x2:"18",y2:"18"})],-1)])],8,Re)]))),128)),E(e("input",{"onUpdate:modelValue":t[0]||(t[0]=a=>o.value=a),type:"text",placeholder:"Add tag...",class:"w-20 bg-transparent text-[10px] text-text-primary placeholder-text-muted outline-none",onKeydown:t[1]||(t[1]=a=>f(a,s.tags))},null,544),[[L,o.value]])]))}}),Le={class:"rounded-lg border border-accent/30 bg-surface-raised p-4 space-y-4"},Ue={class:"flex items-center justify-between"},Ve={class:"flex items-center gap-2"},ze={class:"text-xs text-text-secondary"},Fe={class:"text-[10px] text-text-muted"},Ke={class:"text-[10px] text-text-muted"},Je={class:"flex items-center gap-2"},Oe={class:"max-h-32 overflow-auto rounded-lg bg-surface p-3 text-xs text-text-secondary whitespace-pre-wrap font-mono"},We={class:"max-h-32 overflow-auto rounded-lg bg-surface p-3 text-xs text-text-secondary whitespace-pre-wrap font-mono"},qe={key:0},Ge={class:"max-h-40 overflow-auto rounded-lg bg-accent/5 border border-accent/20 p-3 text-xs text-text-secondary whitespace-pre-wrap font-mono italic"},He={class:"mb-1 flex items-center justify-between"},Qe={key:1,class:"max-h-64 overflow-auto rounded-lg bg-surface p-3 text-xs text-text-secondary whitespace-pre-wrap font-mono"},Xe={key:2,class:"mt-2 flex gap-2"},Ye={class:"flex items-center justify-end border-t border-border-default pt-3"},Ze=D({__name:"TrainingDetailPanel",props:{pair:{},allTags:{}},emits:["close","update:response","update:tags","toggle-accepted","delete"],setup(s,{emit:l}){const g=s,o=l,f=h(!1),n=h(""),d=h(!1);function t(){n.value=g.pair.response,f.value=!0}function a(){o("update:response",g.pair.id,n.value),f.value=!1}function b(){f.value=!1}function C(){d.value?(o("delete",g.pair.id),d.value=!1):(d.value=!0,setTimeout(()=>{d.value=!1},3e3))}const M={draft:"bg-blue-500/20 text-blue-400",insights:"bg-amber-500/20 text-amber-400",automap:"bg-emerald-500/20 text-emerald-400",fix:"bg-rose-500/20 text-rose-400"};return(U,y)=>(c(),p("div",Le,[e("div",Ue,[e("div",Ve,[e("span",{class:w(["rounded-full px-2 py-0.5 text-[10px] font-medium",M[s.pair.phase]])},m(s.pair.phase),3),e("span",ze,m(s.pair.toolName),1),e("span",Fe,m(s.pair.model),1),e("span",Ke,m(u(z)(s.pair.timestamp)),1)]),e("div",Je,[e("button",{class:w(["rounded px-2 py-1 text-[10px] transition-colors",s.pair.accepted?"bg-success/10 text-success":"bg-error/10 text-error"]),onClick:y[0]||(y[0]=B=>o("toggle-accepted",s.pair.id))},m(s.pair.accepted?"Accepted":"Rejected"),3),e("button",{class:"text-text-muted hover:text-text-primary transition-colors text-xs",onClick:y[1]||(y[1]=B=>o("close"))}," ✕ ")])]),e("div",null,[y[4]||(y[4]=e("p",{class:"mb-1 text-[10px] font-medium uppercase tracking-wider text-text-muted"},"System Prompt",-1)),e("pre",Oe,m(s.pair.systemPrompt),1)]),e("div",null,[y[5]||(y[5]=e("p",{class:"mb-1 text-[10px] font-medium uppercase tracking-wider text-text-muted"},"User Prompt",-1)),e("pre",We,m(s.pair.userPrompt),1)]),s.pair.reasoning?(c(),p("div",qe,[y[6]||(y[6]=e("p",{class:"mb-1 text-[10px] font-medium uppercase tracking-wider text-accent"},"Reasoning",-1)),e("pre",Ge,m(s.pair.reasoning),1)])):$("",!0),e("div",null,[e("div",He,[y[7]||(y[7]=e("p",{class:"text-[10px] font-medium uppercase tracking-wider text-text-muted"},"AI Response",-1)),f.value?$("",!0):(c(),p("button",{key:0,class:"text-[10px] text-accent hover:underline",onClick:t}," Edit response "))]),f.value?E((c(),p("textarea",{key:0,"onUpdate:modelValue":y[2]||(y[2]=B=>n.value=B),rows:"8",class:"w-full rounded-lg border border-accent bg-surface px-3 py-2 text-xs text-text-primary font-mono outline-none resize-y"},null,512)),[[L,n.value]]):(c(),p("pre",Qe,m(s.pair.response),1)),f.value?(c(),p("div",Xe,[e("button",{class:"rounded-lg bg-accent px-3 py-1 text-xs text-white hover:bg-accent-hover transition-colors",onClick:a}," Save "),e("button",{class:"rounded-lg px-3 py-1 text-xs text-text-muted hover:text-text-primary transition-colors",onClick:b}," Cancel ")])):$("",!0)]),e("div",null,[y[8]||(y[8]=e("p",{class:"mb-1.5 text-[10px] font-medium uppercase tracking-wider text-text-muted"},"Tags",-1)),N(Ee,{tags:s.pair.tags??[],"all-tags":s.allTags,"onUpdate:tags":y[3]||(y[3]=B=>o("update:tags",s.pair.id,B))},null,8,["tags","all-tags"])]),e("div",Ye,[e("button",{class:w(["rounded-lg px-3 py-1 text-xs transition-colors",d.value?"bg-error/10 text-error":"text-text-muted hover:text-error"]),onClick:C},m(d.value?"Confirm delete?":"Delete pair"),3)])]))}}),_e={key:0,class:"rounded-lg bg-surface-overlay p-8 text-center"},et={key:1,class:"space-y-1"},tt=["onClick"],st=["onClick"],ot={key:0,class:"text-[8px]"},at={class:"shrink-0 text-text-secondary w-24 truncate"},lt={class:"shrink-0 text-text-muted w-28 truncate"},nt={class:"flex items-center gap-1 shrink-0"},rt={key:0,class:"text-[8px] text-text-muted"},dt={class:"flex-1 min-w-0 truncate text-text-muted"},it={class:"shrink-0 text-[10px] text-text-muted"},ut=D({__name:"TrainingTable",props:{pairs:{},selectedIds:{},expandedId:{},allTags:{}},emits:["toggle-selection","set-expanded","update:response","update:tags","toggle-accepted","delete"],setup(s,{emit:l}){const g=l,o={draft:"bg-blue-500/20 text-blue-400",insights:"bg-amber-500/20 text-amber-400",automap:"bg-emerald-500/20 text-emerald-400",fix:"bg-rose-500/20 text-rose-400"};return(f,n)=>s.pairs.length===0?(c(),p("div",_e,[...n[5]||(n[5]=[e("p",{class:"text-sm text-text-muted"},"No training pairs match your filters.",-1)])])):(c(),p("div",et,[(c(!0),p(A,null,S(s.pairs,d=>(c(),p("div",{key:d.id},[e("div",{class:w(["flex items-center gap-3 rounded-lg border border-border-default bg-surface-raised px-3 py-2.5 text-xs transition-colors cursor-pointer hover:border-accent/30",s.expandedId===d.id?"border-accent/50":""]),onClick:t=>g("set-expanded",d.id)},[e("button",{class:w(["flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",s.selectedIds.has(d.id)?"border-accent bg-accent text-white":"border-border-default hover:border-accent"]),onClick:X(t=>g("toggle-selection",d.id),["stop"])},[s.selectedIds.has(d.id)?(c(),p("span",ot,"✓")):$("",!0)],10,st),e("span",{class:w(["shrink-0 rounded-full px-2 py-0.5 text-[9px] font-medium",o[d.phase]])},m(d.phase),3),e("span",at,m(d.toolName),1),e("span",lt,m(d.model),1),e("span",{class:w(["shrink-0 rounded-full px-1.5 py-0.5 text-[9px]",d.accepted?"bg-success/10 text-success":"bg-error/10 text-error"])},m(d.accepted?"accepted":"rejected"),3),e("div",nt,[(c(!0),p(A,null,S((d.tags??[]).slice(0,2),t=>(c(),p("span",{key:t,class:"rounded-full bg-accent/10 px-1.5 py-0.5 text-[8px] text-accent"},m(t),1))),128)),(d.tags??[]).length>2?(c(),p("span",rt,"+"+m((d.tags??[]).length-2),1)):$("",!0)]),e("span",dt,m(d.userPrompt.slice(0,80))+m(d.userPrompt.length>80?"...":""),1),e("span",it,m(u(z)(d.timestamp)),1)],10,tt),s.expandedId===d.id?(c(),R(Ze,{key:0,pair:d,"all-tags":s.allTags,class:"mt-1 ml-7",onClose:n[0]||(n[0]=t=>g("set-expanded",null)),"onUpdate:response":n[1]||(n[1]=(t,a)=>g("update:response",t,a)),"onUpdate:tags":n[2]||(n[2]=(t,a)=>g("update:tags",t,a)),onToggleAccepted:n[3]||(n[3]=t=>g("toggle-accepted",t)),onDelete:n[4]||(n[4]=t=>g("delete",t))},null,8,["pair","all-tags"])):$("",!0)]))),128))]))}}),ct={class:"flex items-center gap-2 rounded-lg border border-accent/30 bg-surface-raised px-4 py-2.5"},xt={class:"text-xs font-medium text-accent"},pt={class:"ml-auto flex items-center gap-2"},mt={key:0,class:"flex items-center gap-1"},gt=D({__name:"TrainingBulkActions",props:{selectedCount:{}},emits:["export","mark-accepted","mark-rejected","add-tag","delete","deselect-all"],setup(s,{emit:l}){const g=l,o=h(!1),f=h(""),n=h(!1);function d(){const a=f.value.trim().toLowerCase();a&&(g("add-tag",a),f.value="",o.value=!1)}function t(){n.value?(g("delete"),n.value=!1):(n.value=!0,setTimeout(()=>{n.value=!1},3e3))}return(a,b)=>(c(),p("div",ct,[e("span",xt,m(s.selectedCount)+" selected",1),e("div",pt,[e("button",{class:"rounded-lg bg-surface-overlay px-3 py-1 text-[10px] text-text-secondary hover:text-text-primary transition-colors",onClick:b[0]||(b[0]=C=>g("export"))}," Export JSONL "),e("button",{class:"rounded-lg bg-success/10 px-3 py-1 text-[10px] text-success hover:bg-success/20 transition-colors",onClick:b[1]||(b[1]=C=>g("mark-accepted"))}," Mark Accepted "),e("button",{class:"rounded-lg bg-error/10 px-3 py-1 text-[10px] text-error hover:bg-error/20 transition-colors",onClick:b[2]||(b[2]=C=>g("mark-rejected"))}," Mark Rejected "),o.value?(c(),p("div",mt,[E(e("input",{"onUpdate:modelValue":b[3]||(b[3]=C=>f.value=C),type:"text",placeholder:"Tag name...",class:"w-24 rounded border border-accent bg-surface px-2 py-0.5 text-[10px] text-text-primary outline-none",onKeydown:[V(d,["enter"]),b[4]||(b[4]=V(C=>o.value=!1,["escape"]))]},null,544),[[L,f.value]]),e("button",{class:"text-[10px] text-accent hover:underline",onClick:d},"Add")])):(c(),p("button",{key:1,class:"rounded-lg bg-accent/10 px-3 py-1 text-[10px] text-accent hover:bg-accent/20 transition-colors",onClick:b[5]||(b[5]=C=>o.value=!0)}," Add Tag ")),e("button",{class:w(["rounded-lg px-3 py-1 text-[10px] transition-colors",n.value?"bg-error/10 text-error":"text-text-muted hover:text-error"]),onClick:t},m(n.value?"Confirm?":"Delete"),3),e("button",{class:"text-[10px] text-text-muted hover:text-text-primary transition-colors",onClick:b[6]||(b[6]=C=>g("deselect-all"))}," Deselect ")])]))}}),ft={class:"mx-auto max-w-6xl space-y-6"},vt={key:1,class:"flex items-center gap-3"},bt={class:"text-[10px] text-text-muted"},yt={key:2,class:"rounded-lg border border-border-default bg-surface-raised p-8 text-center"},kt={class:"text-xs text-text-muted"},Tt=D({__name:"AITrainingPage",setup(s){const l=se();return Y(()=>{l.loadPairs()}),(g,o)=>{const f=_("RouterLink");return c(),p("div",ft,[o[18]||(o[18]=e("div",null,[e("h2",{class:"text-lg font-semibold text-text-primary"},"AI Training"),e("p",{class:"text-sm text-text-muted"},"Browse, curate, and export your training data from the Tool Workshop.")],-1)),N(ye,{stats:u(l).stats},null,8,["stats"]),N(je,{filters:u(l).filters,models:u(l).allModels,"tool-names":u(l).allToolNames,tags:u(l).allTags,"onUpdate:filters":o[0]||(o[0]=n=>u(l).filters=n)},null,8,["filters","models","tool-names","tags"]),u(l).selectedIds.size>0?(c(),R(gt,{key:0,"selected-count":u(l).selectedIds.size,onExport:o[1]||(o[1]=n=>u(l).exportSelected([...u(l).selectedIds])),onMarkAccepted:o[2]||(o[2]=n=>u(l).bulkSetAccepted([...u(l).selectedIds],!0)),onMarkRejected:o[3]||(o[3]=n=>u(l).bulkSetAccepted([...u(l).selectedIds],!1)),onAddTag:o[4]||(o[4]=n=>u(l).bulkAddTag([...u(l).selectedIds],n)),onDelete:o[5]||(o[5]=n=>u(l).deletePairs([...u(l).selectedIds])),onDeselectAll:o[6]||(o[6]=n=>u(l).deselectAll())},null,8,["selected-count"])):$("",!0),u(l).filteredPairs.length>0?(c(),p("div",vt,[e("button",{class:"text-[10px] text-text-muted hover:text-accent transition-colors",onClick:o[7]||(o[7]=n=>u(l).selectedIds.size===u(l).filteredPairs.length?u(l).deselectAll():u(l).selectAll())},m(u(l).selectedIds.size===u(l).filteredPairs.length?"Deselect all":`Select all ${u(l).filteredPairs.length}`),1),e("span",bt,m(u(l).filteredPairs.length)+" of "+m(u(l).pairs.length)+" pairs shown ",1)])):$("",!0),N(ut,{pairs:u(l).filteredPairs,"selected-ids":u(l).selectedIds,"expanded-id":u(l).expandedId,"all-tags":u(l).allTags,onToggleSelection:o[8]||(o[8]=n=>u(l).toggleSelection(n)),onSetExpanded:o[9]||(o[9]=n=>u(l).setExpanded(n)),"onUpdate:response":o[10]||(o[10]=(n,d)=>u(l).updateResponse(n,d)),"onUpdate:tags":o[11]||(o[11]=(n,d)=>u(l).updateTags(n,d)),onToggleAccepted:o[12]||(o[12]=n=>u(l).toggleAccepted(n)),onDelete:o[13]||(o[13]=n=>u(l).deletePairs([n]))},null,8,["pairs","selected-ids","expanded-id","all-tags"]),u(l).pairs.length===0&&!u(l).loading?(c(),p("div",yt,[o[17]||(o[17]=e("p",{class:"text-sm text-text-muted mb-2"},"No training data collected yet.",-1)),e("p",kt,[o[15]||(o[15]=j(" Training pairs are generated automatically when you use AI features in the ",-1)),N(f,{to:"/tools",class:"text-accent hover:underline"},{default:Z(()=>[...o[14]||(o[14]=[j("Tool Workshop",-1)])]),_:1}),o[16]||(o[16]=j(" (draft generation, code analysis, auto-mapping, and AI fix). ",-1))])])):$("",!0)])}}});export{Tt as default};
@@ -1 +0,0 @@
1
- import{d as X,r as C,c as k,n as j,a as F,z as Y,K,A as ee,e as v,f as t,i as I,h as T,F as w,j as $,t as y,b as m,u as z,g as M,p as P,m as D,w as te,B as O,E as V,k as A,C as se}from"./index-BqB3FY2M.js";import{u as oe}from"./toolcall-store-BumXt8DE.js";import{s as ne}from"./generate-service-mPYQA7Xh.js";import{u as Z}from"./metrics-store-HzdMIV8O.js";import{c as le,a as re}from"./format-BqVZ9rwM.js";import{_ as H,b as N}from"./StatusBadge.vue_vue_type_script_setup_true_lang-f9O-U2FX.js";import{_ as ae}from"./TokenStreamDisplay.vue_vue_type_script_setup_true_lang-CJW7ndOY.js";import{D as ue}from"./base-CrPFMexR.js";import"./stream-handler-29OjEvbo.js";import"./agent-store-_RIMRfEn.js";const ie=X("comparison",()=>{const o=C(new Map),e=C(null),s=k(()=>e.value?o.value.get(e.value)??null:null);function n(c,i){const f=j(),g=i.map(p=>({slotId:p.slotId,model:p.model,label:p.label,sessionId:"",status:"idle",outputText:"",metrics:null}));return o.value.set(f,{id:f,prompt:c,slots:i,createdAt:Date.now(),status:"running",executions:g}),e.value=f,f}function r(c,i,f){const g=o.value.get(c);if(!g)return;const p=g.executions.find(b=>b.slotId===i);p&&Object.assign(p,f)}function u(c){const i=o.value.get(c);if(i){const f=i.executions.every(g=>g.status==="completed"||g.status==="error");i.status=f?"completed":"partial"}}function a(c,i){return o.value.get(c)?.executions.find(f=>f.slotId===i)}return{runs:o,activeRunId:e,activeRun:s,createRun:n,updateExecution:r,finalizeRun:u,getExecution:a}});function de(o,e){const s=e.filter(c=>c.model===o.model);if(s.length<=1)return o.model;if(new Set(s.map(c=>c.options.temperature??.7)).size===s.length)return`${o.model} @ ${(o.options.temperature??.7).toFixed(2)}`;if(new Set(s.map(c=>c.system)).size===s.length&&o.system){const c=o.system.split(/\s+/)[0]??"",i=c.length>12?c.slice(0,12)+"...":c;return`${o.model} (${i})`}if(new Set(s.map(c=>c.options.seed)).size===s.length&&o.options.seed!=null)return`${o.model} seed:${o.options.seed}`;const a=s.findIndex(c=>c.slotId===o.slotId);return`${o.model} #${a+1}`}const ce={class:"rounded-lg border border-border-default bg-surface-raised p-4 space-y-4"},pe={class:"flex items-center justify-between"},xe={class:"flex items-center gap-2"},me={class:"group relative"},fe={class:"group relative"},ve={class:"flex items-center gap-3"},ge={class:"flex items-center justify-center h-5 w-5 rounded-full bg-surface-overlay text-[10px] font-bold text-text-secondary shrink-0"},be=["value","onChange"],he=["value"],ye=["onClick"],_e={class:"flex items-center gap-2"},ke=["onClick"],we={class:"text-[10px] text-text-muted"},Ie={key:0,class:"space-y-3 pt-1 border-t border-border-default/50"},$e=["value","onInput"],Ce={class:"flex items-center justify-between mb-1"},Se={class:"text-[11px] text-text-primary font-medium"},Me=["value","onInput"],Te={class:"flex items-center justify-between mb-1"},Pe={class:"text-[11px] text-text-primary font-medium"},Fe=["value","onInput"],We=["value","onInput"],Ee={class:"text-[11px]"},De={class:"mt-2 space-y-2"},Re={class:"flex items-center gap-2"},je=["value","onInput"],ze={class:"flex items-center gap-2"},Ae=["value","onInput"],Ne={class:"flex items-center gap-2"},Oe=["value","onChange"],Le={class:"flex items-center gap-2"},Be=["value","onInput"],Ve={class:"flex items-center gap-2"},Je=["value","onInput"],Ue={key:0,class:"rounded-lg border border-dashed border-border-default py-8 text-center space-y-3"},Ge=F({__name:"ComparisonSlotConfigurator",props:{slots:{default:()=>[]},slotsModifiers:{}},emits:["update:slots"],setup(o){const e=Y(),s=K(o,"slots"),n=C({});function r(){if(s.value.length>=4)return;const d=e.chatModelNames[0]??"",l={slotId:j(),model:d,label:"",system:"",options:{temperature:.7}},x=[...s.value,l];s.value=f(x)}function u(d){delete n.value[d];const l=s.value.filter(x=>x.slotId!==d);s.value=f(l)}function a(){n.value={},s.value=[]}function c(d,l){const x=s.value.map(_=>_.slotId===d?{..._,...l}:_);s.value=f(x)}function i(d,l){const x=s.value.map(_=>_.slotId===d?{..._,options:{..._.options,...l}}:_);s.value=f(x)}function f(d){return d.map(l=>({...l,label:de(l,d)}))}function g(d){n.value[d]=!n.value[d]}function p(d){const l=e.chatModelNames[0]??"";if(!l)return;let x;if(d==="temp-sweep")x=[.2,.7,1.2].map(_=>({slotId:j(),model:l,label:"",system:"",options:{temperature:_}}));else{const _=Math.floor(Math.random()*1e5);x=[.3,1].map(h=>({slotId:j(),model:l,label:"",system:"",options:{temperature:h,seed:_}}))}s.value=f(x)}function b(d){const l=[],x=d.options.temperature;return x!=null&&l.push(`temp ${x.toFixed(2)}`),d.options.top_p!=null&&l.push(`top_p ${d.options.top_p}`),d.options.seed!=null&&l.push(`seed ${d.options.seed}`),d.system&&l.push("system prompt"),l.join(", ")||"defaults"}return ee(async()=>{e.models.length===0&&await e.fetchModels()}),(d,l)=>(m(),v("div",ce,[t("div",pe,[l[2]||(l[2]=t("div",null,[t("h3",{class:"text-sm font-medium text-text-primary"},"Comparison Slots"),t("p",{class:"text-[11px] text-text-muted mt-0.5"}," Each slot is a model + settings combination. Add the same model multiple times with different settings to compare behavior. ")],-1)),s.value.length>0?(m(),v("button",{key:0,class:"rounded-md border border-border-default px-2.5 py-1 text-[11px] text-text-muted hover:border-error hover:text-error transition-colors shrink-0 self-start",onClick:a}," Clear All ")):I("",!0)]),t("div",xe,[l[5]||(l[5]=t("span",{class:"text-[11px] text-text-muted"},"Quick start:",-1)),t("div",me,[t("button",{class:"rounded-md border border-border-default px-2.5 py-1 text-[11px] text-text-secondary hover:border-accent hover:text-text-primary transition-colors",onClick:l[0]||(l[0]=x=>p("temp-sweep"))}," Temperature Sweep "),l[3]||(l[3]=t("div",{class:"pointer-events-none absolute left-0 top-full z-10 mt-1.5 w-64 rounded-lg border border-border-default bg-surface-raised p-3 text-xs text-text-secondary opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100"},[t("p",{class:"font-medium text-text-primary mb-1"},"Temperature Sweep"),t("p",null,[T("Creates 3 slots of the same model at temperatures "),t("strong",null,"0.2"),T(" (focused), "),t("strong",null,"0.7"),T(" (balanced), and "),t("strong",null,"1.2"),T(" (creative). See how temperature changes the output for the exact same prompt.")])],-1))]),t("div",fe,[t("button",{class:"rounded-md border border-border-default px-2.5 py-1 text-[11px] text-text-secondary hover:border-accent hover:text-text-primary transition-colors",onClick:l[1]||(l[1]=x=>p("deterministic-pair"))}," Deterministic Pair "),l[4]||(l[4]=t("div",{class:"pointer-events-none absolute left-0 top-full z-10 mt-1.5 w-64 rounded-lg border border-border-default bg-surface-raised p-3 text-xs text-text-secondary opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100"},[t("p",{class:"font-medium text-text-primary mb-1"},"Deterministic Pair"),t("p",null,[T("Creates 2 slots of the same model with the "),t("strong",null,"same seed"),T(" but different temperatures (0.3 and 1.0). The shared seed means any difference in the output is purely from temperature, not randomness.")])],-1))])]),(m(!0),v(w,null,$(s.value,(x,_)=>(m(),v("div",{key:x.slotId,class:"rounded-lg border border-border-default bg-surface p-3 space-y-2"},[t("div",ve,[t("span",ge,y(_+1),1),t("select",{value:x.model,class:"flex-1 rounded-lg border border-border-default bg-surface-raised px-3 py-1.5 text-sm text-text-primary focus:border-accent focus:outline-none",onChange:h=>c(x.slotId,{model:h.target.value})},[(m(!0),v(w,null,$(z(e).chatModelNames,h=>(m(),v("option",{key:h,value:h},y(h)+" "+y(z(e).capabilityIcons(h)),9,he))),128))],40,be),t("button",{class:"rounded-md p-1 text-text-muted hover:text-error transition-colors",title:"Remove slot",onClick:h=>u(x.slotId)},[...l[6]||(l[6]=[t("svg",{class:"h-4 w-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("path",{d:"M18 6L6 18M6 6l12 12"})],-1)])],8,ye)]),t("div",_e,[t("button",{class:"flex items-center gap-1.5 text-[11px] text-text-secondary hover:text-text-primary transition-colors",onClick:h=>g(x.slotId)},[(m(),v("svg",{class:M(["h-3 w-3 transition-transform",n.value[x.slotId]?"rotate-90":""]),viewBox:"0 0 24 24",fill:"currentColor"},[...l[7]||(l[7]=[t("path",{d:"M8 5l8 7-8 7z"},null,-1)])],2)),l[8]||(l[8]=T(" Settings ",-1))],8,ke),t("span",we,y(b(x)),1)]),n.value[x.slotId]?(m(),v("div",Ie,[t("div",null,[l[9]||(l[9]=t("label",{class:"text-[11px] text-text-muted block mb-1"},"System Prompt",-1)),t("textarea",{value:x.system,rows:"2",class:"w-full rounded-md border border-border-default bg-surface-raised px-2.5 py-1.5 text-xs text-text-primary placeholder-text-muted focus:border-accent focus:outline-none resize-none",placeholder:"Optional system prompt...",onInput:h=>c(x.slotId,{system:h.target.value})},null,40,$e)]),t("div",null,[t("div",Ce,[l[10]||(l[10]=t("label",{class:"text-[11px] text-text-muted"},"Temperature",-1)),t("span",Se,y((x.options.temperature??.7).toFixed(1)),1)]),t("input",{type:"range",min:"0",max:"2",step:"0.1",value:x.options.temperature??.7,class:"w-full",onInput:h=>i(x.slotId,{temperature:parseFloat(h.target.value)})},null,40,Me)]),t("div",null,[t("div",Te,[l[11]||(l[11]=t("label",{class:"text-[11px] text-text-muted"},"Top-P",-1)),t("span",Pe,y((x.options.top_p??.9).toFixed(2)),1)]),t("input",{type:"range",min:"0",max:"1",step:"0.05",value:x.options.top_p??.9,class:"w-full",onInput:h=>i(x.slotId,{top_p:parseFloat(h.target.value)})},null,40,Fe)]),t("div",null,[l[12]||(l[12]=t("label",{class:"text-[11px] text-text-muted block mb-1"},"Seed",-1)),t("input",{type:"number",value:x.options.seed??"",class:"w-full rounded-md border border-border-default bg-surface-raised px-2.5 py-1.5 text-xs text-text-primary placeholder-text-muted focus:border-accent focus:outline-none",placeholder:"Random (leave empty)",onInput:h=>i(x.slotId,{seed:h.target.value?parseInt(h.target.value,10):void 0})},null,40,We)]),t("details",Ee,[l[19]||(l[19]=t("summary",{class:"text-text-muted cursor-pointer hover:text-text-secondary"},"Advanced",-1)),t("div",De,[t("div",Re,[l[13]||(l[13]=t("label",{class:"text-text-muted w-24 shrink-0"},"Top-K",-1)),t("input",{type:"number",value:x.options.top_k??"",class:"flex-1 rounded-md border border-border-default bg-surface-raised px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none",placeholder:"40",onInput:h=>i(x.slotId,{top_k:h.target.value?parseInt(h.target.value,10):void 0})},null,40,je)]),t("div",ze,[l[14]||(l[14]=t("label",{class:"text-text-muted w-24 shrink-0"},"Repeat Penalty",-1)),t("input",{type:"number",step:"0.1",value:x.options.repeat_penalty??"",class:"flex-1 rounded-md border border-border-default bg-surface-raised px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none",placeholder:"1.1",onInput:h=>i(x.slotId,{repeat_penalty:h.target.value?parseFloat(h.target.value):void 0})},null,40,Ae)]),t("div",Ne,[l[16]||(l[16]=t("label",{class:"text-text-muted w-24 shrink-0"},"Mirostat",-1)),t("select",{value:x.options.mirostat??0,class:"flex-1 rounded-md border border-border-default bg-surface-raised px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none",onChange:h=>i(x.slotId,{mirostat:parseInt(h.target.value,10)||void 0})},[...l[15]||(l[15]=[t("option",{value:0},"Off",-1),t("option",{value:1},"Mirostat 1",-1),t("option",{value:2},"Mirostat 2",-1)])],40,Oe)]),t("div",Le,[l[17]||(l[17]=t("label",{class:"text-text-muted w-24 shrink-0"},"Max Tokens",-1)),t("input",{type:"number",value:x.options.num_predict??"",class:"flex-1 rounded-md border border-border-default bg-surface-raised px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none",placeholder:"Default",onInput:h=>i(x.slotId,{num_predict:h.target.value?parseInt(h.target.value,10):void 0})},null,40,Be)]),t("div",Ve,[l[18]||(l[18]=t("label",{class:"text-text-muted w-24 shrink-0"},"Context Length",-1)),t("input",{type:"number",value:x.options.num_ctx??"",class:"flex-1 rounded-md border border-border-default bg-surface-raised px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none",placeholder:"Default",onInput:h=>i(x.slotId,{num_ctx:h.target.value?parseInt(h.target.value,10):void 0})},null,40,Je)])])])])):I("",!0)]))),128)),s.value.length===0?(m(),v("div",Ue,[l[20]||(l[20]=t("p",{class:"text-sm text-text-secondary"},"No slots configured yet",-1)),l[21]||(l[21]=t("p",{class:"text-xs text-text-muted max-w-sm mx-auto"}," Add a slot to pick a model and settings, or use a quick-start preset above to get going. ",-1)),t("button",{class:"rounded-lg bg-accent px-4 py-2 text-sm font-medium text-surface hover:bg-accent-hover transition-colors",onClick:r}," + Add First Slot ")])):s.value.length<4?(m(),v("button",{key:1,class:"w-full rounded-lg border border-dashed border-border-default py-2.5 text-sm text-text-muted hover:border-accent hover:text-text-primary transition-colors",onClick:r}," + Add Slot ("+y(s.value.length)+"/4) ",1)):I("",!0)]))}}),qe={class:"rounded-lg border border-border-default bg-surface-raised overflow-hidden"},Qe={class:"border-b border-border-default px-4 py-3 space-y-1"},Ze={class:"flex items-center justify-between"},He={class:"text-sm font-semibold text-text-primary"},Xe={key:0,class:"flex flex-wrap gap-1"},Ye={class:"p-4 space-y-3"},Ke={key:1,class:"grid grid-cols-3 gap-2"},et=F({__name:"ComparisonColumn",props:{execution:{},slotConfig:{}},setup(o){const e=o,s=Z(),n=k(()=>e.execution.sessionId?s.getMetrics(e.execution.sessionId):null),r=k(()=>e.execution.label||e.execution.model),u=k(()=>{if(!e.slotConfig)return[];const a=[],c=e.slotConfig.options;return c.temperature!=null&&a.push(`temp ${c.temperature.toFixed(1)}`),c.top_p!=null&&a.push(`top_p ${c.top_p}`),c.seed!=null&&a.push(`seed ${c.seed}`),e.slotConfig.system&&a.push("sys prompt"),a});return(a,c)=>(m(),v("div",qe,[t("div",Qe,[t("div",Ze,[t("span",He,y(r.value),1),P(H,{status:o.execution.status},null,8,["status"])]),u.value.length>0?(m(),v("div",Xe,[(m(!0),v(w,null,$(u.value,i=>(m(),v("span",{key:i,class:"rounded-full bg-surface-overlay px-2 py-0.5 text-[10px] text-text-muted"},y(i),1))),128))])):I("",!0)]),t("div",Ye,[o.execution.sessionId?(m(),D(ae,{key:0,"session-id":o.execution.sessionId},null,8,["session-id"])):I("",!0),n.value?(m(),v("div",Ke,[P(N,{label:"TTFT",value:z(le)(n.value.ttftMs)},null,8,["value"]),P(N,{label:"Speed",value:z(re)(n.value.tokensPerSecond)},null,8,["value"]),P(N,{label:"Tokens",value:n.value.completionTokenCount},null,8,["value"])])):I("",!0)])]))}}),tt=F({__name:"ComparisonGrid",props:{executions:{},slots:{}},setup(o){const e=o;function s(n){return e.slots.find(r=>r.slotId===n.slotId)}return(n,r)=>(m(),v("div",{class:M(["grid gap-4",{"grid-cols-1":o.executions.length===1,"grid-cols-2":o.executions.length===2,"grid-cols-2 xl:grid-cols-3":o.executions.length===3,"grid-cols-2 xl:grid-cols-4":o.executions.length>=4}])},[(m(!0),v(w,null,$(o.executions,u=>(m(),D(et,{key:u.slotId,execution:u,"slot-config":s(u)},null,8,["execution","slot-config"]))),128))],2))}});function J(o,e){let s;for(s=0;s<o.length&&s<e.length;s++)if(o[s]!=e[s])return o.slice(0,s);return o.slice(0,s)}function U(o,e){let s;if(!o||!e||o[o.length-1]!=e[e.length-1])return"";for(s=0;s<o.length&&s<e.length;s++)if(o[o.length-(s+1)]!=e[e.length-(s+1)])return o.slice(-s);return o.slice(-s)}function L(o,e,s){if(o.slice(0,e.length)!=e)throw Error(`string ${JSON.stringify(o)} doesn't start with prefix ${JSON.stringify(e)}; this is a bug`);return s+o.slice(e.length)}function B(o,e,s){if(!e)return o+s;if(o.slice(-e.length)!=e)throw Error(`string ${JSON.stringify(o)} doesn't end with suffix ${JSON.stringify(e)}; this is a bug`);return o.slice(0,-e.length)+s}function W(o,e){return L(o,e,"")}function R(o,e){return B(o,e,"")}function G(o,e){return e.slice(0,st(o,e))}function st(o,e){let s=0;o.length>e.length&&(s=o.length-e.length);let n=e.length;o.length<e.length&&(n=o.length);const r=Array(n);let u=0;r[0]=0;for(let a=1;a<n;a++){for(e[a]==e[u]?r[a]=r[u]:r[a]=u;u>0&&e[a]!=e[u];)u=r[u];e[a]==e[u]&&u++}u=0;for(let a=s;a<o.length;a++){for(;u>0&&o[a]!=e[u];)u=r[u];o[a]==e[u]&&u++}return u}function E(o){let e;for(e=o.length-1;e>=0&&o[e].match(/\s/);e--);return o.substring(e+1)}function S(o){const e=o.match(/^\s*/);return e?e[0]:""}const q="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}",ot=new RegExp(`[${q}]+|\\s+|[^${q}]`,"ug");class nt extends ue{equals(e,s,n){return n.ignoreCase&&(e=e.toLowerCase(),s=s.toLowerCase()),e.trim()===s.trim()}tokenize(e,s={}){let n;if(s.intlSegmenter){const a=s.intlSegmenter;if(a.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');n=[];for(const c of Array.from(a.segment(e))){const i=c.segment;n.length&&/\s/.test(n[n.length-1])&&/\s/.test(i)?n[n.length-1]+=i:n.push(i)}}else n=e.match(ot)||[];const r=[];let u=null;return n.forEach(a=>{/\s/.test(a)?u==null?r.push(a):r.push(r.pop()+a):u!=null&&/\s/.test(u)?r[r.length-1]==u?r.push(r.pop()+a):r.push(u+a):r.push(a),u=a}),r}join(e){return e.map((s,n)=>n==0?s:s.replace(/^\s+/,"")).join("")}postProcess(e,s){if(!e||s.oneChangePerToken)return e;let n=null,r=null,u=null;return e.forEach(a=>{a.added?r=a:a.removed?u=a:((r||u)&&Q(n,u,r,a),n=a,r=null,u=null)}),(r||u)&&Q(n,u,r,null),e}}const lt=new nt;function rt(o,e,s){return lt.diff(o,e,s)}function Q(o,e,s,n){if(e&&s){const r=S(e.value),u=E(e.value),a=S(s.value),c=E(s.value);if(o){const i=J(r,a);o.value=B(o.value,a,i),e.value=W(e.value,i),s.value=W(s.value,i)}if(n){const i=U(u,c);n.value=L(n.value,c,i),e.value=R(e.value,i),s.value=R(s.value,i)}}else if(s){if(o){const r=S(s.value);s.value=s.value.substring(r.length)}if(n){const r=S(n.value);n.value=n.value.substring(r.length)}}else if(o&&n){const r=S(n.value),u=S(e.value),a=E(e.value),c=J(r,u);e.value=W(e.value,c);const i=U(W(r,c),a);e.value=R(e.value,i),n.value=L(n.value,r,i),o.value=B(o.value,r,r.slice(0,r.length-i.length))}else if(n){const r=S(n.value),u=E(e.value),a=G(u,r);e.value=R(e.value,a)}else if(o){const r=E(o.value),u=S(e.value),a=G(r,u);e.value=W(e.value,a)}}const at={class:"rounded-lg border border-border-default bg-surface-raised p-4 space-y-3"},ut={key:0,class:"text-sm text-text-muted text-center py-4"},it={key:0,class:"flex items-center gap-3 text-sm"},dt=["value","disabled"],ct=["value","disabled"],pt={class:"flex items-center gap-4 text-[11px]"},xt={class:"flex items-center gap-1.5"},mt={class:"text-text-muted"},ft={class:"flex items-center gap-1.5"},vt={class:"text-text-muted"},gt={class:"rounded-md border border-border-default bg-surface p-3 text-sm leading-relaxed max-h-96 overflow-y-auto"},bt=F({__name:"ComparisonDiffView",props:{executions:{}},setup(o){const e=o,s=k(()=>e.executions.filter(i=>i.status==="completed"&&i.outputText)),n=C(0),r=C(1);te(s,i=>{i.length>=2&&(n.value=0,r.value=1)},{immediate:!0});const u=k(()=>{const i=s.value[n.value],f=s.value[r.value];if(!i||!f)return[];const g=i.outputText.replace(/<think>[\s\S]*?<\/think>/g,"").trim(),p=f.outputText.replace(/<think>[\s\S]*?<\/think>/g,"").trim();return rt(g,p)}),a=k(()=>s.value[n.value]?.label||s.value[n.value]?.model||""),c=k(()=>s.value[r.value]?.label||s.value[r.value]?.model||"");return(i,f)=>(m(),v("div",at,[s.value.length<2?(m(),v("div",ut," Need at least 2 completed results to show a diff. ")):(m(),v(w,{key:1},[s.value.length>2?(m(),v("div",it,[f[2]||(f[2]=t("span",{class:"text-text-muted text-xs"},"Compare:",-1)),O(t("select",{"onUpdate:modelValue":f[0]||(f[0]=g=>n.value=g),class:"rounded-md border border-border-default bg-surface px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none"},[(m(!0),v(w,null,$(s.value,(g,p)=>(m(),v("option",{key:g.slotId,value:p,disabled:p===r.value},y(g.label||g.model),9,dt))),128))],512),[[V,n.value,void 0,{number:!0}]]),f[3]||(f[3]=t("span",{class:"text-text-muted text-xs"},"vs",-1)),O(t("select",{"onUpdate:modelValue":f[1]||(f[1]=g=>r.value=g),class:"rounded-md border border-border-default bg-surface px-2 py-1 text-xs text-text-primary focus:border-accent focus:outline-none"},[(m(!0),v(w,null,$(s.value,(g,p)=>(m(),v("option",{key:g.slotId,value:p,disabled:p===n.value},y(g.label||g.model),9,ct))),128))],512),[[V,r.value,void 0,{number:!0}]])])):I("",!0),t("div",pt,[t("div",xt,[f[4]||(f[4]=t("span",{class:"inline-block h-2.5 w-2.5 rounded-sm bg-success/30"},null,-1)),t("span",mt,y(a.value)+" only",1)]),t("div",ft,[f[5]||(f[5]=t("span",{class:"inline-block h-2.5 w-2.5 rounded-sm bg-error/30"},null,-1)),t("span",vt,y(c.value)+" only",1)])]),t("div",gt,[(m(!0),v(w,null,$(u.value,(g,p)=>(m(),v("span",{key:p,class:M({"bg-success/20 text-success":g.removed,"bg-error/20 text-error":g.added,"text-text-primary":!g.added&&!g.removed})},y(g.value),3))),128))])],64))]))}}),ht={key:0,class:"rounded-lg border border-border-default bg-surface-raised p-4 space-y-4"},yt={class:"space-y-1.5"},_t={class:"text-[10px] text-text-secondary w-28 truncate shrink-0"},kt={class:"flex-1 h-3 bg-surface rounded-full overflow-hidden"},wt={class:"text-[10px] text-text-muted w-14 text-right shrink-0"},It={class:"space-y-1.5"},$t={class:"text-[10px] text-text-secondary w-28 truncate shrink-0"},Ct={class:"flex-1 h-3 bg-surface rounded-full overflow-hidden"},St={class:"text-[10px] text-text-muted w-14 text-right shrink-0"},Mt={class:"space-y-1.5"},Tt={class:"text-[10px] text-text-secondary w-28 truncate shrink-0"},Pt={class:"flex-1 h-3 bg-surface rounded-full overflow-hidden"},Ft={class:"text-[10px] text-text-muted w-14 text-right shrink-0"},Wt=F({__name:"ComparisonMetricsBar",props:{executions:{}},setup(o){const e=o,s=Z(),n=k(()=>e.executions.filter(p=>p.status==="completed"&&p.sessionId).map(p=>{const b=s.getMetrics(p.sessionId);return{label:p.label||p.model,slotId:p.slotId,ttftMs:b?.ttftMs??0,tokensPerSecond:b?.tokensPerSecond??0,totalTokens:b?.completionTokenCount??0}})),r=k(()=>Math.max(...n.value.map(p=>p.ttftMs),1)),u=k(()=>Math.max(...n.value.map(p=>p.tokensPerSecond),1)),a=k(()=>Math.max(...n.value.map(p=>p.totalTokens),1)),c=k(()=>n.value.length===0?"":n.value.reduce((p,b)=>p.ttftMs<b.ttftMs&&p.ttftMs>0?p:b).slotId),i=k(()=>n.value.length===0?"":n.value.reduce((p,b)=>p.tokensPerSecond>b.tokensPerSecond?p:b).slotId),f=["bg-accent","bg-success","bg-warning","bg-error"];function g(p){return f[p%f.length]??"bg-accent"}return(p,b)=>n.value.length>=2?(m(),v("div",ht,[b[3]||(b[3]=t("h4",{class:"text-xs font-medium text-text-secondary"},"Performance Comparison",-1)),t("div",yt,[b[0]||(b[0]=t("div",{class:"flex items-center justify-between"},[t("span",{class:"text-[11px] text-text-muted"},"Time to First Token"),t("span",{class:"text-[10px] text-text-muted"},"lower is better")],-1)),(m(!0),v(w,null,$(n.value,(d,l)=>(m(),v("div",{key:d.slotId+"-ttft",class:"flex items-center gap-2"},[t("span",_t,y(d.label),1),t("div",kt,[t("div",{class:M(["h-full rounded-full transition-all duration-500",[g(l),d.slotId===c.value?"opacity-100":"opacity-50"]]),style:A({width:`${d.ttftMs/r.value*100}%`})},null,6)]),t("span",wt,y(d.ttftMs.toFixed(0))+"ms",1)]))),128))]),t("div",It,[b[1]||(b[1]=t("div",{class:"flex items-center justify-between"},[t("span",{class:"text-[11px] text-text-muted"},"Tokens/sec"),t("span",{class:"text-[10px] text-text-muted"},"higher is better")],-1)),(m(!0),v(w,null,$(n.value,(d,l)=>(m(),v("div",{key:d.slotId+"-tps",class:"flex items-center gap-2"},[t("span",$t,y(d.label),1),t("div",Ct,[t("div",{class:M(["h-full rounded-full transition-all duration-500",[g(l),d.slotId===i.value?"opacity-100":"opacity-50"]]),style:A({width:`${d.tokensPerSecond/u.value*100}%`})},null,6)]),t("span",St,y(d.tokensPerSecond.toFixed(1)),1)]))),128))]),t("div",Mt,[b[2]||(b[2]=t("div",{class:"flex items-center justify-between"},[t("span",{class:"text-[11px] text-text-muted"},"Total Tokens")],-1)),(m(!0),v(w,null,$(n.value,(d,l)=>(m(),v("div",{key:d.slotId+"-tokens",class:"flex items-center gap-2"},[t("span",Tt,y(d.label),1),t("div",Pt,[t("div",{class:M(["h-full rounded-full transition-all duration-500",g(l)]),style:A({width:`${d.totalTokens/a.value*100}%`})},null,6)]),t("span",Ft,y(d.totalTokens),1)]))),128))])])):I("",!0)}}),Et={class:"space-y-6"},Dt={class:"rounded-lg border border-border-default bg-surface-raised p-4 space-y-3"},Rt=["disabled"],jt={class:"flex items-center justify-between"},zt={class:"text-xs text-text-muted"},At=["disabled"],Nt={key:0,class:"space-y-4"},Ot={class:"flex items-center gap-3"},Lt={key:0,class:"ml-auto flex gap-1 rounded-lg border border-border-default p-0.5"},Yt=F({__name:"ComparisonPage",setup(o){const e=ie(),s=oe(),n=C([]),r=C(""),u=C(!1),a=C("grid"),c=k(()=>e.activeRun),i=k(()=>n.value.length>0&&r.value.trim().length>0&&!u.value),f=k(()=>c.value?.executions.some(p=>p.status==="completed")??!1);async function g(){if(!i.value)return;u.value=!0,a.value="grid";const p=e.createRun(r.value.trim(),n.value),b=n.value.map(async d=>{try{const l=await ne({model:d.model,prompt:r.value.trim(),system:d.system||void 0,options:d.options});e.updateExecution(p,d.slotId,{sessionId:l.sessionId,status:"streaming"});const x=setInterval(()=>{const _=s.sessionById(l.sessionId);_&&(_.status==="completed"||_.status==="error")&&(e.updateExecution(p,d.slotId,{status:_.status,outputText:_.outputText,metrics:_.metrics}),clearInterval(x),e.finalizeRun(p))},500)}catch{e.updateExecution(p,d.slotId,{status:"error"})}});await Promise.allSettled(b),u.value=!1}return(p,b)=>(m(),v("div",Et,[P(Ge,{slots:n.value,"onUpdate:slots":b[0]||(b[0]=d=>n.value=d)},null,8,["slots"]),t("div",Dt,[O(t("textarea",{"onUpdate:modelValue":b[1]||(b[1]=d=>r.value=d),class:"w-full rounded-lg border border-border-default bg-surface px-4 py-3 text-sm text-text-primary placeholder-text-muted focus:border-accent focus:outline-none resize-none",disabled:u.value,rows:"3",placeholder:"Enter prompt to compare across slots..."},null,8,Rt),[[se,r.value]]),t("div",jt,[t("span",zt,y(n.value.length)+" slot"+y(n.value.length!==1?"s":"")+" configured ",1),t("button",{class:"rounded-lg bg-accent px-4 py-2 text-sm font-medium text-surface hover:bg-accent-hover transition-colors disabled:opacity-50",disabled:!i.value,onClick:g},y(u.value?"Running...":"Compare"),9,At)])]),c.value?(m(),v("div",Nt,[t("div",Ot,[b[4]||(b[4]=t("h3",{class:"text-sm font-medium text-text-secondary"},"Results",-1)),P(H,{status:c.value.status},null,8,["status"]),f.value?(m(),v("div",Lt,[t("button",{class:M(["rounded-md px-2.5 py-1 text-[11px] transition-colors",a.value==="grid"?"bg-surface-overlay text-text-primary":"text-text-muted hover:text-text-secondary"]),onClick:b[2]||(b[2]=d=>a.value="grid")}," Grid ",2),t("button",{class:M(["rounded-md px-2.5 py-1 text-[11px] transition-colors",a.value==="diff"?"bg-surface-overlay text-text-primary":"text-text-muted hover:text-text-secondary"]),onClick:b[3]||(b[3]=d=>a.value="diff")}," Diff ",2)])):I("",!0)]),a.value==="grid"?(m(),D(tt,{key:0,executions:c.value.executions,slots:c.value.slots},null,8,["executions","slots"])):(m(),D(bt,{key:1,executions:c.value.executions},null,8,["executions"])),f.value?(m(),D(Wt,{key:2,executions:c.value.executions},null,8,["executions"])):I("",!0)])):I("",!0)]))}});export{Yt as default};