turbollm 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -211
- package/dist/cli.js +664 -232
- package/dist/webdist/assets/{ChatScreen-DY2flMe9.js → ChatScreen-DwW1RFdb.js} +10 -10
- package/dist/webdist/assets/{CustomizeScreen-Cl6H68Sy.js → CustomizeScreen-DSE61GGl.js} +1 -1
- package/dist/webdist/assets/{DeveloperScreen-zC1nePXh.js → DeveloperScreen-BYGLUEKp.js} +1 -1
- package/dist/webdist/assets/{EnginesScreen-CrsziC3B.js → EnginesScreen-D1fV7OUs.js} +1 -1
- package/dist/webdist/assets/{ModelDetailDialog-BOvumdHI.js → ModelDetailDialog-DOWC_r7x.js} +1 -1
- package/dist/webdist/assets/{ModelDirs-Bj-XrX0c.js → ModelDirs-BnEgYeD7.js} +1 -1
- package/dist/webdist/assets/{ModelsScreen-BTir-kDY.js → ModelsScreen-CsIWlTix.js} +1 -1
- package/dist/webdist/assets/{SettingsScreen-B696egCa.js → SettingsScreen-BsoeEYxo.js} +1 -1
- package/dist/webdist/assets/check-BEcwngnz.js +1 -0
- package/dist/webdist/assets/{circle-x-CsuAddI_.js → circle-x-BMU1-bqZ.js} +1 -1
- package/dist/webdist/assets/{common-DIXPIrUd.js → common-CsaPxOo6.js} +1 -1
- package/dist/webdist/assets/{copy-button-BtQZA6P8.js → copy-button-VN55eluX.js} +1 -1
- package/dist/webdist/assets/{dialog-Dpyml8ZT.js → dialog-oym6ZR4Z.js} +1 -1
- package/dist/webdist/assets/{index-sjgdofsd.js → index-DdsLEQg8.js} +2 -2
- package/dist/webdist/assets/{pencil-BuQwoNyj.js → pencil-BUeTGZ2m.js} +1 -1
- package/dist/webdist/assets/{personas-CQapYHeK.js → personas-B44JP8XF.js} +1 -1
- package/dist/webdist/assets/{plus-B1w15FoZ.js → plus-B4N6E4A9.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-BoAcjLtt.js → refresh-cw-35eljdhP.js} +1 -1
- package/dist/webdist/assets/{save-DE1APWTG.js → save-AXon2pXP.js} +1 -1
- package/dist/webdist/assets/{skeleton-Dvq8tYzC.js → skeleton-BqBFt4sB.js} +1 -1
- package/dist/webdist/assets/{sparkles-C54kYWeQ.js → sparkles-C1EIsU4T.js} +1 -1
- package/dist/webdist/assets/{trash-2-DIMVgidH.js → trash-2-BOZ6n1d2.js} +1 -1
- package/dist/webdist/index.html +1 -1
- package/package.json +1 -1
- package/dist/webdist/assets/check-DFwkcl_5.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e}from"./radix-BFvMxQq9.js";import{r as g}from"./vendor-D_-14Whs.js";import{S as w}from"./common-
|
|
1
|
+
import{j as e}from"./radix-BFvMxQq9.js";import{r as g}from"./vendor-D_-14Whs.js";import{S as w}from"./common-CsaPxOo6.js";import{M as P,B as y,a1 as A,L as K,t as d,A as N}from"./index-DdsLEQg8.js";import{C as U}from"./check-BEcwngnz.js";import{P as M}from"./pencil-BUeTGZ2m.js";import{T}from"./trash-2-BOZ6n1d2.js";import{P as z}from"./plus-B4N6E4A9.js";function Y(){const{query:r}=P(),a=r.data;return e.jsxs("div",{className:"w-full px-6 py-6",children:[e.jsx(w,{title:"Customize",description:"Add tools and external providers the model can call during conversations."}),e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(L,{search:a?.search??{provider:"tavily",tavilyKeySet:!1,kagiKeySet:!1,searxngUrl:""},onSaved:()=>{r.refetch()}}),e.jsx($,{servers:a?.mcp?.servers??[]})]})]})}const C=[{id:"tavily",label:"Tavily",blurb:"AI-search API tuned for LLMs. Reliable default.",getKey:"https://app.tavily.com"},{id:"kagi",label:"Kagi",blurb:"Premium search, no bot-blocking, no tracking ($0.012/query).",getKey:"https://kagi.com/settings?p=api"},{id:"searxng",label:"SearXNG",blurb:"Your own self-hosted meta-search. Fully local — no key, just a URL."}];function L({search:r,onSaved:a}){const{save:l}=P(),[n,x]=g.useState(r.provider),[p,u]=g.useState(""),c=C.find(s=>s.id===n),o=n==="searxng",v=n==="tavily"?r.tavilyKeySet:n==="kagi"?r.kagiKeySet:!!r.searxngUrl,k=s=>{x(s),u(s==="searxng"?r.searxngUrl:"")},f=()=>{const s=p.trim(),b={provider:n};o?b.searxngUrl=s:s&&n==="tavily"?b.tavilyApiKey=s:s&&n==="kagi"&&(b.kagiApiKey=s),l.mutate({search:b},{onSuccess:()=>{d.success(`Search set to ${c.label}${s?` — ${o?"URL":"key"} saved`:""}`),o||u(""),a()},onError:j=>d.error(j instanceof N?j.message:"Could not save search settings.")})};return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsx("h2",{className:"mb-1 text-[13px] font-semibold uppercase tracking-wide text-faint",children:"Web Search"}),e.jsxs("p",{className:"mb-3 text-[12px] text-muted",children:["Choose a search provider. When one is configured, the model can call the"," ",e.jsx("span",{className:"font-mono text-ink",children:"web_search"})," tool automatically."]}),e.jsx("div",{className:"mb-3 inline-flex rounded-md border border-border p-0.5",children:C.map(s=>e.jsx("button",{onClick:()=>k(s.id),className:`rounded px-3 py-1 text-[13px] transition-colors ${n===s.id?"bg-bg text-ink":"text-muted hover:text-ink"}`,children:s.label},s.id))}),e.jsxs("p",{className:"mb-2 text-[12px] text-muted",children:[c.blurb," ",c.getKey&&e.jsx("a",{href:c.getKey,target:"_blank",rel:"noopener noreferrer",className:"text-ink underline-offset-2 hover:underline",children:"Get a key"})]}),e.jsx("div",{className:"mb-2 text-[13px] text-muted",children:v?e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-ink",children:[e.jsx(U,{size:13,style:{color:"var(--ok)"}})," ",o?"A URL is configured":"A key is configured"]}):o?"No URL configured":"No key configured"}),e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center",children:[e.jsx("input",{type:o?"text":"password",value:p,onChange:s=>u(s.target.value),placeholder:o?"http://localhost:8888":v?"Enter a new key to replace the current one":n==="tavily"?"tvly-…":"Kagi API key",autoComplete:"off",className:"flex-1 rounded-md border border-border bg-bg px-2 py-1.5 font-mono text-[13px] text-ink outline-none"}),e.jsx(y,{size:"sm",onClick:f,disabled:l.isPending,children:"Save"})]}),e.jsxs("p",{className:"mt-3 text-[12px] text-faint",children:[e.jsx("span",{className:"font-mono text-ink",children:"fetch_url"})," and"," ",e.jsx("span",{className:"font-mono text-ink",children:"run_code"})," (sandboxed JS) are always available — no key needed."]})]})}const E=()=>({name:"",transport:"stdio",command:"",argsStr:"",envStr:"",url:"",enabled:!0});function R(r){return{name:r.name,transport:r.transport,command:r.command??"",argsStr:(r.args??[]).join(", "),envStr:Object.entries(r.env??{}).map(([a,l])=>`${a}=${l}`).join(`
|
|
2
2
|
`),url:r.url??"",enabled:r.enabled}}function F(r){const a=r.argsStr.trim()?r.argsStr.split(",").map(n=>n.trim()).filter(Boolean):[],l={};for(const n of r.envStr.split(`
|
|
3
3
|
`)){const x=n.indexOf("=");x>0&&(l[n.slice(0,x).trim()]=n.slice(x+1).trim())}return{name:r.name.trim(),transport:r.transport,command:r.transport==="stdio"&&r.command.trim()||void 0,args:r.transport==="stdio"&&a.length?a:void 0,env:r.transport==="stdio"&&Object.keys(l).length?l:void 0,url:r.transport==="sse"&&r.url.trim()||void 0,enabled:r.enabled}}function $({servers:r}){const a=A(),[l,n]=g.useState(null),[x,p]=g.useState(!1),[u,c]=g.useState(E()),o=t=>c(i=>({...i,...t})),v=()=>{n(null),c(E()),p(!0)},k=t=>{n(t.id),c(R(t)),p(!0)},f=()=>{p(!1),n(null)},s=()=>{const t=F(u);if(!t.name)return void d.error("Server name is required.");if(t.transport==="stdio"&&!t.command)return void d.error("Command is required for stdio transport.");if(t.transport==="sse"&&!t.url)return void d.error("URL is required for SSE transport.");const i={onSuccess:()=>{d.success(l?"MCP server updated":"MCP server added"),f()},onError:h=>d.error(h instanceof N?h.message:"Could not save server.")};l?a.update.mutate({id:l,patch:t},i):a.add.mutate(t,i)},b=(t,i)=>{window.confirm(`Remove MCP server "${i}"?`)&&a.remove.mutate(t,{onError:h=>d.error(h instanceof N?h.message:"Could not remove server.")})},j=t=>{a.update.mutate({id:t.id,patch:{enabled:!t.enabled}},{onError:i=>d.error(i instanceof N?i.message:"Could not update server.")})},m=u,S=a.add.isPending||a.update.isPending;return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsx("h2",{className:"mb-1 text-[13px] font-semibold uppercase tracking-wide text-faint",children:"MCP Servers"}),e.jsx("p",{className:"mb-3 text-[12px] text-muted",children:"Connect external tool providers via the Model Context Protocol. Supports stdio (subprocess) and SSE (HTTP) transports per the MCP 2024-11-05 spec."}),r.length>0&&e.jsx("div",{className:"mb-3 flex flex-col gap-1.5",children:r.map(t=>e.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-border bg-panel-2 px-3 py-2",children:[e.jsx("span",{className:"shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px] font-medium",style:{background:t.transport==="sse"?"color-mix(in srgb, var(--accent) 15%, transparent)":"color-mix(in srgb, var(--muted) 20%, transparent)",color:t.transport==="sse"?"var(--accent)":"var(--muted)"},children:t.transport}),e.jsx("span",{className:"flex-1 truncate text-[13px] font-medium text-ink",children:t.name}),e.jsx("span",{className:"hidden shrink-0 max-w-[220px] truncate font-mono text-[11px] text-faint sm:block",title:t.transport==="stdio"?t.command:t.url,children:t.transport==="stdio"?t.command?.split(/[\\/]/).slice(-1)[0]:t.url}),e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:()=>j(t),title:t.enabled?"Disable":"Enable",className:"h-3.5 w-3.5 accent-[var(--accent)]"}),e.jsx("button",{type:"button",onClick:()=>k(t),title:"Edit",className:"rounded p-1 text-faint transition-colors hover:bg-bg hover:text-ink",children:e.jsx(M,{size:12})}),e.jsx("button",{type:"button",onClick:()=>b(t.id,t.name),title:"Delete",className:"rounded p-1 transition-colors hover:bg-bg",style:{color:"var(--err)"},children:e.jsx(T,{size:12})})]},t.id))}),x?e.jsxs("div",{className:"flex flex-col gap-3 rounded-lg border border-border bg-panel-2 p-3",children:[e.jsx("div",{className:"text-[13px] font-medium text-ink",children:l?"Edit server":"Add server"}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-[12px] text-muted",children:"Name"}),e.jsx("input",{type:"text",value:m.name,onChange:t=>o({name:t.target.value}),placeholder:"My Tool Server",className:"rounded-md border border-border bg-bg px-2 py-1.5 text-[13px] text-ink outline-none"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-[12px] text-muted",children:"Transport"}),e.jsx("div",{className:"flex gap-4",children:["stdio","sse"].map(t=>e.jsxs("label",{className:"flex cursor-pointer items-center gap-1.5 text-[13px] text-ink",children:[e.jsx("input",{type:"radio",name:"mcp-transport",checked:m.transport===t,onChange:()=>o({transport:t}),className:"h-3.5 w-3.5 accent-[var(--accent)]"}),e.jsx("span",{className:"font-mono",children:t}),e.jsx("span",{className:"text-[11px] text-faint",children:t==="stdio"?"(subprocess)":"(HTTP)"})]},t))})]}),m.transport==="stdio"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-[12px] text-muted",children:"Command"}),e.jsx("input",{type:"text",value:m.command,onChange:t=>o({command:t.target.value}),placeholder:"npx -y @modelcontextprotocol/server-filesystem",className:"rounded-md border border-border bg-bg px-2 py-1.5 font-mono text-[12px] text-ink outline-none"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("label",{className:"text-[12px] text-muted",children:["Args ",e.jsx("span",{className:"text-faint",children:"(comma-separated, optional)"})]}),e.jsx("input",{type:"text",value:m.argsStr,onChange:t=>o({argsStr:t.target.value}),placeholder:"--port, 3000",className:"rounded-md border border-border bg-bg px-2 py-1.5 font-mono text-[12px] text-ink outline-none"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("label",{className:"text-[12px] text-muted",children:["Env vars ",e.jsx("span",{className:"text-faint",children:"(KEY=VALUE, one per line, optional)"})]}),e.jsx("textarea",{rows:2,value:m.envStr,onChange:t=>o({envStr:t.target.value}),placeholder:`API_KEY=abc123
|
|
4
4
|
DEBUG=true`,className:"resize-none rounded-md border border-border bg-bg px-2 py-1.5 font-mono text-[12px] text-ink outline-none"})]})]}):e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-[12px] text-muted",children:"URL"}),e.jsx("input",{type:"text",value:m.url,onChange:t=>o({url:t.target.value}),placeholder:"http://localhost:3000",className:"rounded-md border border-border bg-bg px-2 py-1.5 font-mono text-[12px] text-ink outline-none"})]}),e.jsxs("label",{className:"flex cursor-pointer items-center gap-2 text-[13px] text-ink",children:[e.jsx("input",{type:"checkbox",checked:m.enabled,onChange:t=>o({enabled:t.target.checked}),className:"h-3.5 w-3.5 accent-[var(--accent)]"}),"Enable immediately"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(y,{size:"sm",onClick:s,disabled:S,children:[S?e.jsx(K,{size:13,className:"animate-spin"}):null,l?"Update":"Add"]}),e.jsx(y,{variant:"outline",size:"sm",onClick:f,children:"Cancel"})]})]}):e.jsxs(y,{variant:"outline",size:"sm",onClick:v,children:[e.jsx(z,{size:13}),"Add server"]})]})}export{Y as CustomizeScreen};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./radix-BFvMxQq9.js";import{r as p}from"./vendor-D_-14Whs.js";import{C as m}from"./copy-button-
|
|
1
|
+
import{j as e}from"./radix-BFvMxQq9.js";import{r as p}from"./vendor-D_-14Whs.js";import{C as m}from"./copy-button-VN55eluX.js";import{S as y}from"./common-CsaPxOo6.js";import{c as f,$ as N,B as v,t as b,A as g,a0 as k}from"./index-DdsLEQg8.js";import{T as C}from"./trash-2-BOZ6n1d2.js";import{P as S}from"./plus-B4N6E4A9.js";import"./check-BEcwngnz.js";const w=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]],A=f("globe",w);const I=[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]],E=f("key",I);const L=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],P=f("terminal",L),u=window.location.origin,T=[{method:"POST",path:"/v1/chat/completions",desc:"OpenAI Chat Completions"},{method:"POST",path:"/v1/messages",desc:"Anthropic Messages"},{method:"GET",path:"/v1/models",desc:"OpenAI Models List"},{method:"GET",path:"/api/v1/status",desc:"Daemon Status"},{method:"GET",path:"/api/v1/engines",desc:"Engine Registry"},{method:"GET",path:"/api/v1/models",desc:"Model Library"},{method:"GET",path:"/api/v1/keys",desc:"API Keys"}],K=[{id:"claude-code",name:"Claude Code",desc:"Anthropic-compatible endpoint — the hero demo"},{id:"opencode",name:"opencode",desc:"OpenAI-compatible, AI SDK provider config"},{id:"kilo",name:"Kilo Code",desc:"OpenAI-compatible, kilo.jsonc provider entry"},{id:"qwen",name:"Qwen Code",desc:"OpenAI-compatible (OPENAI_BASE_URL)"}];function V(){return e.jsxs("div",{className:"w-full px-6 py-6",children:[e.jsx(y,{title:"Developer",description:"Server URLs, API endpoints, keys, and CLI setup."}),e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(_,{}),e.jsx(G,{}),e.jsx(z,{}),e.jsx(O,{})]})]})}function _(){return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[e.jsx(A,{size:15,className:"text-accent"}),e.jsx("h2",{className:"text-[13px] font-semibold uppercase tracking-wide text-faint",children:"Server"})]}),e.jsxs("div",{className:"flex items-center justify-between py-1",children:[e.jsx("span",{className:"text-[13px] text-muted",children:"Local URL"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-[13px] text-ink",children:u}),e.jsx(m,{text:u})]})]})]})}function G(){const{query:s,create:n,revoke:c}=N(),[a,l]=p.useState(""),[r,o]=p.useState(null),x=s.data?.keys??[],i=()=>{const t=a.trim();t&&n.mutate(t,{onSuccess:d=>{l(""),o(d.key)},onError:d=>b.error(d instanceof g?d.message:"Could not create key.")})},h=(t,d)=>{c.mutate(t,{onSuccess:()=>{r?.startsWith(d)&&o(null)},onError:j=>b.error(j instanceof g?j.message:"Could not revoke key.")})};return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[e.jsx(E,{size:15,className:"text-accent"}),e.jsx("h2",{className:"text-[13px] font-semibold uppercase tracking-wide text-faint",children:"API Keys"})]}),r&&e.jsxs("div",{className:"mb-4 rounded-md border p-3",style:{borderColor:"var(--ok)",background:"color-mix(in srgb, var(--ok) 8%, transparent)"},children:[e.jsx("p",{className:"mb-1.5 text-[12px] font-medium",style:{color:"var(--ok)"},children:"Key created — copy it now, it won't be shown again."}),e.jsxs("div",{className:"flex items-center gap-2 rounded border border-border bg-bg px-2 py-1.5",children:[e.jsx("code",{className:"min-w-0 flex-1 break-all font-mono text-[12px] text-ink",children:r}),e.jsx(m,{text:r})]})]}),x.length===0&&!r&&e.jsx("p",{className:"mb-3 text-[13px] text-faint",children:"No API keys yet."}),x.length>0&&e.jsx("div",{className:"mb-3 divide-y divide-border rounded-md border border-border",children:x.map(t=>e.jsxs("div",{className:"flex items-center justify-between px-3 py-2.5",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:t.name}),e.jsxs("span",{className:"ml-2 font-mono text-[11px] text-faint",children:[t.prefix,"…"]})]}),e.jsx("button",{type:"button",onClick:()=>h(t.id,t.prefix),className:"rounded p-1 text-faint transition-colors hover:text-err",title:"Revoke key",children:e.jsx(C,{size:14})})]},t.id))}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:a,onChange:t=>l(t.target.value),placeholder:"Key name (e.g. claude-code)",className:"flex-1 rounded-md border border-border bg-bg px-2.5 py-1.5 text-[13px] text-ink outline-none placeholder:text-faint focus:border-[color:var(--accent)]",onKeyDown:t=>t.key==="Enter"&&i()}),e.jsxs(v,{size:"sm",onClick:i,disabled:!a.trim()||n.isPending,children:[e.jsx(S,{size:13}),n.isPending?"Creating…":"Create"]})]})]})}function z(){return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsx("h2",{className:"mb-3 text-[13px] font-semibold uppercase tracking-wide text-faint",children:"Available APIs"}),e.jsx("div",{className:"divide-y divide-border rounded-md border border-border",children:T.map(({method:s,path:n,desc:c})=>e.jsxs("div",{className:"flex items-center gap-3 px-3 py-2",children:[e.jsx("span",{className:"w-10 shrink-0 rounded px-1 py-0.5 text-center font-mono text-[10px] font-bold uppercase",style:{background:s==="GET"?"color-mix(in srgb, var(--ok) 15%, transparent)":"color-mix(in srgb, var(--accent) 15%, transparent)",color:s==="GET"?"var(--ok)":"var(--accent)"},children:s}),e.jsx("span",{className:"min-w-0 flex-1 truncate font-mono text-[13px] text-ink",children:n}),e.jsx("span",{className:"hidden shrink-0 text-[11px] text-muted sm:block",children:c}),e.jsx(m,{text:`${u}${n}`})]},n))})]})}function O(){return e.jsxs("section",{className:"rounded-lg border border-border bg-panel p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[e.jsx(P,{size:15,className:"text-accent"}),e.jsx("h2",{className:"text-[13px] font-semibold uppercase tracking-wide text-faint",children:"Connect a CLI"})]}),e.jsx("div",{className:"flex flex-col gap-2.5",children:K.map(s=>e.jsx(B,{cli:s},s.id))})]})}function B({cli:s}){const[n,c]=p.useState(null),[a,l]=p.useState(!1),[r,o]=p.useState(!1),x=()=>{if(r){o(!1);return}if(n){o(!0);return}l(!0),k(s.id).then(i=>{c(i),o(!0)}).catch(()=>b.error("Could not fetch setup snippets.")).finally(()=>l(!1))};return e.jsxs("div",{className:"rounded-md border border-border bg-bg",children:[e.jsxs("div",{className:"flex items-center justify-between px-3 py-2.5",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[13px] font-semibold text-ink",children:s.name}),e.jsx("span",{className:"ml-2 text-[11px] text-muted",children:s.desc})]}),e.jsx(v,{size:"sm",variant:r?"outline":"default",onClick:x,disabled:a,children:a?"Loading…":r?"Hide":"Get setup"})]}),r&&n&&e.jsx("div",{className:"flex flex-col gap-2.5 border-t border-border px-3 pb-3 pt-2.5",children:n.steps.map((i,h)=>e.jsx(R,{step:i},h))})]})}function R({step:s}){return e.jsxs("div",{children:[e.jsx("div",{className:"mb-1 text-[11px] text-faint",children:s.label}),e.jsxs("div",{className:"relative rounded border border-border bg-panel-2",children:[e.jsx("pre",{className:"overflow-x-auto whitespace-pre-wrap break-all px-3 py-2 pr-10 font-mono text-[12px] leading-relaxed text-ink",children:s.snippet}),e.jsx(m,{text:s.snippet,className:"absolute right-2 top-2"})]})]})}export{V as DeveloperScreen};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,g as nn,h as sn,i as tn,k as an,l as ln}from"./radix-BFvMxQq9.js";import{r as b}from"./vendor-D_-14Whs.js";import{c as R,F as rn,B as S,A as C,G as on,H as Z,J as cn,L as G,I as ve,t as v,K as dn,M as un,u as ie,N as Ae,X as mn,D as Q,d as xn,O as pn,w as ce,P as hn,Q as fn,R as Le,T as pe,U as Ee,V as Be,y as Me,W as gn,e as ke,m as bn,C as jn,Y as vn}from"./index-sjgdofsd.js";import{I as Y,S as kn}from"./common-DIXPIrUd.js";import{B as T,E as ze,S as oe}from"./skeleton-Dvq8tYzC.js";import{h as he,j as fe,l as q,m as H,n as ne,o as K,i as Ne,b as W,g as Nn,a as yn,D as se,c as te,d as ae,f as U,e as X,A as $e,p as Ue,q as Re,r as Ie,s as Te,t as _e,u as Fe,v as Oe,C as de}from"./dialog-Dpyml8ZT.js";import{C as F}from"./check-DFwkcl_5.js";import{P as qe}from"./plus-B1w15FoZ.js";import{E as le,R as He}from"./refresh-cw-BoAcjLtt.js";import{a as wn,C as Ge}from"./copy-button-BtQZA6P8.js";import{C as Ve}from"./circle-x-CsuAddI_.js";import{S as ge}from"./sparkles-C54kYWeQ.js";const Cn=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],ye=R("arrow-left",Cn);const Sn=[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]],Dn=R("arrow-up",Sn);const Pn=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}]],An=R("file",Pn);const Ln=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],En=R("folder-open",Ln);const Bn=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]],Mn=R("folder",Bn);const zn=[["path",{d:"m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9",key:"1hayfq"}],["path",{d:"m18 15 4-4",key:"16gjal"}],["path",{d:"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5",key:"15ts47"}]],$n=R("hammer",zn);const Un=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],Rn=R("layers",Un);const In=[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]],Ye=R("rotate-cw",In);const Tn=[["path",{d:"m13.5 8.5-5 5",key:"1cs55j"}],["path",{d:"m8.5 8.5 5 5",key:"a8mexj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]],_n=R("search-x",Tn);const Fn=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],On=R("wrench",Fn);function qn({open:n,onOpenChange:s,onSelect:i,mode:a="file"}){const[u,d]=b.useState(null),{data:c,isFetching:o,error:g,refetch:h}=rn(u,n);b.useEffect(()=>{n&&d(null)},[n]);const x=N=>{i(N),s(!1)};return e.jsx(he,{open:n,onOpenChange:s,children:e.jsxs(fe,{className:"max-w-lg",children:[e.jsxs(q,{children:[e.jsx(H,{children:a==="folder"?"Choose engine folder":"Browse for binary"}),e.jsx(ne,{children:a==="folder"?e.jsxs(e.Fragment,{children:["Open the folder that contains your engine build, then click"," ",e.jsx("span",{className:"font-medium text-ink",children:"Select this folder"}),". We'll scan it for ",e.jsx("code",{className:"font-mono",children:"llama-server"}),". Limited to your home directory."]}):e.jsxs(e.Fragment,{children:["Navigate to the compiled ",e.jsx("code",{className:"font-mono",children:"llama-server"})," executable and click it to select. Limited to your home directory."]})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(S,{variant:"outline",size:"iconSm",onClick:()=>c?.parent!=null&&d(c.parent),disabled:!c||c.parent==null||o,"aria-label":"Up one folder",children:e.jsx(Dn,{size:16})}),e.jsx("div",{className:"min-w-0 flex-1 truncate rounded-md border border-border bg-panel-2 px-2.5 py-1.5 font-mono text-[12px] text-muted",title:c?.path??"",children:c?.path??"…"}),e.jsx(S,{variant:"outline",size:"iconSm",onClick:()=>{h()},disabled:o,"aria-label":"Refresh",children:e.jsx(Ye,{size:16,className:o?"animate-spin":void 0})})]}),g?e.jsx(Y,{message:g instanceof C?g.message:"Could not read that folder.",onRetry:()=>{h()},className:"mt-3"}):e.jsxs("ul",{className:"mt-3 max-h-[320px] overflow-y-auto rounded-md border border-border",children:[c&&c.entries.length===0&&e.jsx("li",{className:"px-3 py-6 text-center text-[13px] text-muted",children:"This folder is empty."}),c?.entries.map(N=>{const f=a==="folder"&&!N.isDir;return e.jsx("li",{children:e.jsxs("button",{type:"button",disabled:f,onClick:()=>N.isDir?d(N.path):x(N.path),className:"flex w-full items-center gap-2.5 px-3 py-2 text-left text-[13px] text-ink "+(f?"cursor-default text-faint":"hover:bg-panel-2"),children:[N.isDir?e.jsx(Mn,{size:16,className:"shrink-0 text-muted"}):e.jsx(An,{size:16,className:f?"shrink-0 text-faint":"shrink-0 text-muted"}),e.jsx("span",{className:"min-w-0 flex-1 truncate font-mono",children:on(N.name,48)}),a==="file"&&!N.isDir&&e.jsx("span",{className:"shrink-0 text-[11px] text-muted",children:"Select"})]})},N.path)})]}),e.jsxs(K,{children:[e.jsx(S,{variant:"outline",onClick:()=>s(!1),children:"Cancel"}),a==="folder"&&e.jsxs(S,{onClick:()=>c?.path&&x(c.path),disabled:!c?.path||o,children:[e.jsx(F,{size:16})," Select this folder"]})]})]})})}function be({open:n,onOpenChange:s,defaultSourceRepo:i,trigger:a}={}){const[u,d]=b.useState(!1),c=n!==void 0,o=c?n:u,g=p=>{c||d(p),s?.(p)},[h,x]=b.useState("choose"),[N,f]=b.useState(null),[w,k]=b.useState(""),[B,D]=b.useState(""),[z,P]=b.useState(""),[A,$]=b.useState(""),[L,l]=b.useState(null),[m,t]=b.useState(null),{add:r}=Z(),j=cn();b.useEffect(()=>{o&&i&&$(i)},[o,i]);const E=()=>{x("choose"),f(null),k(""),D(""),P(""),$(""),l(null),t(null)},I=p=>{t(null),l(null),x("scanning"),j.mutate(p,{onSuccess:y=>{if(!y.found){x("notfound");return}k(y.binPath),D(y.version),P(y.suggestedName),x("confirm")},onError:y=>{t(y instanceof C?y.message:"Could not scan that location."),x("choose")}})},V=()=>{l(null),t(null);const p=A.trim();r.mutate({name:z.trim(),binPath:w,...p?{sourceRepo:p}:{}},{onSuccess:y=>{y.warning==="no_version"?v.warning("Engine added, but its version could not be detected."):v.success("Engine added"),g(!1),E()},onError:y=>{const O=y instanceof C?y.code:"",_=y instanceof C?y.message:"Could not add engine.";O==="name_already_taken"?l(_):t(_)}})};return e.jsxs(he,{open:o,onOpenChange:p=>{g(p),p||E()},children:[a!==void 0?a!==null&&e.jsx(Ne,{asChild:!0,children:a}):e.jsx(Ne,{asChild:!0,children:e.jsxs(S,{children:[e.jsx(qe,{size:16})," Add engine"]})}),e.jsxs(fe,{children:[h==="choose"&&e.jsxs(e.Fragment,{children:[e.jsxs(q,{children:[e.jsx(H,{children:"Add your own engine"}),e.jsx(ne,{children:"Bring any llama.cpp-compatible build or community fork. Pick the folder it lives in and we'll find the server binary for you."})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs(S,{onClick:()=>f("folder"),className:"w-full",children:[e.jsx(En,{size:16})," Choose folder…"]}),e.jsx("button",{type:"button",onClick:()=>f("file"),className:"text-[12px] text-muted underline-offset-2 hover:text-ink hover:underline",children:"or pick the binary directly"}),e.jsx("p",{className:"text-[12px] text-faint",children:"Works with: ik_llama.cpp · TurboQuant · llama.cpp builds · any fork"}),m&&e.jsx(Y,{message:m})]}),e.jsx(K,{children:e.jsx(S,{variant:"outline",onClick:()=>g(!1),children:"Cancel"})})]}),h==="scanning"&&e.jsxs(e.Fragment,{children:[e.jsx(q,{children:e.jsx(H,{children:"Add your own engine"})}),e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:[e.jsx(G,{size:18,className:"shrink-0 animate-spin text-ink"}),"Looking for the server binary…"]})]}),h==="confirm"&&e.jsxs(e.Fragment,{children:[e.jsxs(q,{children:[e.jsx(H,{children:"Confirm engine"}),e.jsx(ne,{children:"Review what we found, then add it."})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2.5 rounded-lg border border-border bg-panel p-3 text-[13px] text-ink",children:[e.jsx(W,{size:16,className:"shrink-0",style:{color:"var(--ok)"}}),e.jsxs("span",{children:["Found ",e.jsx("code",{className:"font-mono",children:"llama-server"}),B&&B.toLowerCase()!=="unknown"?e.jsxs(e.Fragment,{children:[" · ",e.jsx("span",{className:"text-muted",children:B})]}):null]})]}),e.jsxs("label",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Name"}),e.jsx(ve,{value:z,onChange:p=>P(p.target.value),autoFocus:!0}),e.jsx("span",{className:"text-[12px] text-muted",children:"Any label you choose — shown in the engine list."}),L&&e.jsx(Y,{message:L})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Binary"}),e.jsx("div",{className:"truncate rounded-md border border-border bg-panel-2 px-2.5 py-1.5 font-mono text-[12px] text-muted",title:w,children:w})]}),e.jsxs("label",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Source repo URL (optional)"}),e.jsx(ve,{value:A,onChange:p=>$(p.target.value),placeholder:"https://github.com/owner/repo"}),e.jsx("span",{className:"text-[12px] text-muted",children:"Paste the GitHub repo you built this from — lets TurboLLM tell you when a newer build is available."})]}),m&&e.jsx(Y,{message:m})]}),e.jsxs(K,{children:[e.jsxs(S,{variant:"outline",onClick:()=>x("choose"),disabled:r.isPending,children:[e.jsx(ye,{size:16})," Back"]}),e.jsx(S,{onClick:V,disabled:z.trim().length===0||r.isPending,children:r.isPending?"Adding…":"Add engine"})]})]}),h==="notfound"&&e.jsxs(e.Fragment,{children:[e.jsx(q,{children:e.jsx(H,{children:"No engine found"})}),e.jsxs("div",{className:"flex items-start gap-2.5 rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:[e.jsx(_n,{size:18,className:"mt-0.5 shrink-0 text-faint"}),e.jsxs("span",{children:["We couldn't find ",e.jsx("code",{className:"font-mono",children:"llama-server"})," in that folder. Pick the folder that contains it, or select the binary directly."]})]}),e.jsxs(K,{children:[e.jsxs(S,{variant:"outline",onClick:()=>x("choose"),children:[e.jsx(ye,{size:16})," Back"]}),e.jsx(S,{onClick:()=>f("file"),children:"Pick the binary directly"})]})]}),e.jsx(qn,{open:N!==null,mode:N==="file"?"file":"folder",onOpenChange:p=>{p||f(null)},onSelect:p=>{f(null),I(p)}})]})]})}function Hn(n,s){const i=(s??"").trim();return[i?`git clone --branch ${i} --depth 1 ${n} turbo-build`:`git clone --depth 1 ${n} turbo-build`,"cd turbo-build","cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release","cmake --build build --config Release -j --target llama-server",'# Built binary: build\\bin\\Release\\llama-server.exe — add it via "Add your own engine".']}const Gn={provisioning:"Downloading CUDA Toolkit…",preparing:"Preparing…",cloning:"Cloning the repository…",configuring:"Configuring (cmake)…",compiling:"Compiling llama-server… this can take several minutes",registering:"Registering the built engine…",done:"Built and registered ✓",error:"Build failed"};function ue({open:n,onOpenChange:s,repoUrl:i,engineName:a,branch:u,mode:d="build"}){const c=dn(n),o=un(),g=ie(),h=Ae(),[x,N]=b.useState(!1),[f,w]=b.useState(!1),[k,B]=b.useState(null),D=o.query.data?.build.toolchainDirs??[],[z,P]=b.useState(null),A=z??D,L=Hn(i,u).join(`
|
|
1
|
+
import{j as e,g as nn,h as sn,i as tn,k as an,l as ln}from"./radix-BFvMxQq9.js";import{r as b}from"./vendor-D_-14Whs.js";import{c as R,F as rn,B as S,A as C,G as on,H as Z,J as cn,L as G,I as ve,t as v,K as dn,M as un,u as ie,N as Ae,X as mn,D as Q,d as xn,O as pn,w as ce,P as hn,Q as fn,R as Le,T as pe,U as Ee,V as Be,y as Me,W as gn,e as ke,m as bn,C as jn,Y as vn}from"./index-DdsLEQg8.js";import{I as Y,S as kn}from"./common-CsaPxOo6.js";import{B as T,E as ze,S as oe}from"./skeleton-BqBFt4sB.js";import{h as he,j as fe,l as q,m as H,n as ne,o as K,i as Ne,b as W,g as Nn,a as yn,D as se,c as te,d as ae,f as U,e as X,A as $e,p as Ue,q as Re,r as Ie,s as Te,t as _e,u as Fe,v as Oe,C as de}from"./dialog-oym6ZR4Z.js";import{C as F}from"./check-BEcwngnz.js";import{P as qe}from"./plus-B4N6E4A9.js";import{E as le,R as He}from"./refresh-cw-35eljdhP.js";import{a as wn,C as Ge}from"./copy-button-VN55eluX.js";import{C as Ve}from"./circle-x-BMU1-bqZ.js";import{S as ge}from"./sparkles-C1EIsU4T.js";const Cn=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],ye=R("arrow-left",Cn);const Sn=[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]],Dn=R("arrow-up",Sn);const Pn=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}]],An=R("file",Pn);const Ln=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],En=R("folder-open",Ln);const Bn=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]],Mn=R("folder",Bn);const zn=[["path",{d:"m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9",key:"1hayfq"}],["path",{d:"m18 15 4-4",key:"16gjal"}],["path",{d:"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5",key:"15ts47"}]],$n=R("hammer",zn);const Un=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],Rn=R("layers",Un);const In=[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]],Ye=R("rotate-cw",In);const Tn=[["path",{d:"m13.5 8.5-5 5",key:"1cs55j"}],["path",{d:"m8.5 8.5 5 5",key:"a8mexj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]],_n=R("search-x",Tn);const Fn=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],On=R("wrench",Fn);function qn({open:n,onOpenChange:s,onSelect:i,mode:a="file"}){const[u,d]=b.useState(null),{data:c,isFetching:o,error:g,refetch:h}=rn(u,n);b.useEffect(()=>{n&&d(null)},[n]);const x=N=>{i(N),s(!1)};return e.jsx(he,{open:n,onOpenChange:s,children:e.jsxs(fe,{className:"max-w-lg",children:[e.jsxs(q,{children:[e.jsx(H,{children:a==="folder"?"Choose engine folder":"Browse for binary"}),e.jsx(ne,{children:a==="folder"?e.jsxs(e.Fragment,{children:["Open the folder that contains your engine build, then click"," ",e.jsx("span",{className:"font-medium text-ink",children:"Select this folder"}),". We'll scan it for ",e.jsx("code",{className:"font-mono",children:"llama-server"}),". Limited to your home directory."]}):e.jsxs(e.Fragment,{children:["Navigate to the compiled ",e.jsx("code",{className:"font-mono",children:"llama-server"})," executable and click it to select. Limited to your home directory."]})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(S,{variant:"outline",size:"iconSm",onClick:()=>c?.parent!=null&&d(c.parent),disabled:!c||c.parent==null||o,"aria-label":"Up one folder",children:e.jsx(Dn,{size:16})}),e.jsx("div",{className:"min-w-0 flex-1 truncate rounded-md border border-border bg-panel-2 px-2.5 py-1.5 font-mono text-[12px] text-muted",title:c?.path??"",children:c?.path??"…"}),e.jsx(S,{variant:"outline",size:"iconSm",onClick:()=>{h()},disabled:o,"aria-label":"Refresh",children:e.jsx(Ye,{size:16,className:o?"animate-spin":void 0})})]}),g?e.jsx(Y,{message:g instanceof C?g.message:"Could not read that folder.",onRetry:()=>{h()},className:"mt-3"}):e.jsxs("ul",{className:"mt-3 max-h-[320px] overflow-y-auto rounded-md border border-border",children:[c&&c.entries.length===0&&e.jsx("li",{className:"px-3 py-6 text-center text-[13px] text-muted",children:"This folder is empty."}),c?.entries.map(N=>{const f=a==="folder"&&!N.isDir;return e.jsx("li",{children:e.jsxs("button",{type:"button",disabled:f,onClick:()=>N.isDir?d(N.path):x(N.path),className:"flex w-full items-center gap-2.5 px-3 py-2 text-left text-[13px] text-ink "+(f?"cursor-default text-faint":"hover:bg-panel-2"),children:[N.isDir?e.jsx(Mn,{size:16,className:"shrink-0 text-muted"}):e.jsx(An,{size:16,className:f?"shrink-0 text-faint":"shrink-0 text-muted"}),e.jsx("span",{className:"min-w-0 flex-1 truncate font-mono",children:on(N.name,48)}),a==="file"&&!N.isDir&&e.jsx("span",{className:"shrink-0 text-[11px] text-muted",children:"Select"})]})},N.path)})]}),e.jsxs(K,{children:[e.jsx(S,{variant:"outline",onClick:()=>s(!1),children:"Cancel"}),a==="folder"&&e.jsxs(S,{onClick:()=>c?.path&&x(c.path),disabled:!c?.path||o,children:[e.jsx(F,{size:16})," Select this folder"]})]})]})})}function be({open:n,onOpenChange:s,defaultSourceRepo:i,trigger:a}={}){const[u,d]=b.useState(!1),c=n!==void 0,o=c?n:u,g=p=>{c||d(p),s?.(p)},[h,x]=b.useState("choose"),[N,f]=b.useState(null),[w,k]=b.useState(""),[B,D]=b.useState(""),[z,P]=b.useState(""),[A,$]=b.useState(""),[L,l]=b.useState(null),[m,t]=b.useState(null),{add:r}=Z(),j=cn();b.useEffect(()=>{o&&i&&$(i)},[o,i]);const E=()=>{x("choose"),f(null),k(""),D(""),P(""),$(""),l(null),t(null)},I=p=>{t(null),l(null),x("scanning"),j.mutate(p,{onSuccess:y=>{if(!y.found){x("notfound");return}k(y.binPath),D(y.version),P(y.suggestedName),x("confirm")},onError:y=>{t(y instanceof C?y.message:"Could not scan that location."),x("choose")}})},V=()=>{l(null),t(null);const p=A.trim();r.mutate({name:z.trim(),binPath:w,...p?{sourceRepo:p}:{}},{onSuccess:y=>{y.warning==="no_version"?v.warning("Engine added, but its version could not be detected."):v.success("Engine added"),g(!1),E()},onError:y=>{const O=y instanceof C?y.code:"",_=y instanceof C?y.message:"Could not add engine.";O==="name_already_taken"?l(_):t(_)}})};return e.jsxs(he,{open:o,onOpenChange:p=>{g(p),p||E()},children:[a!==void 0?a!==null&&e.jsx(Ne,{asChild:!0,children:a}):e.jsx(Ne,{asChild:!0,children:e.jsxs(S,{children:[e.jsx(qe,{size:16})," Add engine"]})}),e.jsxs(fe,{children:[h==="choose"&&e.jsxs(e.Fragment,{children:[e.jsxs(q,{children:[e.jsx(H,{children:"Add your own engine"}),e.jsx(ne,{children:"Bring any llama.cpp-compatible build or community fork. Pick the folder it lives in and we'll find the server binary for you."})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs(S,{onClick:()=>f("folder"),className:"w-full",children:[e.jsx(En,{size:16})," Choose folder…"]}),e.jsx("button",{type:"button",onClick:()=>f("file"),className:"text-[12px] text-muted underline-offset-2 hover:text-ink hover:underline",children:"or pick the binary directly"}),e.jsx("p",{className:"text-[12px] text-faint",children:"Works with: ik_llama.cpp · TurboQuant · llama.cpp builds · any fork"}),m&&e.jsx(Y,{message:m})]}),e.jsx(K,{children:e.jsx(S,{variant:"outline",onClick:()=>g(!1),children:"Cancel"})})]}),h==="scanning"&&e.jsxs(e.Fragment,{children:[e.jsx(q,{children:e.jsx(H,{children:"Add your own engine"})}),e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:[e.jsx(G,{size:18,className:"shrink-0 animate-spin text-ink"}),"Looking for the server binary…"]})]}),h==="confirm"&&e.jsxs(e.Fragment,{children:[e.jsxs(q,{children:[e.jsx(H,{children:"Confirm engine"}),e.jsx(ne,{children:"Review what we found, then add it."})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2.5 rounded-lg border border-border bg-panel p-3 text-[13px] text-ink",children:[e.jsx(W,{size:16,className:"shrink-0",style:{color:"var(--ok)"}}),e.jsxs("span",{children:["Found ",e.jsx("code",{className:"font-mono",children:"llama-server"}),B&&B.toLowerCase()!=="unknown"?e.jsxs(e.Fragment,{children:[" · ",e.jsx("span",{className:"text-muted",children:B})]}):null]})]}),e.jsxs("label",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Name"}),e.jsx(ve,{value:z,onChange:p=>P(p.target.value),autoFocus:!0}),e.jsx("span",{className:"text-[12px] text-muted",children:"Any label you choose — shown in the engine list."}),L&&e.jsx(Y,{message:L})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Binary"}),e.jsx("div",{className:"truncate rounded-md border border-border bg-panel-2 px-2.5 py-1.5 font-mono text-[12px] text-muted",title:w,children:w})]}),e.jsxs("label",{className:"flex flex-col gap-1.5",children:[e.jsx("span",{className:"text-[13px] font-medium text-ink",children:"Source repo URL (optional)"}),e.jsx(ve,{value:A,onChange:p=>$(p.target.value),placeholder:"https://github.com/owner/repo"}),e.jsx("span",{className:"text-[12px] text-muted",children:"Paste the GitHub repo you built this from — lets TurboLLM tell you when a newer build is available."})]}),m&&e.jsx(Y,{message:m})]}),e.jsxs(K,{children:[e.jsxs(S,{variant:"outline",onClick:()=>x("choose"),disabled:r.isPending,children:[e.jsx(ye,{size:16})," Back"]}),e.jsx(S,{onClick:V,disabled:z.trim().length===0||r.isPending,children:r.isPending?"Adding…":"Add engine"})]})]}),h==="notfound"&&e.jsxs(e.Fragment,{children:[e.jsx(q,{children:e.jsx(H,{children:"No engine found"})}),e.jsxs("div",{className:"flex items-start gap-2.5 rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:[e.jsx(_n,{size:18,className:"mt-0.5 shrink-0 text-faint"}),e.jsxs("span",{children:["We couldn't find ",e.jsx("code",{className:"font-mono",children:"llama-server"})," in that folder. Pick the folder that contains it, or select the binary directly."]})]}),e.jsxs(K,{children:[e.jsxs(S,{variant:"outline",onClick:()=>x("choose"),children:[e.jsx(ye,{size:16})," Back"]}),e.jsx(S,{onClick:()=>f("file"),children:"Pick the binary directly"})]})]}),e.jsx(qn,{open:N!==null,mode:N==="file"?"file":"folder",onOpenChange:p=>{p||f(null)},onSelect:p=>{f(null),I(p)}})]})]})}function Hn(n,s){const i=(s??"").trim();return[i?`git clone --branch ${i} --depth 1 ${n} turbo-build`:`git clone --depth 1 ${n} turbo-build`,"cd turbo-build","cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release","cmake --build build --config Release -j --target llama-server",'# Built binary: build\\bin\\Release\\llama-server.exe — add it via "Add your own engine".']}const Gn={provisioning:"Downloading CUDA Toolkit…",preparing:"Preparing…",cloning:"Cloning the repository…",configuring:"Configuring (cmake)…",compiling:"Compiling llama-server… this can take several minutes",registering:"Registering the built engine…",done:"Built and registered ✓",error:"Build failed"};function ue({open:n,onOpenChange:s,repoUrl:i,engineName:a,branch:u,mode:d="build"}){const c=dn(n),o=un(),g=ie(),h=Ae(),[x,N]=b.useState(!1),[f,w]=b.useState(!1),[k,B]=b.useState(null),D=o.query.data?.build.toolchainDirs??[],[z,P]=b.useState(null),A=z??D,L=Hn(i,u).join(`
|
|
2
2
|
`),l=c.data?.supported??null,m=c.data?.tools??[],t=m.filter(M=>(M.id==="git"||M.id==="cmake"||M.id==="cuda")&&!M.found),r=g.data?.engineBuild,j=!!r?.active,E=!!g.data?.engineProvision?.active,I=k!==null||j,V=m.some(M=>M.id==="cuda"&&!M.found),p=l===!0&&t.length===0&&!j&&!E;b.useEffect(()=>{!k||!r||r.active||(r.phase==="done"?k==="cuda"?(c.refetch(),o.query.refetch(),B(null)):h.refresh():r.phase==="error"&&k==="build"&&h.refresh())},[k,r?.active,r?.phase]);const y=b.useRef(null);b.useEffect(()=>{y.current&&(y.current.scrollTop=y.current.scrollHeight)},[r?.log]);const O=()=>{navigator.clipboard.writeText(L).then(()=>{N(!0),setTimeout(()=>N(!1),1500)})},_=async()=>{await o.save.mutateAsync({build:{toolchainDirs:A.map(M=>M.trim()).filter(Boolean)}}),P(null),c.refetch()},Je=()=>{B("build"),h.start.mutate({repoUrl:i,branch:u,name:a})},Ze=()=>{B("cuda"),h.cuda.mutate()},en=d==="rebuild"?"Rebuild now":"Build it for me";return e.jsxs(he,{open:n,onOpenChange:s,children:[e.jsxs(fe,{className:"max-w-lg",children:[e.jsxs(q,{children:[e.jsxs(H,{children:[d==="rebuild"?"Rebuild":"Build"," ",a," from source"]}),e.jsx(ne,{children:d==="rebuild"?"A newer commit is available — recompile from source and replace the binary.":"No prebuilt binary for your system — compile it here, or build it yourself and add it."})]}),c.isLoading?e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:[e.jsx(G,{size:18,className:"shrink-0 animate-spin text-ink"}),"Checking your build tools…"]}):l===!1?e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"rounded-lg border border-border bg-panel p-4 text-[13px] text-muted",children:["In-app build is currently ",e.jsx("span",{className:"font-medium text-ink",children:"Windows + CUDA"})," only. On your system, clone the repo and follow its upstream build instructions, then add the resulting ",e.jsx("code",{className:"font-mono",children:"llama-server"})," binary via “Add your own engine”."]}),e.jsxs("a",{href:i,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 self-start text-[13px] text-accent hover:underline",children:["Open ",a," repo + build docs ",e.jsx(le,{size:13})]})]}):e.jsxs("div",{className:"flex max-h-[60vh] flex-col gap-4 overflow-y-auto",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("p",{className:"text-[11px] font-medium uppercase tracking-wide text-faint",children:"Build prerequisites"}),e.jsx("div",{className:"flex flex-col gap-1.5 rounded-lg border border-border bg-panel p-3",children:m.map(M=>e.jsx(Yn,{tool:M,onDownload:M.id==="cuda"&&!M.found&&!I?Ze:void 0},M.id))}),V&&!I&&e.jsxs("p",{className:"text-[11px] text-faint",children:["No CUDA Toolkit found. ",e.jsx("span",{className:"text-muted",children:"Download CUDA"})," grabs NVIDIA’s official build components (~0.5 GB) automatically — no installer needed."]})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("p",{className:"text-[11px] font-medium uppercase tracking-wide text-faint",children:"Build environment"}),e.jsxs("div",{className:"flex flex-col gap-2 rounded-lg border border-border bg-panel p-3",children:[e.jsxs("p",{className:"text-[12px] text-muted",children:["If your CUDA Toolkit or compiler lives in a conda env or a custom location (not on the system PATH), add that folder — e.g. the env’s ",e.jsx("code",{className:"font-mono",children:"bin"})," — so TurboLLM finds ",e.jsx("code",{className:"font-mono",children:"nvcc"}),". Then re-check."]}),A.map((M,re)=>e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("input",{value:M,onChange:je=>{const ee=[...A];ee[re]=je.target.value,P(ee)},placeholder:"C:\\\\Users\\\\you\\\\miniconda3\\\\envs\\\\cuda\\\\Library\\\\bin",className:"min-w-0 flex-1 rounded-md border border-border bg-panel-2 px-2 py-1 font-mono text-[12px] text-ink outline-none focus:border-accent"}),e.jsx("button",{type:"button",onClick:()=>P(A.filter((je,ee)=>ee!==re)),className:"shrink-0 rounded-md p-1 text-faint hover:text-ink","aria-label":"Remove folder",children:e.jsx(mn,{size:14})})]},re)),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("button",{type:"button",onClick:()=>P([...A,""]),className:"inline-flex items-center gap-1 text-[12px] text-muted hover:text-ink",children:[e.jsx(qe,{size:13})," Add folder"]}),e.jsxs("button",{type:"button",onClick:()=>{_()},disabled:o.save.isPending||c.isFetching,className:"inline-flex items-center gap-1 text-[12px] text-accent hover:underline disabled:opacity-50",children:[o.save.isPending||c.isFetching?e.jsx(G,{size:13,className:"animate-spin"}):e.jsx(He,{size:13}),"Re-check"]})]})]})]}),I&&r&&e.jsx(Vn,{build:r,kind:k==="cuda"?"cuda":"build",logRef:y,onCancel:()=>h.cancel.mutate(),onClose:()=>s(!1)}),e.jsxs("details",{className:"group",children:[e.jsx("summary",{className:"cursor-pointer list-none text-[11px] font-medium uppercase tracking-wide text-faint hover:text-muted",children:"Or build it yourself (manual commands)"}),e.jsxs("div",{className:"mt-1.5 flex flex-col gap-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-[11px] text-faint",children:"Windows + CUDA"}),e.jsxs("button",{type:"button",onClick:O,className:"inline-flex items-center gap-1 text-[12px] text-muted hover:text-ink",children:[x?e.jsx(W,{size:13,style:{color:"var(--ok)"}}):e.jsx(wn,{size:13}),x?"Copied":"Copy"]})]}),e.jsx("pre",{className:"overflow-x-auto rounded-lg border border-border bg-panel-2 p-3 font-mono text-[12px] leading-relaxed text-ink",children:L})]})]})]}),e.jsxs(K,{children:[e.jsx(S,{variant:"outline",onClick:()=>s(!1),children:"Close"}),l!==!1&&e.jsxs(e.Fragment,{children:[e.jsx(S,{variant:"outline",onClick:()=>w(!0),disabled:c.isLoading||j,children:"I've built it"}),e.jsxs(S,{onClick:Je,disabled:!p,children:[e.jsx($n,{size:15,className:"mr-1.5"}),j?"Building…":en]})]})]})]}),e.jsx(be,{open:f,onOpenChange:w,defaultSourceRepo:i,trigger:null})]})}function Vn({build:n,kind:s,logRef:i,onCancel:a,onClose:u}){const d=n.phase==="error",c=n.phase==="done",o=d?"var(--err, #ef4444)":c?"var(--ok)":"var(--accent)";return c&&s==="build"?e.jsxs("div",{className:"flex flex-col items-center gap-3 rounded-lg border p-5 text-center",style:{borderColor:"color-mix(in srgb, var(--ok) 40%, var(--border))",background:"color-mix(in srgb, var(--ok) 8%, transparent)"},children:[e.jsx("div",{className:"flex h-12 w-12 items-center justify-center rounded-full",style:{background:"color-mix(in srgb, var(--ok) 18%, transparent)"},children:e.jsx(W,{size:28,style:{color:"var(--ok)"}})}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("p",{className:"text-[15px] font-semibold text-ink",children:"Engine ready 🎉"}),e.jsxs("p",{className:"text-[13px] text-muted",children:[e.jsx("span",{className:"font-medium text-ink",children:n.engine})," was built from source, bundled with its CUDA runtime, and set as your active engine. Load a model to start using it."]})]}),e.jsxs("details",{className:"w-full",children:[e.jsx("summary",{className:"cursor-pointer list-none text-[11px] uppercase tracking-wide text-faint hover:text-muted",children:"Build log"}),e.jsx("pre",{className:"mt-1.5 max-h-40 overflow-auto rounded-md border border-border bg-panel-2 p-2 text-left font-mono text-[11px] leading-relaxed text-muted",children:n.log.join(`
|
|
3
3
|
`)})]}),e.jsx(S,{onClick:u,className:"mt-1",children:"Done"})]}):e.jsxs("div",{className:"flex flex-col gap-2 rounded-lg border border-border bg-panel p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[13px]",children:[n.active?e.jsx(G,{size:15,className:"shrink-0 animate-spin",style:{color:o}}):d?e.jsx(Ve,{size:15,className:"shrink-0",style:{color:o}}):e.jsx(W,{size:15,className:"shrink-0",style:{color:o}}),e.jsx("span",{className:"text-ink",children:Gn[n.phase]}),n.active&&e.jsx("button",{type:"button",onClick:a,className:"ml-auto text-[12px] text-faint hover:text-ink",children:"Cancel"})]}),d&&n.error&&e.jsx("p",{className:"text-[12px]",style:{color:o},children:n.error}),n.log.length>0&&e.jsx("pre",{ref:i,className:"max-h-40 overflow-auto rounded-md border border-border bg-panel-2 p-2 font-mono text-[11px] leading-relaxed text-muted",children:n.log.join(`
|
|
4
4
|
`)})]})}function Yn({tool:n,onDownload:s}){return e.jsxs("div",{className:"flex items-center gap-2 text-[13px]",children:[n.found?e.jsx(W,{size:15,className:"shrink-0",style:{color:"var(--ok)"}}):e.jsx(Ve,{size:15,className:"shrink-0 text-faint"}),e.jsx("span",{className:"text-ink",children:n.name}),n.found&&n.version&&e.jsx("span",{className:"text-[12px] text-muted",children:n.version}),!n.found&&e.jsxs("span",{className:"ml-auto inline-flex items-center gap-3",children:[s&&e.jsxs("button",{type:"button",onClick:s,className:"inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-[12px] font-medium transition-colors hover:opacity-80",style:{background:"color-mix(in srgb, var(--accent) 15%, transparent)",color:"var(--accent)"},children:[e.jsx(Q,{size:12})," Download CUDA"]}),e.jsxs("a",{href:n.installUrl,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 text-[12px] text-accent hover:underline",children:[s?"or install manually":"Install"," ",e.jsx(le,{size:11})]})]})]})}function Kn({status:n,activeEngineName:s}){const i=n?.engine.state??"stopped",a=n?.engine.error,u=n?.model?.loadElapsedMs,d=i==="running"?n?.engineStats??null:null,c=i==="running"?n?.liveGeneration??null:null,o=xn(),g=Z(),h=i==="running"||i==="starting",x=i==="running"||i==="error",N=()=>o.eject.mutate(void 0,{onError:w=>v.error(w instanceof C?w.message:"Could not stop the engine.")}),f=()=>g.restart.mutate(void 0,{onError:w=>v.error(w instanceof C?w.message:"Could not restart the engine.")});return e.jsxs("div",{className:"rounded-[var(--radius)] border border-[color:var(--accent)] bg-panel p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[12px] text-muted",children:"Active engine"}),e.jsx("div",{className:"text-sm font-semibold text-ink",children:s??"None active"})]}),e.jsx(pn,{state:i}),i==="starting"&&u!=null&&e.jsxs("span",{className:"text-[13px] text-muted",children:["Loading model… (",Math.round(u/1e3),"s)"]}),i==="running"&&n?.model&&e.jsx("span",{className:"text-[13px] text-muted truncate",children:n.model.name}),i==="running"&&!c&&(d?.activeRequests??0)>0&&e.jsxs("span",{className:"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[12px] font-medium",style:{background:"color-mix(in srgb, var(--accent) 12%, transparent)",color:"var(--accent)"},title:"The engine is actively generating",children:[e.jsx("span",{className:"tllm-pulse inline-block h-1.5 w-1.5 rounded-full",style:{background:"var(--accent)"}}),"Generating",(d?.activeRequests??0)>1?` (${d?.activeRequests})`:"","…"]}),x&&e.jsxs(S,{size:"sm",variant:"outline",className:"ml-auto",onClick:f,disabled:g.restart.isPending,title:"Restart the engine",children:[e.jsx(Ye,{size:14}),"Restart"]}),h&&e.jsxs(S,{size:"sm",variant:"outline",className:x?"":"ml-auto",onClick:N,disabled:o.eject.isPending,title:"Stop the engine and unload the model",children:[e.jsx(Nn,{size:14}),"Stop & unload"]})]}),(c||d)&&e.jsx(Qn,{live:c,stats:d}),i==="error"&&a&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"mb-1.5 flex items-center justify-between",children:[e.jsxs("span",{className:"text-[13px] font-medium",style:{color:"var(--err)"},children:[a.message,a.exitCode!=null&&` (exit ${a.exitCode})`]}),e.jsx(Ge,{text:(a?.logTail??[]).join(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as T,X as ne,w as $,x as Ne,y as we,d as Se,z as Pe,E as Fe,a as Le,u as Ae,A as q,B as G,t as V}from"./index-sjgdofsd.js";import{b as Ee,j as e,c as Ge,d as Te,e as Re,f as ze,D as De}from"./radix-BFvMxQq9.js";import{r as v}from"./vendor-D_-14Whs.js";import{C as qe,A as Ue,p as $e,q as Be,r as Ke,s as _e,t as Ve,u as He,v as Ie}from"./dialog-Dpyml8ZT.js";import{E as Oe}from"./refresh-cw-BoAcjLtt.js";import{S as We}from"./save-DE1APWTG.js";const Qe=[["path",{d:"m12 14 4-4",key:"9kzdfg"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0",key:"19p75a"}]],Y=T("gauge",Qe);const Je=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Xe=T("rotate-ccw",Je);const Ze=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],St=T("search",Ze);const Ye=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],Pt=T("sliders-horizontal",Ye);const et=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],ae=T("zap",et);function ee(){return{splitMode:"layer",tensorSplit:[],mainGpu:-1,tensorParallelSize:1}}function tt(){return{maxModelLen:0,gpuMemoryUtilization:.9,maxNumSeqs:0,dtype:"auto",kvCacheDtype:"auto",enforceEager:!1,trustRemoteCode:!1}}const nt=128;function at(n,a){if(!n.length)return 0;if(a?.splitMode==="none"){const s=a.mainGpu>=0?a.mainGpu:0;return n[s]?.vramMb??n[0]?.vramMb??0}return n.reduce((s,r)=>s+(r.vramMb||0),0)}function st(n){switch(n){case"f16":return 2;case"q8_0":case"q8_1":return 1;case"q5_0":case"q5_1":return .625;case"q4_0":case"q4_1":case"turbo4":return .5;case"turbo3":return .375;case"turbo2":return .25;default:return 2}}function lt(n,a,s){if(!s)return{estMb:0,totalVramMb:0,pct:0,verdict:"cpu"};const r=a.sizeBytes/1e6,c=a.blockCount||1,i=a.moe?1-.85*(n.nCpuMoe/c):Math.min(n.ngl,c)/c,d=r*Math.max(0,Math.min(1,i)),f=2*c*n.ctx*(a.headCountKv||8)*nt*st(n.kvTypeK)/1e6*(n.kvUnified?1:Math.max(1,n.parallel)),j=n.useMmproj&&n.mmprojGpu&&a.mmprojPath?600:0,l=Math.round(d+f+800+j),g=l/s,R=g<=.8?"fits":g<=.95?"tight":"overflow";return{estMb:l,totalVramMb:s,pct:g,verdict:R}}const ot=Ee,se=v.forwardRef(({className:n,children:a,...s},r)=>e.jsx(Ge,{children:e.jsxs(Te,{ref:r,className:$("tllm-sheet fixed z-50 flex flex-col border-border bg-panel shadow-[var(--shadow-2)] focus:outline-none",n),...s,children:[a,e.jsx(Re,{className:"absolute right-4 top-4 rounded-sm text-muted hover:text-ink","aria-label":"Close",children:e.jsx(ne,{size:16})})]})}));se.displayName="SheetContent";function rt({className:n,...a}){return e.jsx("div",{className:$("mb-4 flex flex-col gap-1",n),...a})}const le=v.forwardRef(({className:n,...a},s)=>e.jsx(ze,{ref:s,className:$("text-[16px] font-semibold tracking-[-0.01em] text-ink",n),...a}));le.displayName="SheetTitle";const oe=v.forwardRef(({className:n,...a},s)=>e.jsx(De,{ref:s,className:$("text-[13px] text-muted",n),...a}));oe.displayName="SheetDescription";function it(n){switch(n){case"llama-server":return"llamacpp";case"mlx":return"mlx";case"vllm":return"vllm";default:return"none"}}function Ft({modelKey:n,onClose:a,onViewRepo:s}){const r=Ne(n),c=we(),i=Se(),d=Pe(),h=Fe(),[f,j]=v.useState(null),[l,g]=v.useState(null),[R,de]=v.useState(!1),[B,me]=v.useState(!0),pe=Le(),o=r.data,K=Ae().data?.engine.state;v.useEffect(()=>{o&&g(structuredClone(o.profile))},[o]),v.useEffect(()=>{if(!n)return;const t=document.documentElement,m=parseInt(ct()??"",10);if(m>0){const p=Math.min(Math.max(m,Q),ie());t.style.setProperty("--tllm-config-w",`${p}px`)}return t.classList.add("tllm-config-open"),()=>t.classList.remove("tllm-config-open")},[n]),v.useEffect(()=>{f&&(K==="stopped"||K==="error")&&(d.start.mutate({key:f,base:l??void 0}),j(null))},[f,K,d.start]);const S=c.data?.engines.find(t=>t.id===c.data?.activeEngineId),xe=S?.capabilities.kvTypes??["f16"],z=S?.capabilities.flags??[],F=t=>z.length===0||z.includes(t),J=t=>z.length===0||z.includes(`spec-type:${t}`),ue=(o?.arch??"").toLowerCase(),he=(o?.name??"").toLowerCase(),fe=/gemma4/.test(ue)||/gemma[ _-]?4/.test(he),ge=(o?.nextnLayers??0)>0,L=["off"];F("--spec-type")&&F("--mtp-head")&&fe&&L.push("mtp"),F("--spec-type")&&F("--model-draft")&&ge&&(J("nextn")||J("draft-mtp"))&&L.push("nextn"),F("--model-draft")&&L.push("draft");const D=v.useMemo(()=>!o||!l?null:lt(l,o,at(o.gpus??[],l.gpu)),[o,l]),x=(t,m)=>g(p=>p&&{...p,[t]:m}),C=(t,m)=>g(p=>p&&{...p,sampling:{...p.sampling,[t]:m}}),X=(t,m)=>g(p=>p&&{...p,gpu:{...p.gpu??ee(),[t]:m}}),M=(t,m)=>g(p=>p&&{...p,vllm:{...p.vllm??tt(),[t]:m}}),Z=i.load.error instanceof q?i.load.error.message:null,A=!!h&&h.modelKey===o?.key,ve=!!h?.running&&A,E=!!h?.done&&A&&!h.running,je=d.start.error instanceof q?d.start.error.message:null,_=it(S?.kind),P=_==="llamacpp",be=_==="mlx",ye=_==="vllm",ke=()=>{o&&(o.loaded?(j(o.key),i.eject.mutate()):d.start.mutate({key:o.key,base:l??void 0}))};v.useEffect(()=>{E&&o?.key&&pe.invalidateQueries({queryKey:["model",o.key]})},[E,o?.key]);const Ce=()=>{d.save.mutate(void 0,{onSuccess:()=>V.success("Tuned settings saved"),onError:t=>V.error(t instanceof q?t.message:"Could not save tuned settings.")}),a()},Me=()=>{d.cancel.mutate(),a()};return e.jsxs(e.Fragment,{children:[e.jsx(ot,{open:!!n,onOpenChange:t=>!t&&a(),modal:!1,children:e.jsxs(se,{className:"overflow-y-auto p-5 slim-scroll",onPointerDownOutside:t=>t.preventDefault(),onInteractOutside:t=>t.preventDefault(),children:[e.jsx(dt,{}),e.jsxs(rt,{children:[e.jsx(le,{className:"truncate",children:o?.name??"Model"}),e.jsx(oe,{children:o?`${o.arch} · ${o.quant} · ${jt(o.sizeBytes)}`:"Load settings"}),o?.sourceRepo&&s&&e.jsxs("button",{type:"button",onClick:()=>s(o.sourceRepo),className:"mt-1 inline-flex w-fit items-center gap-1 text-[12px] font-medium text-accent hover:underline",title:`View ${o.sourceRepo} on Hugging Face`,children:[e.jsx(Oe,{size:12})," Model card & quants on Hugging Face"]})]}),!o||!l?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"Loading…"}):e.jsxs("div",{className:"flex flex-col gap-4",children:[D&&e.jsx(pt,{estMb:D.estMb,totalMb:D.totalVramMb,verdict:D.verdict}),P&&o.gpu&&e.jsx(xt,{running:ve,done:E,step:A?h?.step:void 0,bestTps:A?h?.bestTps:void 0,resultError:E?h?.error:void 0,benchTps:o.benchTps,tuned:l.tunedBy==="bench",loaded:o.loaded,startError:je,pending:d.start.isPending||f!==null,onStart:ke,onCancel:()=>d.cancel.mutate()}),be&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px] text-muted",children:["MLX (Apple Silicon, mlx-lm) manages context and KV cache automatically — there are no context/GPU-layer/KV knobs to set. Only the ",e.jsx("span",{className:"text-ink",children:"sampling defaults"})," below apply at load; per-conversation overrides still work in chat."]}),ye&&e.jsxs(N,{children:[e.jsx(u,{label:"Max model length",hint:"vLLM --max-model-len. Max context tokens. 0 = derive from the model config.",children:e.jsx(k,{value:l.vllm?.maxModelLen??0,min:0,max:Math.max(0,o.nativeCtx||0),step:1024,onChange:t=>M("maxModelLen",t)})}),e.jsx(b,{label:"GPU memory utilization",hint:"vLLM --gpu-memory-utilization. Fraction of VRAM vLLM may reserve. Lower it to share the GPU.",value:Math.round((l.vllm?.gpuMemoryUtilization??.9)*100),min:10,max:100,step:5,onChange:t=>M("gpuMemoryUtilization",t/100),fmt:t=>`${t}%`}),e.jsx(u,{label:"Max concurrent sequences",hint:"vLLM --max-num-seqs. Requests served in parallel. 0 = vLLM default.",children:e.jsx(k,{value:l.vllm?.maxNumSeqs??0,min:0,max:1024,step:1,onChange:t=>M("maxNumSeqs",t)})}),e.jsx(u,{label:"Compute dtype",hint:"vLLM --dtype. 'auto' follows the model's config.",children:e.jsx(O,{value:l.vllm?.dtype??"auto",options:["auto","bfloat16","float16","float32"],onChange:t=>M("dtype",t)})}),e.jsx(u,{label:"KV cache dtype",hint:"vLLM --kv-cache-dtype. fp8 roughly halves KV-cache memory.",children:e.jsx(O,{value:l.vllm?.kvCacheDtype??"auto",options:["auto","fp8"],onChange:t=>M("kvCacheDtype",t)})}),e.jsx(w,{label:"Enforce eager",hint:"vLLM --enforce-eager. Skips CUDA graphs: less VRAM, somewhat slower.",value:l.vllm?.enforceEager??!1,onChange:t=>M("enforceEager",t)}),e.jsx(w,{label:"Trust remote code",hint:"vLLM --trust-remote-code. Needed for models that ship custom modelling code.",value:l.vllm?.trustRemoteCode??!1,onChange:t=>M("trustRemoteCode",t)})]}),P&&e.jsxs(N,{children:[e.jsx(b,{label:"Context length",hint:"Tokens of history the model can use.",value:l.ctx,min:512,max:Math.max(512,o.nativeCtx||8192),step:512,onChange:t=>x("ctx",t),fmt:t=>t.toLocaleString()}),o.gpu&&e.jsx(b,{label:"GPU layers",hint:o.blockCount>0?`${o.blockCount} total layers.`:"All layers on GPU = max performance.",value:l.ngl,min:0,max:o.blockCount>0?o.blockCount:99,step:1,onChange:t=>x("ngl",t),fmt:t=>t>=(o.blockCount>0?o.blockCount:99)?"All":String(t)}),o.moe&&o.blockCount>0&&e.jsx(b,{label:"MoE experts on CPU",hint:"Higher = less VRAM, slower. Lower = faster if it fits.",value:l.nCpuMoe,min:0,max:o.blockCount,step:1,onChange:t=>x("nCpuMoe",t)}),e.jsx(u,{label:"Context overflow",hint:"What to do when the context window fills up.",children:e.jsx(U,{value:l.contextOverflow,options:["shift","keep"],onChange:t=>x("contextOverflow",t)})}),l.contextOverflow==="keep"&&e.jsx(u,{label:"Tokens to keep",hint:"Preserve this many tokens from the start (e.g. system prompt length) when shifting.",children:e.jsx(k,{value:l.nKeep,min:0,max:l.ctx,onChange:t=>x("nKeep",t)})})]}),o.gpus&&o.gpus.length>1&&(S?.kind==="llama-server"||S?.kind==="vllm")&&e.jsxs(e.Fragment,{children:[e.jsxs(I,{children:["Multi-GPU · ",o.gpus.length," GPUs"]}),e.jsx(N,{children:S.kind==="vllm"?e.jsx(u,{label:"Tensor parallel size",hint:"Shard the model across this many GPUs.",children:e.jsx(k,{value:l.gpu?.tensorParallelSize??1,min:1,max:o.gpus.length,onChange:t=>X("tensorParallelSize",t)})}):e.jsx(ut,{gpus:o.gpus,gpu:l.gpu??ee(),setG:X})})]}),P&&e.jsxs(N,{children:[e.jsx(u,{label:"Parallel slots",children:e.jsx(k,{value:l.parallel,min:1,max:16,onChange:t=>x("parallel",t)})}),e.jsx(u,{label:"KV cache type",hint:"turbo* are TurboQuant-fork exclusive.",children:e.jsx(O,{value:l.kvTypeK,options:xe,onChange:t=>g(m=>m&&{...m,kvTypeK:t,kvTypeV:t})})}),e.jsx(u,{label:"Flash attention",children:e.jsx(U,{value:l.flashAttn,options:["auto","on","off"],onChange:t=>x("flashAttn",t)})}),e.jsx(w,{label:"Use Jinja chat template",value:l.useJinja,onChange:t=>x("useJinja",t)}),l.useJinja&&e.jsx(W,{label:"Template file path (optional)",hint:"Leave empty to use model's built-in template.",value:l.chatTemplateFile,placeholder:"Path to .jinja template file",onChange:t=>x("chatTemplateFile",t)})]}),e.jsx(I,{children:"Sampling"}),e.jsxs(N,{children:[e.jsx(b,{label:"Temperature",value:l.sampling.temp,min:0,max:2,step:.05,onChange:t=>C("temp",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Top P",value:l.sampling.topP,min:0,max:1,step:.01,onChange:t=>C("topP",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Top K",value:l.sampling.topK,min:0,max:200,step:1,onChange:t=>C("topK",t)}),e.jsx(b,{label:"Min P",value:l.sampling.minP,min:0,max:1,step:.01,onChange:t=>C("minP",t),fmt:t=>t.toFixed(2)}),P&&e.jsxs(e.Fragment,{children:[e.jsx(b,{label:"Repeat penalty",hint:"Penalise tokens that appeared earlier. 1.0 = off.",value:l.sampling.repeatPenalty,min:1,max:2,step:.05,onChange:t=>C("repeatPenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Presence penalty",hint:"Flat penalty for any token that appeared. 0 = off.",value:l.sampling.presencePenalty,min:0,max:2,step:.05,onChange:t=>C("presencePenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Frequency penalty",hint:"Penalty proportional to how often a token appeared. 0 = off.",value:l.sampling.frequencyPenalty,min:0,max:2,step:.05,onChange:t=>C("frequencyPenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(u,{label:"Stop strings",hint:"Halt generation when any of these sequences is produced.",children:e.jsx("div",{className:"w-full"})}),e.jsx(gt,{value:l.sampling.stop,onChange:t=>g(m=>m&&{...m,sampling:{...m.sampling,stop:t}})})]})]}),P&&L.length>1&&e.jsxs(e.Fragment,{children:[e.jsx(I,{children:"Speculative decoding"}),e.jsxs(N,{children:[e.jsx(u,{label:"Mode",hint:"Predict extra tokens per step — faster generation.",children:e.jsx(ft,{value:l.speculative,options:L,onChange:t=>x("speculative",t)})}),l.speculative==="mtp"&&e.jsx(W,{label:"MTP head GGUF",hint:"Gemma-4 assistant model file.",value:l.mtpHeadPath,placeholder:"Path to gemma-4-mtp-assistant.gguf",onChange:t=>x("mtpHeadPath",t)}),l.speculative==="nextn"&&e.jsx("p",{className:"text-[11px] text-faint",children:"Uses this model's built-in NextN head — no extra file needed."}),l.speculative==="draft"&&e.jsx(W,{label:"Draft model GGUF",hint:"A small same-family model.",value:l.draftModelPath,placeholder:"Path to small draft model",onChange:t=>x("draftModelPath",t)})]})]}),P&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",onClick:()=>de(t=>!t),className:"flex items-center gap-1 text-[13px] font-medium text-muted hover:text-ink",children:[e.jsx(qe,{size:14,className:R?"rotate-180 transition-transform":"transition-transform"}),"Advanced"]}),R&&e.jsxs(N,{children:[e.jsx(b,{label:"CPU threads",hint:l.threads===0?`Auto — half your cores (${vt(o.cores)} of ${o.cores||"?"})`:`${l.threads} of ${o.cores||"?"} cores`,value:l.threads,min:0,max:Math.max(1,o.cores||64),step:1,onChange:t=>x("threads",t),fmt:t=>t===0?"Auto":String(t)}),e.jsx(w,{label:"Reuse cached prompt",hint:"Skips re-processing the unchanged start of a prompt on repeated or continued requests — faster first token. Recommended on.",value:l.cacheReuse>0,onChange:t=>x("cacheReuse",t?256:0)}),o.vision&&e.jsx(w,{label:"Vision encoder on GPU",value:l.mmprojGpu,onChange:t=>x("mmprojGpu",t)}),l.parallel>1&&e.jsx(w,{label:"Unified KV across slots",value:l.kvUnified,onChange:t=>x("kvUnified",t)}),e.jsx(u,{label:"RoPE scaling",hint:"Extend context beyond the model's trained limit. 'none' = model native.",children:e.jsx(U,{value:l.ropeScalingType,options:["none","linear","yarn"],onChange:t=>x("ropeScalingType",t)})}),l.ropeScalingType!=="none"&&e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"RoPE freq base",hint:"Base frequency override. 0 = model native.",children:e.jsx(k,{value:l.ropeFreqBase,min:0,max:1e7,onChange:t=>x("ropeFreqBase",t)})}),e.jsx(u,{label:"RoPE freq scale",hint:"Frequency scale. 0 = model native; e.g. 0.25 for 4× context.",children:e.jsx(k,{value:l.ropeFreqScale,min:0,max:10,step:.01,onChange:t=>x("ropeFreqScale",t)})})]})]})]}),Z&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:Z}),e.jsxs("label",{className:"flex cursor-pointer items-center gap-2 pt-1 text-[13px] text-ink",children:[e.jsx("input",{type:"checkbox",checked:B,onChange:t=>me(t.target.checked),className:"h-4 w-4 accent-[var(--accent)]"}),"Remember these settings",e.jsx("span",{className:"text-[11px] text-faint",children:B?"· saved as this model's default":"· this load only"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(G,{className:"flex-1",onClick:()=>{const t=()=>i.load.mutate({key:o.key,overrides:l},{onError:m=>V.error(m instanceof q?`Could not load model: ${m.message}`:"Could not load model — check the engine logs on the Engines screen.")});B?i.save.mutate({key:o.key,profile:l},{onSuccess:t,onError:t}):t(),a()},disabled:i.load.isPending,children:[e.jsx(ae,{size:14}),o.loaded?"Reload":"Load model"]}),e.jsxs(G,{variant:"outline",onClick:()=>i.save.mutate({key:o.key,profile:l}),disabled:i.save.isPending,title:"Save without reloading",children:[e.jsx(We,{size:14}),"Save"]}),e.jsx(G,{variant:"ghost",onClick:()=>i.reset.mutate(o.key),disabled:i.reset.isPending,title:"Reset to defaults",children:e.jsx(Xe,{size:14})})]})]})]})}),e.jsx(mt,{result:E&&A?h?.result:void 0,modelName:o?.name,onSave:Ce,onCancel:Me})]})}const re="tllm-config-w",Q=360;function ie(){return Math.max(Q,Math.min(760,window.innerWidth-220))}function ct(){try{return localStorage.getItem(re)}catch{return null}}function dt(){const n=a=>{if(a.button!==0)return;a.preventDefault();const s=document.documentElement;s.classList.add("tllm-config-resizing");const r=i=>{const d=Math.min(Math.max(window.innerWidth-i.clientX,Q),ie());s.style.setProperty("--tllm-config-w",`${Math.round(d)}px`)},c=()=>{s.classList.remove("tllm-config-resizing"),window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",c);try{localStorage.setItem(re,getComputedStyle(s).getPropertyValue("--tllm-config-w").trim())}catch{}};window.addEventListener("pointermove",r),window.addEventListener("pointerup",c)};return e.jsx("div",{className:"tllm-config-resizer",onPointerDown:n,role:"separator","aria-orientation":"vertical","aria-label":"Resize panel"})}function y({label:n,value:a,tag:s}){return e.jsxs("div",{className:"flex items-center justify-between gap-3 py-[3px]",children:[e.jsx("span",{className:"text-muted",children:n}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[s&&e.jsx("span",{className:"rounded px-1 py-0.5 text-[10px] font-medium uppercase tracking-wide",style:{color:"var(--accent)",background:"color-mix(in srgb, var(--accent) 12%, transparent)"},children:s}),e.jsx("span",{className:"font-mono text-ink",children:a})]})]})}function H({title:n}){return e.jsx("div",{className:"mt-2 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wide text-faint first:mt-0 first:pt-0",children:n})}function mt({result:n,modelName:a,onSave:s,onCancel:r}){const c=n?.recommendedSampling,i=n?.sampling,d=j=>c?.[j]!=null,h=!!c&&(c.temp!=null||c.topP!=null||c.topK!=null||c.minP!=null),f=[{label:"Temperature",key:"temp"},{label:"Top-K",key:"topK"},{label:"Top-P",key:"topP"},{label:"Min-P",key:"minP"}];return e.jsx(Ue,{open:!!n,onOpenChange:j=>{j||r()},children:e.jsxs($e,{children:[e.jsxs(Be,{children:[e.jsx(Ke,{children:"Auto-tune complete"}),e.jsx(_e,{asChild:!0,children:e.jsxs("div",{className:"flex flex-col gap-2.5 text-[13px]",children:[e.jsxs("span",{className:"text-muted",children:["Fastest config found on your machine —"," ",e.jsxs("span",{className:"font-mono font-medium",style:{color:"var(--ok)"},children:[n?.tps.toFixed(1)," tok/s"]}),". Save applies this complete config to ",a??"this model",":"]}),n&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-1.5",children:[e.jsx(H,{title:"Runtime"}),e.jsx(y,{label:"GPU layers",value:n.params.ngl}),n.params.nCpuMoe>0&&e.jsx(y,{label:"MoE experts on CPU",value:n.params.nCpuMoe}),e.jsx(y,{label:"Context length",value:`${n.params.ctx.toLocaleString()} tok`}),e.jsx(y,{label:"KV cache type",value:n.params.kvTypeK}),e.jsx(y,{label:"Flash attention",value:n.params.flashAttn}),n.params.parallel>1&&e.jsx(y,{label:"Parallel slots",value:n.params.parallel}),e.jsx(H,{title:"Sampling"}),i?f.map(({label:j,key:l})=>e.jsx(y,{label:j,value:i[l]??"—",tag:d(l)?"from card":void 0},l)):e.jsx(y,{label:"Sampling",value:"model defaults"}),e.jsx(H,{title:"Measured"}),e.jsx(y,{label:"Speed",value:`${n.tps.toFixed(1)} tok/s`}),n.vramMb!=null&&e.jsx(y,{label:"VRAM used",value:`~${n.vramMb.toLocaleString()} MB`}),n.ttftMs?e.jsx(y,{label:"First token",value:`${Math.round(n.ttftMs)} ms`}):null]}),e.jsxs("span",{className:"text-faint",children:[h?e.jsxs(e.Fragment,{children:["Values tagged ",e.jsx("span",{style:{color:"var(--accent)"},children:"from card"})," were read from the model's Hugging Face page. "]}):e.jsx(e.Fragment,{children:"No sampling recommendation was found on the model's card — sampling stays at your current values. "}),"Change any of these later in Sampling."]})]})})]}),e.jsxs(Ve,{children:[e.jsx(He,{onClick:r,children:"Cancel"}),e.jsx(Ie,{onClick:s,children:"Save"})]})]})})}function pt({estMb:n,totalMb:a,verdict:s}){if(s==="cpu"||a===0)return e.jsx("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2 text-[12px] text-muted",children:"CPU-only — no GPU detected."});const r=s==="fits"?"var(--ok)":s==="tight"?"var(--warn)":"var(--err)",c=Math.min(100,Math.round(n/a*100)),i=s==="overflow"?"will spill to system RAM — expect severe slowdown":s==="tight"?"may slow under desktop load":"fits comfortably";return e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5",children:[e.jsxs("div",{className:"mb-1.5 flex items-center justify-between text-[12px]",children:[e.jsx("span",{className:"text-muted",children:"Estimated VRAM"}),e.jsxs("span",{style:{color:r},children:["~",(n/1e3).toFixed(1)," / ",(a/1e3).toFixed(1)," GB · ",i]})]}),e.jsx("div",{className:"h-2 overflow-hidden rounded-full",style:{background:"var(--border)"},children:e.jsx("div",{className:"h-full rounded-full transition-all",style:{width:`${c}%`,background:r}})})]})}function xt({running:n,done:a,step:s,bestTps:r,resultError:c,benchTps:i,tuned:d,loaded:h,startError:f,pending:j,onStart:l,onCancel:g}){return e.jsx("div",{className:"rounded-lg border border-border bg-panel p-3",children:n?e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[13px] text-ink",children:[e.jsx(Y,{size:14,className:"animate-pulse",style:{color:"var(--accent)"}}),"Auto-tuning…"]}),e.jsxs(G,{variant:"outline",onClick:g,children:[e.jsx(ne,{size:14}),"Cancel"]})]}),e.jsx("p",{className:"font-mono text-[12px] text-muted",children:s??"Preparing…"}),r!==void 0&&e.jsxs("p",{className:"text-[12px] text-ink",children:["Best so far: ",e.jsxs("span",{className:"font-mono",style:{color:"var(--ok)"},children:[r.toFixed(1)," tok/s"]})]})]}):e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[13px] font-medium text-ink",children:[e.jsx(Y,{size:14,style:{color:"var(--accent)"}}),"Auto-tune"]}),e.jsx("p",{className:"text-[11px] text-faint",children:i!==null?`Tuned: ${i.toFixed(1)} tok/s on your machine${d?" · settings applied below":""}`:"Measures real speed on your hardware and saves the fastest settings (~3 min)."})]}),e.jsxs(G,{variant:"outline",onClick:l,disabled:j,children:[e.jsx(ae,{size:14}),h?"Stop & benchmark":"Auto-tune"]})]}),a&&r!==void 0&&!c&&e.jsxs("p",{className:"text-[12px] text-ink",children:["Done — ",e.jsxs("span",{className:"font-mono",style:{color:"var(--ok)"},children:[r.toFixed(1)," tok/s"]}),". Saved as this model's default."]}),a&&c&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--warn)"},children:c}),f&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:f})]})})}function N({children:n}){return e.jsx("div",{className:"flex flex-col gap-3 rounded-lg border border-border bg-panel p-3",children:n})}function I({children:n}){return e.jsx("div",{className:"text-[12px] font-semibold uppercase tracking-wide text-faint",children:n})}function b({label:n,hint:a,value:s,min:r,max:c,step:i,onChange:d,fmt:h}){return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-1 flex items-baseline justify-between",children:[e.jsx("span",{className:"text-[13px] text-ink",children:n}),e.jsx("span",{className:"font-mono text-[12px] text-muted",children:h?h(s):s})]}),e.jsx("input",{type:"range",min:r,max:c,step:i,value:s,onChange:f=>d(Number(f.target.value)),className:"w-full accent-[var(--accent)]"}),a&&e.jsx("p",{className:"mt-0.5 text-[11px] text-faint",children:a})]})}function u({label:n,hint:a,children:s}){return e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[13px] text-ink",children:n}),a&&e.jsx("div",{className:"text-[11px] text-faint",children:a})]}),s]})}function k({value:n,min:a,max:s,step:r=1,onChange:c}){return e.jsx("input",{type:"number",min:a,max:s,step:r,value:n,onChange:i=>c(Math.max(a,Math.min(s,Number(i.target.value)||a))),className:"w-20 rounded-md border border-border bg-bg px-2 py-1 text-right text-[13px] text-ink outline-none"})}function O({value:n,options:a,onChange:s}){return e.jsx("select",{value:n,onChange:r=>s(r.target.value),className:"rounded-md border border-border bg-bg px-2 py-1 text-[13px] text-ink outline-none",children:a.map(r=>e.jsx("option",{value:r,children:r},r))})}function U({value:n,options:a,onChange:s}){return e.jsx("div",{className:"flex overflow-hidden rounded-md border border-border",children:a.map(r=>e.jsx("button",{type:"button",onClick:()=>s(r),className:"px-2.5 py-1 text-[12px] capitalize transition-colors",style:{background:n===r?"var(--accent)":"transparent",color:n===r?"var(--on-accent)":"var(--muted)"},children:r},r))})}function ce(n,a){const s=n.vramMb?` (${Math.round(n.vramMb/1024)} GB)`:"";return`GPU ${a}${n.name?` · ${n.name}`:""}${s}`}function te({gpus:n,value:a,allowAuto:s,onChange:r}){return e.jsxs("select",{value:String(a),onChange:c=>r(Number(c.target.value)),className:"max-w-[260px] rounded-md border border-border bg-bg px-2 py-1 text-[13px] text-ink outline-none",children:[s&&e.jsx("option",{value:"-1",children:"Auto"}),n.map((c,i)=>e.jsx("option",{value:String(i),children:ce(c,i)},i))]})}function ut({gpus:n,gpu:a,setG:s}){const r=a.tensorSplit.length>0;return e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"Split mode",hint:"layer = by layers (default) · row = tensor-parallel · none = single GPU.",children:e.jsx(U,{value:a.splitMode,options:["layer","row","none"],onChange:c=>s("splitMode",c)})}),a.splitMode==="none"?e.jsx(u,{label:"GPU",hint:"Which GPU to load the model on.",children:e.jsx(te,{gpus:n,value:a.mainGpu>=0?a.mainGpu:0,allowAuto:!1,onChange:c=>s("mainGpu",c)})}):e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"Main GPU",hint:"Holds the KV cache / small tensors. Auto lets the engine choose.",children:e.jsx(te,{gpus:n,value:a.mainGpu,allowAuto:!0,onChange:c=>s("mainGpu",c)})}),e.jsx(w,{label:"Custom GPU split",hint:"Off = even split across GPUs. On = set each GPU's share.",value:r,onChange:c=>s("tensorSplit",c?n.map(()=>1):[])}),r&&e.jsx("div",{className:"flex flex-col gap-2 pl-1",children:n.map((c,i)=>e.jsx(u,{label:ce(c,i),children:e.jsx(k,{value:a.tensorSplit[i]??0,min:0,max:100,onChange:d=>s("tensorSplit",n.map((h,f)=>f===i?d:a.tensorSplit[f]??0))})},i))})]})]})}const ht={off:"Off",mtp:"MTP",nextn:"NextN",draft:"Draft"};function ft({value:n,options:a,onChange:s}){return e.jsx("div",{className:"flex overflow-hidden rounded-md border border-border",children:a.map(r=>e.jsx("button",{type:"button",onClick:()=>s(r),className:"px-2.5 py-1 text-[12px] transition-colors",style:{background:n===r?"var(--accent)":"transparent",color:n===r?"var(--on-accent)":"var(--muted)"},children:ht[r]},r))})}function W({label:n,hint:a,value:s,placeholder:r,onChange:c}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"text-[12px] text-ink",children:[n,a&&e.jsx("span",{className:"ml-1 text-faint",children:a})]}),e.jsx("input",{type:"text",value:s,placeholder:r,onChange:i=>c(i.target.value),className:"w-full rounded-md border border-border bg-bg px-2 py-1 font-mono text-[12px] text-ink outline-none placeholder:text-faint"})]})}function gt({value:n,onChange:a}){const[s,r]=v.useState(""),c=i=>{const d=i.trim();d&&!n.includes(d)&&a([...n,d]),r("")};return e.jsxs("div",{className:"flex flex-col gap-1.5",children:[n.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1",children:n.map(i=>e.jsxs("span",{className:"flex items-center gap-0.5 rounded border border-border bg-panel-2 px-1.5 py-0.5 font-mono text-[11px] text-ink",children:[i,e.jsx("button",{type:"button",onClick:()=>a(n.filter(d=>d!==i)),className:"ml-0.5 text-muted hover:text-[var(--err)]",children:"×"})]},i))}),e.jsx("input",{type:"text",value:s,placeholder:n.length?"Add another…":"Type a stop string, press Enter",onChange:i=>r(i.target.value),onKeyDown:i=>{i.key==="Enter"&&(i.preventDefault(),c(s)),i.key==="Backspace"&&!s&&n.length&&a(n.slice(0,-1))},onBlur:()=>{s.trim()&&c(s)},className:"w-full rounded-md border border-border bg-bg px-2 py-1 font-mono text-[12px] text-ink outline-none placeholder:text-faint"})]})}function w({label:n,hint:a,value:s,onChange:r}){return e.jsxs("label",{className:"flex cursor-pointer items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"text-[13px] text-ink",children:n}),a&&e.jsx("p",{className:"text-[11px] text-faint",children:a})]}),e.jsx("input",{type:"checkbox",checked:s,onChange:c=>r(c.target.checked),className:"h-4 w-4 shrink-0 accent-[var(--accent)]"})]})}function vt(n){return Math.max(1,Math.floor((n||2)/2))}function jt(n){return n>=1e9?`${(n/1e9).toFixed(1)} GB`:`${Math.round(n/1e6)} MB`}export{Ft as M,St as S,ae as Z,Pt as a};
|
|
1
|
+
import{c as T,X as ne,w as $,x as Ne,y as we,d as Se,z as Pe,E as Fe,a as Le,u as Ae,A as q,B as G,t as V}from"./index-DdsLEQg8.js";import{b as Ee,j as e,c as Ge,d as Te,e as Re,f as ze,D as De}from"./radix-BFvMxQq9.js";import{r as v}from"./vendor-D_-14Whs.js";import{C as qe,A as Ue,p as $e,q as Be,r as Ke,s as _e,t as Ve,u as He,v as Ie}from"./dialog-oym6ZR4Z.js";import{E as Oe}from"./refresh-cw-35eljdhP.js";import{S as We}from"./save-AXon2pXP.js";const Qe=[["path",{d:"m12 14 4-4",key:"9kzdfg"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0",key:"19p75a"}]],Y=T("gauge",Qe);const Je=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Xe=T("rotate-ccw",Je);const Ze=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],St=T("search",Ze);const Ye=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],Pt=T("sliders-horizontal",Ye);const et=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],ae=T("zap",et);function ee(){return{splitMode:"layer",tensorSplit:[],mainGpu:-1,tensorParallelSize:1}}function tt(){return{maxModelLen:0,gpuMemoryUtilization:.9,maxNumSeqs:0,dtype:"auto",kvCacheDtype:"auto",enforceEager:!1,trustRemoteCode:!1}}const nt=128;function at(n,a){if(!n.length)return 0;if(a?.splitMode==="none"){const s=a.mainGpu>=0?a.mainGpu:0;return n[s]?.vramMb??n[0]?.vramMb??0}return n.reduce((s,r)=>s+(r.vramMb||0),0)}function st(n){switch(n){case"f16":return 2;case"q8_0":case"q8_1":return 1;case"q5_0":case"q5_1":return .625;case"q4_0":case"q4_1":case"turbo4":return .5;case"turbo3":return .375;case"turbo2":return .25;default:return 2}}function lt(n,a,s){if(!s)return{estMb:0,totalVramMb:0,pct:0,verdict:"cpu"};const r=a.sizeBytes/1e6,c=a.blockCount||1,i=a.moe?1-.85*(n.nCpuMoe/c):Math.min(n.ngl,c)/c,d=r*Math.max(0,Math.min(1,i)),f=2*c*n.ctx*(a.headCountKv||8)*nt*st(n.kvTypeK)/1e6*(n.kvUnified?1:Math.max(1,n.parallel)),j=n.useMmproj&&n.mmprojGpu&&a.mmprojPath?600:0,l=Math.round(d+f+800+j),g=l/s,R=g<=.8?"fits":g<=.95?"tight":"overflow";return{estMb:l,totalVramMb:s,pct:g,verdict:R}}const ot=Ee,se=v.forwardRef(({className:n,children:a,...s},r)=>e.jsx(Ge,{children:e.jsxs(Te,{ref:r,className:$("tllm-sheet fixed z-50 flex flex-col border-border bg-panel shadow-[var(--shadow-2)] focus:outline-none",n),...s,children:[a,e.jsx(Re,{className:"absolute right-4 top-4 rounded-sm text-muted hover:text-ink","aria-label":"Close",children:e.jsx(ne,{size:16})})]})}));se.displayName="SheetContent";function rt({className:n,...a}){return e.jsx("div",{className:$("mb-4 flex flex-col gap-1",n),...a})}const le=v.forwardRef(({className:n,...a},s)=>e.jsx(ze,{ref:s,className:$("text-[16px] font-semibold tracking-[-0.01em] text-ink",n),...a}));le.displayName="SheetTitle";const oe=v.forwardRef(({className:n,...a},s)=>e.jsx(De,{ref:s,className:$("text-[13px] text-muted",n),...a}));oe.displayName="SheetDescription";function it(n){switch(n){case"llama-server":return"llamacpp";case"mlx":return"mlx";case"vllm":return"vllm";default:return"none"}}function Ft({modelKey:n,onClose:a,onViewRepo:s}){const r=Ne(n),c=we(),i=Se(),d=Pe(),h=Fe(),[f,j]=v.useState(null),[l,g]=v.useState(null),[R,de]=v.useState(!1),[B,me]=v.useState(!0),pe=Le(),o=r.data,K=Ae().data?.engine.state;v.useEffect(()=>{o&&g(structuredClone(o.profile))},[o]),v.useEffect(()=>{if(!n)return;const t=document.documentElement,m=parseInt(ct()??"",10);if(m>0){const p=Math.min(Math.max(m,Q),ie());t.style.setProperty("--tllm-config-w",`${p}px`)}return t.classList.add("tllm-config-open"),()=>t.classList.remove("tllm-config-open")},[n]),v.useEffect(()=>{f&&(K==="stopped"||K==="error")&&(d.start.mutate({key:f,base:l??void 0}),j(null))},[f,K,d.start]);const S=c.data?.engines.find(t=>t.id===c.data?.activeEngineId),xe=S?.capabilities.kvTypes??["f16"],z=S?.capabilities.flags??[],F=t=>z.length===0||z.includes(t),J=t=>z.length===0||z.includes(`spec-type:${t}`),ue=(o?.arch??"").toLowerCase(),he=(o?.name??"").toLowerCase(),fe=/gemma4/.test(ue)||/gemma[ _-]?4/.test(he),ge=(o?.nextnLayers??0)>0,L=["off"];F("--spec-type")&&F("--mtp-head")&&fe&&L.push("mtp"),F("--spec-type")&&F("--model-draft")&&ge&&(J("nextn")||J("draft-mtp"))&&L.push("nextn"),F("--model-draft")&&L.push("draft");const D=v.useMemo(()=>!o||!l?null:lt(l,o,at(o.gpus??[],l.gpu)),[o,l]),x=(t,m)=>g(p=>p&&{...p,[t]:m}),C=(t,m)=>g(p=>p&&{...p,sampling:{...p.sampling,[t]:m}}),X=(t,m)=>g(p=>p&&{...p,gpu:{...p.gpu??ee(),[t]:m}}),M=(t,m)=>g(p=>p&&{...p,vllm:{...p.vllm??tt(),[t]:m}}),Z=i.load.error instanceof q?i.load.error.message:null,A=!!h&&h.modelKey===o?.key,ve=!!h?.running&&A,E=!!h?.done&&A&&!h.running,je=d.start.error instanceof q?d.start.error.message:null,_=it(S?.kind),P=_==="llamacpp",be=_==="mlx",ye=_==="vllm",ke=()=>{o&&(o.loaded?(j(o.key),i.eject.mutate()):d.start.mutate({key:o.key,base:l??void 0}))};v.useEffect(()=>{E&&o?.key&&pe.invalidateQueries({queryKey:["model",o.key]})},[E,o?.key]);const Ce=()=>{d.save.mutate(void 0,{onSuccess:()=>V.success("Tuned settings saved"),onError:t=>V.error(t instanceof q?t.message:"Could not save tuned settings.")}),a()},Me=()=>{d.cancel.mutate(),a()};return e.jsxs(e.Fragment,{children:[e.jsx(ot,{open:!!n,onOpenChange:t=>!t&&a(),modal:!1,children:e.jsxs(se,{className:"overflow-y-auto p-5 slim-scroll",onPointerDownOutside:t=>t.preventDefault(),onInteractOutside:t=>t.preventDefault(),children:[e.jsx(dt,{}),e.jsxs(rt,{children:[e.jsx(le,{className:"truncate",children:o?.name??"Model"}),e.jsx(oe,{children:o?`${o.arch} · ${o.quant} · ${jt(o.sizeBytes)}`:"Load settings"}),o?.sourceRepo&&s&&e.jsxs("button",{type:"button",onClick:()=>s(o.sourceRepo),className:"mt-1 inline-flex w-fit items-center gap-1 text-[12px] font-medium text-accent hover:underline",title:`View ${o.sourceRepo} on Hugging Face`,children:[e.jsx(Oe,{size:12})," Model card & quants on Hugging Face"]})]}),!o||!l?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"Loading…"}):e.jsxs("div",{className:"flex flex-col gap-4",children:[D&&e.jsx(pt,{estMb:D.estMb,totalMb:D.totalVramMb,verdict:D.verdict}),P&&o.gpu&&e.jsx(xt,{running:ve,done:E,step:A?h?.step:void 0,bestTps:A?h?.bestTps:void 0,resultError:E?h?.error:void 0,benchTps:o.benchTps,tuned:l.tunedBy==="bench",loaded:o.loaded,startError:je,pending:d.start.isPending||f!==null,onStart:ke,onCancel:()=>d.cancel.mutate()}),be&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px] text-muted",children:["MLX (Apple Silicon, mlx-lm) manages context and KV cache automatically — there are no context/GPU-layer/KV knobs to set. Only the ",e.jsx("span",{className:"text-ink",children:"sampling defaults"})," below apply at load; per-conversation overrides still work in chat."]}),ye&&e.jsxs(N,{children:[e.jsx(u,{label:"Max model length",hint:"vLLM --max-model-len. Max context tokens. 0 = derive from the model config.",children:e.jsx(k,{value:l.vllm?.maxModelLen??0,min:0,max:Math.max(0,o.nativeCtx||0),step:1024,onChange:t=>M("maxModelLen",t)})}),e.jsx(b,{label:"GPU memory utilization",hint:"vLLM --gpu-memory-utilization. Fraction of VRAM vLLM may reserve. Lower it to share the GPU.",value:Math.round((l.vllm?.gpuMemoryUtilization??.9)*100),min:10,max:100,step:5,onChange:t=>M("gpuMemoryUtilization",t/100),fmt:t=>`${t}%`}),e.jsx(u,{label:"Max concurrent sequences",hint:"vLLM --max-num-seqs. Requests served in parallel. 0 = vLLM default.",children:e.jsx(k,{value:l.vllm?.maxNumSeqs??0,min:0,max:1024,step:1,onChange:t=>M("maxNumSeqs",t)})}),e.jsx(u,{label:"Compute dtype",hint:"vLLM --dtype. 'auto' follows the model's config.",children:e.jsx(O,{value:l.vllm?.dtype??"auto",options:["auto","bfloat16","float16","float32"],onChange:t=>M("dtype",t)})}),e.jsx(u,{label:"KV cache dtype",hint:"vLLM --kv-cache-dtype. fp8 roughly halves KV-cache memory.",children:e.jsx(O,{value:l.vllm?.kvCacheDtype??"auto",options:["auto","fp8"],onChange:t=>M("kvCacheDtype",t)})}),e.jsx(w,{label:"Enforce eager",hint:"vLLM --enforce-eager. Skips CUDA graphs: less VRAM, somewhat slower.",value:l.vllm?.enforceEager??!1,onChange:t=>M("enforceEager",t)}),e.jsx(w,{label:"Trust remote code",hint:"vLLM --trust-remote-code. Needed for models that ship custom modelling code.",value:l.vllm?.trustRemoteCode??!1,onChange:t=>M("trustRemoteCode",t)})]}),P&&e.jsxs(N,{children:[e.jsx(b,{label:"Context length",hint:"Tokens of history the model can use.",value:l.ctx,min:512,max:Math.max(512,o.nativeCtx||8192),step:512,onChange:t=>x("ctx",t),fmt:t=>t.toLocaleString()}),o.gpu&&e.jsx(b,{label:"GPU layers",hint:o.blockCount>0?`${o.blockCount} total layers.`:"All layers on GPU = max performance.",value:l.ngl,min:0,max:o.blockCount>0?o.blockCount:99,step:1,onChange:t=>x("ngl",t),fmt:t=>t>=(o.blockCount>0?o.blockCount:99)?"All":String(t)}),o.moe&&o.blockCount>0&&e.jsx(b,{label:"MoE experts on CPU",hint:"Higher = less VRAM, slower. Lower = faster if it fits.",value:l.nCpuMoe,min:0,max:o.blockCount,step:1,onChange:t=>x("nCpuMoe",t)}),e.jsx(u,{label:"Context overflow",hint:"What to do when the context window fills up.",children:e.jsx(U,{value:l.contextOverflow,options:["shift","keep"],onChange:t=>x("contextOverflow",t)})}),l.contextOverflow==="keep"&&e.jsx(u,{label:"Tokens to keep",hint:"Preserve this many tokens from the start (e.g. system prompt length) when shifting.",children:e.jsx(k,{value:l.nKeep,min:0,max:l.ctx,onChange:t=>x("nKeep",t)})})]}),o.gpus&&o.gpus.length>1&&(S?.kind==="llama-server"||S?.kind==="vllm")&&e.jsxs(e.Fragment,{children:[e.jsxs(I,{children:["Multi-GPU · ",o.gpus.length," GPUs"]}),e.jsx(N,{children:S.kind==="vllm"?e.jsx(u,{label:"Tensor parallel size",hint:"Shard the model across this many GPUs.",children:e.jsx(k,{value:l.gpu?.tensorParallelSize??1,min:1,max:o.gpus.length,onChange:t=>X("tensorParallelSize",t)})}):e.jsx(ut,{gpus:o.gpus,gpu:l.gpu??ee(),setG:X})})]}),P&&e.jsxs(N,{children:[e.jsx(u,{label:"Parallel slots",children:e.jsx(k,{value:l.parallel,min:1,max:16,onChange:t=>x("parallel",t)})}),e.jsx(u,{label:"KV cache type",hint:"turbo* are TurboQuant-fork exclusive.",children:e.jsx(O,{value:l.kvTypeK,options:xe,onChange:t=>g(m=>m&&{...m,kvTypeK:t,kvTypeV:t})})}),e.jsx(u,{label:"Flash attention",children:e.jsx(U,{value:l.flashAttn,options:["auto","on","off"],onChange:t=>x("flashAttn",t)})}),e.jsx(w,{label:"Use Jinja chat template",value:l.useJinja,onChange:t=>x("useJinja",t)}),l.useJinja&&e.jsx(W,{label:"Template file path (optional)",hint:"Leave empty to use model's built-in template.",value:l.chatTemplateFile,placeholder:"Path to .jinja template file",onChange:t=>x("chatTemplateFile",t)})]}),e.jsx(I,{children:"Sampling"}),e.jsxs(N,{children:[e.jsx(b,{label:"Temperature",value:l.sampling.temp,min:0,max:2,step:.05,onChange:t=>C("temp",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Top P",value:l.sampling.topP,min:0,max:1,step:.01,onChange:t=>C("topP",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Top K",value:l.sampling.topK,min:0,max:200,step:1,onChange:t=>C("topK",t)}),e.jsx(b,{label:"Min P",value:l.sampling.minP,min:0,max:1,step:.01,onChange:t=>C("minP",t),fmt:t=>t.toFixed(2)}),P&&e.jsxs(e.Fragment,{children:[e.jsx(b,{label:"Repeat penalty",hint:"Penalise tokens that appeared earlier. 1.0 = off.",value:l.sampling.repeatPenalty,min:1,max:2,step:.05,onChange:t=>C("repeatPenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Presence penalty",hint:"Flat penalty for any token that appeared. 0 = off.",value:l.sampling.presencePenalty,min:0,max:2,step:.05,onChange:t=>C("presencePenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(b,{label:"Frequency penalty",hint:"Penalty proportional to how often a token appeared. 0 = off.",value:l.sampling.frequencyPenalty,min:0,max:2,step:.05,onChange:t=>C("frequencyPenalty",t),fmt:t=>t.toFixed(2)}),e.jsx(u,{label:"Stop strings",hint:"Halt generation when any of these sequences is produced.",children:e.jsx("div",{className:"w-full"})}),e.jsx(gt,{value:l.sampling.stop,onChange:t=>g(m=>m&&{...m,sampling:{...m.sampling,stop:t}})})]})]}),P&&L.length>1&&e.jsxs(e.Fragment,{children:[e.jsx(I,{children:"Speculative decoding"}),e.jsxs(N,{children:[e.jsx(u,{label:"Mode",hint:"Predict extra tokens per step — faster generation.",children:e.jsx(ft,{value:l.speculative,options:L,onChange:t=>x("speculative",t)})}),l.speculative==="mtp"&&e.jsx(W,{label:"MTP head GGUF",hint:"Gemma-4 assistant model file.",value:l.mtpHeadPath,placeholder:"Path to gemma-4-mtp-assistant.gguf",onChange:t=>x("mtpHeadPath",t)}),l.speculative==="nextn"&&e.jsx("p",{className:"text-[11px] text-faint",children:"Uses this model's built-in NextN head — no extra file needed."}),l.speculative==="draft"&&e.jsx(W,{label:"Draft model GGUF",hint:"A small same-family model.",value:l.draftModelPath,placeholder:"Path to small draft model",onChange:t=>x("draftModelPath",t)})]})]}),P&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",onClick:()=>de(t=>!t),className:"flex items-center gap-1 text-[13px] font-medium text-muted hover:text-ink",children:[e.jsx(qe,{size:14,className:R?"rotate-180 transition-transform":"transition-transform"}),"Advanced"]}),R&&e.jsxs(N,{children:[e.jsx(b,{label:"CPU threads",hint:l.threads===0?`Auto — half your cores (${vt(o.cores)} of ${o.cores||"?"})`:`${l.threads} of ${o.cores||"?"} cores`,value:l.threads,min:0,max:Math.max(1,o.cores||64),step:1,onChange:t=>x("threads",t),fmt:t=>t===0?"Auto":String(t)}),e.jsx(w,{label:"Reuse cached prompt",hint:"Skips re-processing the unchanged start of a prompt on repeated or continued requests — faster first token. Recommended on.",value:l.cacheReuse>0,onChange:t=>x("cacheReuse",t?256:0)}),o.vision&&e.jsx(w,{label:"Vision encoder on GPU",value:l.mmprojGpu,onChange:t=>x("mmprojGpu",t)}),l.parallel>1&&e.jsx(w,{label:"Unified KV across slots",value:l.kvUnified,onChange:t=>x("kvUnified",t)}),e.jsx(u,{label:"RoPE scaling",hint:"Extend context beyond the model's trained limit. 'none' = model native.",children:e.jsx(U,{value:l.ropeScalingType,options:["none","linear","yarn"],onChange:t=>x("ropeScalingType",t)})}),l.ropeScalingType!=="none"&&e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"RoPE freq base",hint:"Base frequency override. 0 = model native.",children:e.jsx(k,{value:l.ropeFreqBase,min:0,max:1e7,onChange:t=>x("ropeFreqBase",t)})}),e.jsx(u,{label:"RoPE freq scale",hint:"Frequency scale. 0 = model native; e.g. 0.25 for 4× context.",children:e.jsx(k,{value:l.ropeFreqScale,min:0,max:10,step:.01,onChange:t=>x("ropeFreqScale",t)})})]})]})]}),Z&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:Z}),e.jsxs("label",{className:"flex cursor-pointer items-center gap-2 pt-1 text-[13px] text-ink",children:[e.jsx("input",{type:"checkbox",checked:B,onChange:t=>me(t.target.checked),className:"h-4 w-4 accent-[var(--accent)]"}),"Remember these settings",e.jsx("span",{className:"text-[11px] text-faint",children:B?"· saved as this model's default":"· this load only"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(G,{className:"flex-1",onClick:()=>{const t=()=>i.load.mutate({key:o.key,overrides:l},{onError:m=>V.error(m instanceof q?`Could not load model: ${m.message}`:"Could not load model — check the engine logs on the Engines screen.")});B?i.save.mutate({key:o.key,profile:l},{onSuccess:t,onError:t}):t(),a()},disabled:i.load.isPending,children:[e.jsx(ae,{size:14}),o.loaded?"Reload":"Load model"]}),e.jsxs(G,{variant:"outline",onClick:()=>i.save.mutate({key:o.key,profile:l}),disabled:i.save.isPending,title:"Save without reloading",children:[e.jsx(We,{size:14}),"Save"]}),e.jsx(G,{variant:"ghost",onClick:()=>i.reset.mutate(o.key),disabled:i.reset.isPending,title:"Reset to defaults",children:e.jsx(Xe,{size:14})})]})]})]})}),e.jsx(mt,{result:E&&A?h?.result:void 0,modelName:o?.name,onSave:Ce,onCancel:Me})]})}const re="tllm-config-w",Q=360;function ie(){return Math.max(Q,Math.min(760,window.innerWidth-220))}function ct(){try{return localStorage.getItem(re)}catch{return null}}function dt(){const n=a=>{if(a.button!==0)return;a.preventDefault();const s=document.documentElement;s.classList.add("tllm-config-resizing");const r=i=>{const d=Math.min(Math.max(window.innerWidth-i.clientX,Q),ie());s.style.setProperty("--tllm-config-w",`${Math.round(d)}px`)},c=()=>{s.classList.remove("tllm-config-resizing"),window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",c);try{localStorage.setItem(re,getComputedStyle(s).getPropertyValue("--tllm-config-w").trim())}catch{}};window.addEventListener("pointermove",r),window.addEventListener("pointerup",c)};return e.jsx("div",{className:"tllm-config-resizer",onPointerDown:n,role:"separator","aria-orientation":"vertical","aria-label":"Resize panel"})}function y({label:n,value:a,tag:s}){return e.jsxs("div",{className:"flex items-center justify-between gap-3 py-[3px]",children:[e.jsx("span",{className:"text-muted",children:n}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[s&&e.jsx("span",{className:"rounded px-1 py-0.5 text-[10px] font-medium uppercase tracking-wide",style:{color:"var(--accent)",background:"color-mix(in srgb, var(--accent) 12%, transparent)"},children:s}),e.jsx("span",{className:"font-mono text-ink",children:a})]})]})}function H({title:n}){return e.jsx("div",{className:"mt-2 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wide text-faint first:mt-0 first:pt-0",children:n})}function mt({result:n,modelName:a,onSave:s,onCancel:r}){const c=n?.recommendedSampling,i=n?.sampling,d=j=>c?.[j]!=null,h=!!c&&(c.temp!=null||c.topP!=null||c.topK!=null||c.minP!=null),f=[{label:"Temperature",key:"temp"},{label:"Top-K",key:"topK"},{label:"Top-P",key:"topP"},{label:"Min-P",key:"minP"}];return e.jsx(Ue,{open:!!n,onOpenChange:j=>{j||r()},children:e.jsxs($e,{children:[e.jsxs(Be,{children:[e.jsx(Ke,{children:"Auto-tune complete"}),e.jsx(_e,{asChild:!0,children:e.jsxs("div",{className:"flex flex-col gap-2.5 text-[13px]",children:[e.jsxs("span",{className:"text-muted",children:["Fastest config found on your machine —"," ",e.jsxs("span",{className:"font-mono font-medium",style:{color:"var(--ok)"},children:[n?.tps.toFixed(1)," tok/s"]}),". Save applies this complete config to ",a??"this model",":"]}),n&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-1.5",children:[e.jsx(H,{title:"Runtime"}),e.jsx(y,{label:"GPU layers",value:n.params.ngl}),n.params.nCpuMoe>0&&e.jsx(y,{label:"MoE experts on CPU",value:n.params.nCpuMoe}),e.jsx(y,{label:"Context length",value:`${n.params.ctx.toLocaleString()} tok`}),e.jsx(y,{label:"KV cache type",value:n.params.kvTypeK}),e.jsx(y,{label:"Flash attention",value:n.params.flashAttn}),n.params.parallel>1&&e.jsx(y,{label:"Parallel slots",value:n.params.parallel}),e.jsx(H,{title:"Sampling"}),i?f.map(({label:j,key:l})=>e.jsx(y,{label:j,value:i[l]??"—",tag:d(l)?"from card":void 0},l)):e.jsx(y,{label:"Sampling",value:"model defaults"}),e.jsx(H,{title:"Measured"}),e.jsx(y,{label:"Speed",value:`${n.tps.toFixed(1)} tok/s`}),n.vramMb!=null&&e.jsx(y,{label:"VRAM used",value:`~${n.vramMb.toLocaleString()} MB`}),n.ttftMs?e.jsx(y,{label:"First token",value:`${Math.round(n.ttftMs)} ms`}):null]}),e.jsxs("span",{className:"text-faint",children:[h?e.jsxs(e.Fragment,{children:["Values tagged ",e.jsx("span",{style:{color:"var(--accent)"},children:"from card"})," were read from the model's Hugging Face page. "]}):e.jsx(e.Fragment,{children:"No sampling recommendation was found on the model's card — sampling stays at your current values. "}),"Change any of these later in Sampling."]})]})})]}),e.jsxs(Ve,{children:[e.jsx(He,{onClick:r,children:"Cancel"}),e.jsx(Ie,{onClick:s,children:"Save"})]})]})})}function pt({estMb:n,totalMb:a,verdict:s}){if(s==="cpu"||a===0)return e.jsx("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2 text-[12px] text-muted",children:"CPU-only — no GPU detected."});const r=s==="fits"?"var(--ok)":s==="tight"?"var(--warn)":"var(--err)",c=Math.min(100,Math.round(n/a*100)),i=s==="overflow"?"will spill to system RAM — expect severe slowdown":s==="tight"?"may slow under desktop load":"fits comfortably";return e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5",children:[e.jsxs("div",{className:"mb-1.5 flex items-center justify-between text-[12px]",children:[e.jsx("span",{className:"text-muted",children:"Estimated VRAM"}),e.jsxs("span",{style:{color:r},children:["~",(n/1e3).toFixed(1)," / ",(a/1e3).toFixed(1)," GB · ",i]})]}),e.jsx("div",{className:"h-2 overflow-hidden rounded-full",style:{background:"var(--border)"},children:e.jsx("div",{className:"h-full rounded-full transition-all",style:{width:`${c}%`,background:r}})})]})}function xt({running:n,done:a,step:s,bestTps:r,resultError:c,benchTps:i,tuned:d,loaded:h,startError:f,pending:j,onStart:l,onCancel:g}){return e.jsx("div",{className:"rounded-lg border border-border bg-panel p-3",children:n?e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-[13px] text-ink",children:[e.jsx(Y,{size:14,className:"animate-pulse",style:{color:"var(--accent)"}}),"Auto-tuning…"]}),e.jsxs(G,{variant:"outline",onClick:g,children:[e.jsx(ne,{size:14}),"Cancel"]})]}),e.jsx("p",{className:"font-mono text-[12px] text-muted",children:s??"Preparing…"}),r!==void 0&&e.jsxs("p",{className:"text-[12px] text-ink",children:["Best so far: ",e.jsxs("span",{className:"font-mono",style:{color:"var(--ok)"},children:[r.toFixed(1)," tok/s"]})]})]}):e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[13px] font-medium text-ink",children:[e.jsx(Y,{size:14,style:{color:"var(--accent)"}}),"Auto-tune"]}),e.jsx("p",{className:"text-[11px] text-faint",children:i!==null?`Tuned: ${i.toFixed(1)} tok/s on your machine${d?" · settings applied below":""}`:"Measures real speed on your hardware and saves the fastest settings (~3 min)."})]}),e.jsxs(G,{variant:"outline",onClick:l,disabled:j,children:[e.jsx(ae,{size:14}),h?"Stop & benchmark":"Auto-tune"]})]}),a&&r!==void 0&&!c&&e.jsxs("p",{className:"text-[12px] text-ink",children:["Done — ",e.jsxs("span",{className:"font-mono",style:{color:"var(--ok)"},children:[r.toFixed(1)," tok/s"]}),". Saved as this model's default."]}),a&&c&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--warn)"},children:c}),f&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:f})]})})}function N({children:n}){return e.jsx("div",{className:"flex flex-col gap-3 rounded-lg border border-border bg-panel p-3",children:n})}function I({children:n}){return e.jsx("div",{className:"text-[12px] font-semibold uppercase tracking-wide text-faint",children:n})}function b({label:n,hint:a,value:s,min:r,max:c,step:i,onChange:d,fmt:h}){return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-1 flex items-baseline justify-between",children:[e.jsx("span",{className:"text-[13px] text-ink",children:n}),e.jsx("span",{className:"font-mono text-[12px] text-muted",children:h?h(s):s})]}),e.jsx("input",{type:"range",min:r,max:c,step:i,value:s,onChange:f=>d(Number(f.target.value)),className:"w-full accent-[var(--accent)]"}),a&&e.jsx("p",{className:"mt-0.5 text-[11px] text-faint",children:a})]})}function u({label:n,hint:a,children:s}){return e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[13px] text-ink",children:n}),a&&e.jsx("div",{className:"text-[11px] text-faint",children:a})]}),s]})}function k({value:n,min:a,max:s,step:r=1,onChange:c}){return e.jsx("input",{type:"number",min:a,max:s,step:r,value:n,onChange:i=>c(Math.max(a,Math.min(s,Number(i.target.value)||a))),className:"w-20 rounded-md border border-border bg-bg px-2 py-1 text-right text-[13px] text-ink outline-none"})}function O({value:n,options:a,onChange:s}){return e.jsx("select",{value:n,onChange:r=>s(r.target.value),className:"rounded-md border border-border bg-bg px-2 py-1 text-[13px] text-ink outline-none",children:a.map(r=>e.jsx("option",{value:r,children:r},r))})}function U({value:n,options:a,onChange:s}){return e.jsx("div",{className:"flex overflow-hidden rounded-md border border-border",children:a.map(r=>e.jsx("button",{type:"button",onClick:()=>s(r),className:"px-2.5 py-1 text-[12px] capitalize transition-colors",style:{background:n===r?"var(--accent)":"transparent",color:n===r?"var(--on-accent)":"var(--muted)"},children:r},r))})}function ce(n,a){const s=n.vramMb?` (${Math.round(n.vramMb/1024)} GB)`:"";return`GPU ${a}${n.name?` · ${n.name}`:""}${s}`}function te({gpus:n,value:a,allowAuto:s,onChange:r}){return e.jsxs("select",{value:String(a),onChange:c=>r(Number(c.target.value)),className:"max-w-[260px] rounded-md border border-border bg-bg px-2 py-1 text-[13px] text-ink outline-none",children:[s&&e.jsx("option",{value:"-1",children:"Auto"}),n.map((c,i)=>e.jsx("option",{value:String(i),children:ce(c,i)},i))]})}function ut({gpus:n,gpu:a,setG:s}){const r=a.tensorSplit.length>0;return e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"Split mode",hint:"layer = by layers (default) · row = tensor-parallel · none = single GPU.",children:e.jsx(U,{value:a.splitMode,options:["layer","row","none"],onChange:c=>s("splitMode",c)})}),a.splitMode==="none"?e.jsx(u,{label:"GPU",hint:"Which GPU to load the model on.",children:e.jsx(te,{gpus:n,value:a.mainGpu>=0?a.mainGpu:0,allowAuto:!1,onChange:c=>s("mainGpu",c)})}):e.jsxs(e.Fragment,{children:[e.jsx(u,{label:"Main GPU",hint:"Holds the KV cache / small tensors. Auto lets the engine choose.",children:e.jsx(te,{gpus:n,value:a.mainGpu,allowAuto:!0,onChange:c=>s("mainGpu",c)})}),e.jsx(w,{label:"Custom GPU split",hint:"Off = even split across GPUs. On = set each GPU's share.",value:r,onChange:c=>s("tensorSplit",c?n.map(()=>1):[])}),r&&e.jsx("div",{className:"flex flex-col gap-2 pl-1",children:n.map((c,i)=>e.jsx(u,{label:ce(c,i),children:e.jsx(k,{value:a.tensorSplit[i]??0,min:0,max:100,onChange:d=>s("tensorSplit",n.map((h,f)=>f===i?d:a.tensorSplit[f]??0))})},i))})]})]})}const ht={off:"Off",mtp:"MTP",nextn:"NextN",draft:"Draft"};function ft({value:n,options:a,onChange:s}){return e.jsx("div",{className:"flex overflow-hidden rounded-md border border-border",children:a.map(r=>e.jsx("button",{type:"button",onClick:()=>s(r),className:"px-2.5 py-1 text-[12px] transition-colors",style:{background:n===r?"var(--accent)":"transparent",color:n===r?"var(--on-accent)":"var(--muted)"},children:ht[r]},r))})}function W({label:n,hint:a,value:s,placeholder:r,onChange:c}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"text-[12px] text-ink",children:[n,a&&e.jsx("span",{className:"ml-1 text-faint",children:a})]}),e.jsx("input",{type:"text",value:s,placeholder:r,onChange:i=>c(i.target.value),className:"w-full rounded-md border border-border bg-bg px-2 py-1 font-mono text-[12px] text-ink outline-none placeholder:text-faint"})]})}function gt({value:n,onChange:a}){const[s,r]=v.useState(""),c=i=>{const d=i.trim();d&&!n.includes(d)&&a([...n,d]),r("")};return e.jsxs("div",{className:"flex flex-col gap-1.5",children:[n.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1",children:n.map(i=>e.jsxs("span",{className:"flex items-center gap-0.5 rounded border border-border bg-panel-2 px-1.5 py-0.5 font-mono text-[11px] text-ink",children:[i,e.jsx("button",{type:"button",onClick:()=>a(n.filter(d=>d!==i)),className:"ml-0.5 text-muted hover:text-[var(--err)]",children:"×"})]},i))}),e.jsx("input",{type:"text",value:s,placeholder:n.length?"Add another…":"Type a stop string, press Enter",onChange:i=>r(i.target.value),onKeyDown:i=>{i.key==="Enter"&&(i.preventDefault(),c(s)),i.key==="Backspace"&&!s&&n.length&&a(n.slice(0,-1))},onBlur:()=>{s.trim()&&c(s)},className:"w-full rounded-md border border-border bg-bg px-2 py-1 font-mono text-[12px] text-ink outline-none placeholder:text-faint"})]})}function w({label:n,hint:a,value:s,onChange:r}){return e.jsxs("label",{className:"flex cursor-pointer items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"text-[13px] text-ink",children:n}),a&&e.jsx("p",{className:"text-[11px] text-faint",children:a})]}),e.jsx("input",{type:"checkbox",checked:s,onChange:c=>r(c.target.checked),className:"h-4 w-4 shrink-0 accent-[var(--accent)]"})]})}function vt(n){return Math.max(1,Math.floor((n||2)/2))}function jt(n){return n>=1e9?`${(n/1e9).toFixed(1)} GB`:`${Math.round(n/1e6)} MB`}export{Ft as M,St as S,ae as Z,Pt as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./radix-BFvMxQq9.js";import{r as p}from"./vendor-D_-14Whs.js";import{c as d,A as x,X as m,I as u,B as h}from"./index-
|
|
1
|
+
import{j as e}from"./radix-BFvMxQq9.js";import{r as p}from"./vendor-D_-14Whs.js";import{c as d,A as x,X as m,I as u,B as h}from"./index-DdsLEQg8.js";const f=[["path",{d:"M12 10v6",key:"1bos4e"}],["path",{d:"M9 13h6",key:"1uhe8q"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]],y=d("folder-plus",f);const v=[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]],g=d("star",v);function D({dirs:s,primaryDir:t,mut:a}){const[o,n]=p.useState(""),i=a.addDir.error instanceof x?a.addDir.error.message:null,l=()=>{const r=o.trim();r&&a.addDir.mutate(r,{onSuccess:()=>n("")})};return e.jsxs("div",{className:"mb-5 rounded-lg border border-border bg-panel-2 p-4",children:[e.jsx("div",{className:"mb-2 text-[13px] font-medium text-ink",children:"Model folders"}),s.length>0&&e.jsx("div",{className:"mb-3 flex flex-col gap-1.5",children:s.map(r=>{const c=r===t;return e.jsxs("div",{className:"group/dir flex items-center gap-2 text-[13px]",children:[e.jsx("span",{className:"flex-1 truncate font-mono text-muted",children:r}),c?e.jsx(b,{tone:"ok",children:"Primary"}):e.jsxs("button",{type:"button",onClick:()=>a.setPrimaryDir.mutate(r),disabled:a.setPrimaryDir.isPending,title:"Downloads and imports will land in this folder",className:"flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-faint opacity-0 transition-opacity hover:text-ink focus:opacity-100 group-hover/dir:opacity-100",children:[e.jsx(g,{size:12}),"Set as primary"]}),e.jsx("button",{type:"button","aria-label":`Remove ${r}`,onClick:()=>a.removeDir.mutate(r),className:"rounded p-1 text-muted transition-colors hover:text-ink",children:e.jsx(m,{size:14})})]},r)})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(u,{value:o,onChange:r=>n(r.target.value),onKeyDown:r=>r.key==="Enter"&&l(),placeholder:"Paste an absolute folder path, e.g. D:\\\\models",className:"flex-1 font-mono text-[13px]"}),e.jsxs(h,{size:"sm",onClick:l,disabled:a.addDir.isPending||!o.trim(),children:[e.jsx(y,{size:14}),"Add folder"]})]}),i&&e.jsx("p",{className:"mt-2 text-[12px]",style:{color:"var(--err)"},children:i})]})}function b({children:s,tone:t}){const a=t==="ok"?"var(--ok)":t==="warn"?"var(--warn)":t==="err"?"var(--err)":t==="spec"?"var(--accent)":"var(--muted)";return e.jsx("span",{className:"rounded px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide",style:{color:a,background:`color-mix(in srgb, ${a} 12%, transparent)`},children:s})}export{D as M};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./radix-BFvMxQq9.js";import{c as q,j as be,k as P,D as E,B as k,X,l as ve,m as Y,d as ee,u as te,A as _,t as L,I as se,n as ye,b as ne,o as we,p as ke,a as Ne,q as Me,r as Se,L as _e,s as V,v as Ce}from"./index-sjgdofsd.js";import{r as b}from"./vendor-D_-14Whs.js";import{I as K,E as ae,S as De}from"./common-DIXPIrUd.js";import{S as re,B as oe,E as Le}from"./skeleton-Dvq8tYzC.js";import{b as Be,h as le,j as ie,l as ce,m as de,n as ue,o as Fe,A as $e,p as ze,q as Qe,r as Ge,s as qe,t as Ee,u as Re,v as Ae,g as Te,D as Ie,c as Ke,d as Ue,f as W,a as Pe}from"./dialog-Dpyml8ZT.js";import{Z as xe,S as Z,M as He,a as Oe}from"./ModelDetailDialog-BOvumdHI.js";import{E as Xe,R as Ve}from"./refresh-cw-BoAcjLtt.js";import{S as We}from"./sparkles-C54kYWeQ.js";import{M as Ze}from"./ModelDirs-Bj-XrX0c.js";import{T as Je}from"./trash-2-DIMVgidH.js";import"./save-DE1APWTG.js";const Ye=[["path",{d:"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5",key:"mvr1a0"}]],et=q("heart",Ye);const tt=[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]],me=q("link-2",tt);const st=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],H=q("lock",st);const nt=[["path",{d:"M12 22V12",key:"d0xqtd"}],["path",{d:"M20.27 18.27 22 20",key:"er2am"}],["path",{d:"M21 10.498V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.729l7 4a2 2 0 0 0 2 .001l.98-.559",key:"tok1h1"}],["path",{d:"M3.29 7 12 12l8.71-5",key:"19ckod"}],["path",{d:"m7.5 4.27 8.997 5.148",key:"9yrvtv"}],["circle",{cx:"18.5",cy:"16.5",r:"2.5",key:"ke13xx"}]],at=q("package-search",nt),rt=[{repo:"unsloth/Qwen3.6-35B-A3B-GGUF",name:"Qwen3.6 35B-A3B",blurb:"Sparse MoE flagship — 35B total, 3B active. Fast for its size.",quants:{8:"IQ2_XXS",12:"IQ3_XXS",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Qwen3.6-27B-GGUF",name:"Qwen3.6 27B",blurb:"Dense 27B — strong general reasoning, broad quant range.",quants:{8:"IQ2_XS",12:"IQ3_M",16:"Q3_K_L",24:"Q5_K_M","32+":"Q6_K"}},{repo:"unsloth/Gemma-4-26B-A4B-GGUF",name:"Gemma-4 26B-A4B",blurb:"Google MoE with vision — 26B total, 4B active. Multimodal.",quants:{8:"IQ2_XXS",12:"IQ3_XXS",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Gemma-4-E4B-GGUF",name:"Gemma-4 E4B",blurb:"Compact 4B — runs anywhere, vision-capable, great laptop pick.",quants:{8:"Q4_K_M",12:"Q5_K_M",16:"Q6_K",24:"Q8_0","32+":"Q8_0"}},{repo:"unsloth/Qwen3.5-9B-GGUF",name:"Qwen3.5 9B",blurb:"Dense 9B — efficient, fits midrange GPUs at good quant.",quants:{8:"Q3_K_M",12:"Q4_K_M",16:"Q5_K_M",24:"Q6_K","32+":"Q8_0"}},{repo:"unsloth/GLM-5-Air-GGUF",name:"GLM-5 Air",blurb:"Zhipu MoE — efficient long-context generalist.",quants:{8:"IQ2_XS",12:"IQ3_M",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Llama-3.3-70B-Instruct-GGUF",name:"Llama 3.3 70B",blurb:"Meta 70B — gated; accept the license + add a token to download.",gated:!0,quants:{8:"IQ1_M",12:"IQ2_XXS",16:"IQ2_M",24:"IQ3_M","32+":"Q4_K_M"}},{repo:"unsloth/gpt-oss-20b-GGUF",name:"GPT-OSS 20B",blurb:"OpenAI open-weights 20B — strong tool-use and reasoning.",quants:{8:"IQ2_M",12:"Q3_K_M",16:"Q4_K_M",24:"Q5_K_M","32+":"Q6_K"}}];function ot(t){if(!t)return"16";const s=t/1024;return s<10?"8":s<14?"12":s<20?"16":s<28?"24":"32+"}function lt(){const t=be(),s=P(),a=t.data?.downloads??[];if(a.length===0)return null;const l=a.filter(i=>i.status==="downloading"||i.status==="queued"||i.status==="paused"),o=a.filter(i=>i.status==="error"),r=a.filter(i=>i.status==="done"||i.status==="cancelled"),d=[...l,...o,...r];return e.jsxs("div",{className:"mb-5 rounded-lg border border-border bg-panel-2 p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[13px] font-medium text-ink",children:[e.jsx(E,{size:14,className:"text-muted"}),"Downloads",l.length>0&&e.jsxs("span",{className:"text-[12px] font-normal text-muted",children:["· ",l.length," active"]})]}),e.jsx("div",{className:"flex flex-col gap-2",children:d.map(i=>e.jsx(it,{d:i,onCancel:()=>s.cancel.mutate(i.id),onRemove:()=>s.remove.mutate(i.id),cancelling:s.cancel.isPending},i.id))})]})}function it({d:t,onCancel:s,onRemove:a,cancelling:l}){const o=t.total>0?Math.min(100,Math.round(t.received/t.total*100)):0,r=t.status==="downloading"||t.status==="queued"||t.status==="paused",d=t.status==="done",i=t.status==="error",h=t.status==="cancelled",n=i?"var(--err)":d?"var(--ok)":"var(--accent)";return e.jsxs("div",{className:"rounded-md border border-border bg-panel px-3 py-2.5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[d&&e.jsx(Be,{size:13,style:{color:"var(--ok)"},className:"shrink-0"}),e.jsx("span",{className:"truncate text-[13px] font-medium text-ink",children:t.name})]}),e.jsx("div",{className:"mt-0.5 truncate text-[11px] text-muted",children:e.jsx(ct,{d:t,pct:o})})]}),r&&e.jsxs(k,{size:"sm",variant:"outline",onClick:s,disabled:l,title:"Cancel download",children:[e.jsx(X,{size:13}),"Cancel"]}),(d||i||h)&&e.jsx("button",{type:"button","aria-label":"Remove from list",onClick:a,className:"rounded p-1 text-muted transition-colors hover:text-ink",children:e.jsx(X,{size:14})})]}),(r||i)&&e.jsx("div",{className:"mt-2 h-1.5 overflow-hidden rounded-full",style:{background:"var(--border)"},children:e.jsx("div",{className:"h-full rounded-full transition-all",style:{width:`${i?100:o}%`,background:n}})})]})}function ct({d:t,pct:s}){return t.status==="done"?e.jsx("span",{style:{color:"var(--ok)"},children:"✓ added to library"}):t.status==="error"?e.jsx("span",{style:{color:"var(--err)"},children:t.error??"Download failed"}):t.status==="cancelled"?e.jsx(e.Fragment,{children:"Cancelled"}):t.status==="paused"?e.jsxs(e.Fragment,{children:["Paused · ",Q(t.received)," of ",t.total>0?Q(t.total):"?"]}):t.status==="queued"?e.jsx(e.Fragment,{children:"Queued…"}):e.jsxs(e.Fragment,{children:[s,"% · ",Q(t.received)," of ",t.total>0?Q(t.total):"?",t.bytesPerSec>0?` · ${dt(t.bytesPerSec)}`:""]})}function Q(t){return t>=1e9?`${(t/1e9).toFixed(2)} GB`:`${Math.round(t/1e6)} MB`}function dt(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB/s`:`${Math.round(t/1e3)} KB/s`}function G(t,s){if(!s)return"unknown";const o=(t/1e6*1.15+1e3)/s;return o<=.8?"fits":o<=.95?"tight":"overflow"}const pe={fits:"var(--ok)",tight:"var(--warn)",overflow:"var(--err)",cpu:"var(--muted)",unknown:"var(--faint)"},he={fits:"Fits comfortably on your GPU.",tight:"Tight fit — may slow under desktop load.",overflow:"Larger than your VRAM — will spill to system RAM.",cpu:"CPU-only — no GPU detected.",unknown:"Fit unknown — GPU VRAM not detected."};function fe({repo:t,onClose:s,onSearch:a}){const l=ve(t),o=Y(),r=P(),d=ee(),h=te().data?.engine.kind??"",n=l.data,m=o.data?.gpus?.[0]?.vramMb,f=!!n?.safetensors,[x,y]=b.useState("");b.useEffect(()=>{if(!n)return;const u=n.files.filter(w=>!w.mmproj);if(u.length===0)return;const g=u.filter(w=>G(w.sizeBytes,m)==="fits"),B=[...g.length>0?g:u].sort((w,F)=>{if(F.sizeBytes!==w.sizeBytes)return F.sizeBytes-w.sizeBytes;const T=/q\d_k/i.test(w.quant)?0:1,I=/q\d_k/i.test(F.quant)?0:1;return T-I})[0];y(B.name)},[n,m]);const N=b.useMemo(()=>n?n.files.filter(u=>!u.mmproj).sort((u,g)=>u.sizeBytes-g.sizeBytes):[],[n]),c=N.find(u=>u.name===x)??null,v=!!c?.downloaded,j=c?G(c.sizeBytes,m):"unknown",C=n?.gated??!1,$=C,D=r.enqueue.error instanceof _?r.enqueue.error.message:null,R=()=>{!n||!c||r.enqueue.mutate({repo:n.repo,rfilename:c.name,size:c.sizeBytes,sha256:c.sha256},{onSuccess:()=>{L.success(`Downloading ${c.name}`),s()}})},z=()=>{if(!n?.safetensors||!n.files.length)return;const u=n.repo.split("/").pop()??n.repo;let g=0;for(const S of n.files)r.enqueue.mutate({repo:n.repo,rfilename:S.name,size:S.sizeBytes,sha256:S.sha256,subdir:u}),g++;L.success(`Queued ${g} files for ${u}`),s()},A=()=>{const u=c?.localKey;u&&d.load.mutate({key:u},{onSuccess:()=>{L.success(`Loading ${c?.quant??"model"}`),s()},onError:g=>L.error(g instanceof _?g.message:"Could not load model.")})};return e.jsx(le,{open:!!t,onOpenChange:u=>!u&&s(),children:e.jsxs(ie,{className:"max-h-[88vh] overflow-y-auto sm:max-w-[560px]",children:[e.jsxs(ce,{children:[e.jsx(de,{className:"truncate pr-6",children:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[C&&e.jsx(H,{size:14,style:{color:"var(--warn)"}}),t]})}),e.jsx(ue,{children:n?`${n.downloads.toLocaleString()} downloads · ${n.likes.toLocaleString()} likes${n.license?` · ${n.license}`:""}`:"Loading repo…"})]}),l.isLoading?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"Loading repo…"}):l.isError?e.jsx(xt,{error:l.error,onRetry:()=>l.refetch(),onSearch:a?()=>a(mt(t)):void 0}):f?e.jsx(ut,{detail:n,vramMb:m,engineKind:h,onDownload:z,isPending:r.enqueue.isPending}):!n||N.length===0?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"No GGUF files found in this repo."}):e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsxs("label",{className:"flex items-center gap-1.5 text-[12px] font-medium text-ink",children:["Quant",n.verifying&&e.jsx("span",{className:"text-[11px] font-normal text-faint",children:"· checking your library…"})]}),e.jsx("select",{value:x,onChange:u=>y(u.target.value),className:"w-full rounded-md border border-border bg-bg px-2 py-2 text-[13px] text-ink outline-none",children:N.map(u=>{const g=G(u.sizeBytes,m),S=!!u.downloaded,B=g==="fits"?"●":g==="tight"?"◐":g==="overflow"?"○":"·";return e.jsxs("option",{value:u.name,children:[u.quant," · ",pt(u.sizeBytes),u.parts>1?` · ${u.parts} parts`:""," · ",B,S?" · Downloaded":""]},u.name)})})]}),c&&e.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px]",children:[e.jsx("span",{className:"h-2.5 w-2.5 shrink-0 rounded-full",style:{background:pe[j]}}),e.jsxs("span",{className:"text-muted",children:[he[j],m?` (${(c.sizeBytes/1e9).toFixed(1)} GB file · ${(m/1024).toFixed(0)} GB VRAM)`:""]})]}),$&&e.jsxs("div",{className:"rounded-md border px-3 py-2.5 text-[12px]",style:{borderColor:"var(--warn)",background:"color-mix(in srgb, var(--warn) 10%, transparent)"},children:[e.jsx("p",{className:"text-ink",children:"This is a gated model."}),e.jsxs("p",{className:"mt-1 text-muted",children:["Accept the license on"," ",e.jsxs("a",{href:`https://huggingface.co/${n.repo}`,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-0.5 underline",style:{color:"var(--accent)"},children:["huggingface.co ",e.jsx(Xe,{size:11})]}),", then add a Hugging Face token in Settings → Models."]})]}),D&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:D}),e.jsx("div",{className:"flex items-center gap-2",children:v&&c?.localKey?e.jsxs(k,{className:"flex-1",onClick:A,disabled:d.load.isPending,children:[e.jsx(xe,{size:14}),"Load"]}):e.jsxs(k,{className:"flex-1",onClick:R,disabled:$||r.enqueue.isPending||!c,children:[e.jsx(E,{size:14}),r.enqueue.isPending?"Adding…":v?"Re-download":"Download"]})}),n.card&&e.jsxs("details",{className:"rounded-md border border-border bg-panel-2 px-3 py-2",children:[e.jsx("summary",{className:"cursor-pointer text-[12px] font-medium text-muted",children:"Model card"}),e.jsx("p",{className:"mt-2 whitespace-pre-wrap text-[12px] leading-relaxed text-muted",children:n.card})]})]})]})})}function ut({detail:t,vramMb:s,engineKind:a,onDownload:l,isPending:o}){const r=t.files.reduce((n,m)=>n+m.sizeBytes,0),d=G(r,s),i=a==="mlx"?"MLX model — runs on Apple Silicon via mlx-lm. Downloads as a directory of safetensors weights.":a==="vllm"?"HuggingFace model — runs via vLLM. Downloads as a directory of safetensors weights.":"Safetensors model — downloads as a directory of weight files.",h=a==="mlx"?"Download MLX model":"Download model";return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px] text-muted",children:i}),e.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px]",children:[e.jsx("span",{className:"h-2.5 w-2.5 shrink-0 rounded-full",style:{background:pe[d]}}),e.jsxs("span",{className:"text-muted",children:[he[d],s?` (${(r/1e9).toFixed(1)} GB total · ${(s/1024).toFixed(0)} GB VRAM)`:`${(r/1e9).toFixed(1)} GB total`]})]}),e.jsxs(k,{className:"w-full",onClick:l,disabled:t.gated||o,children:[e.jsx(E,{size:14}),o?"Queuing…":h]})]})}function xt({error:t,onRetry:s,onSearch:a}){const l=t instanceof _?t.code:"",o=l==="hf_not_found",r=l==="hf_unreachable";return e.jsxs("div",{className:"flex flex-col items-center gap-3 py-10 text-center",children:[e.jsx("p",{className:"max-w-sm text-[13px] text-muted",children:o?"We couldn't find this exact model on Hugging Face — the local folder name may not match its repo. Try searching for it instead.":r?"Hugging Face is unreachable — check your connection.":t instanceof _?t.message:"Could not load this repo."}),e.jsxs("div",{className:"flex items-center gap-2",children:[o&&a&&e.jsx(k,{size:"sm",onClick:a,children:"Search Hugging Face"}),e.jsx(k,{size:"sm",variant:"outline",onClick:s,children:"Retry"})]})]})}function mt(t){return t?(t.split("/").pop()??t).replace(/[-_]?gguf$/i,"").replace(/[-_]+/g," ").trim():""}function pt(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:`${Math.round(t/1e6)} MB`}function ht(t){let s;try{s=new URL(t)}catch{return!1}return s.protocol!=="http:"&&s.protocol!=="https:"?!1:s.pathname.toLowerCase().endsWith(".gguf")?!0:/huggingface\.co\/.*\/resolve\/.*\.gguf$/i.test(`${s.host}${s.pathname}`)}function ft(t){try{const a=new URL(t).pathname.split("/").filter(Boolean).pop()??"";return decodeURIComponent(a)}catch{return""}}function gt({open:t,onClose:s}){const a=P(),[l,o]=b.useState(""),r=l.trim(),d=b.useMemo(()=>ft(r),[r]),i=r.length>0&&ht(r),h=r.length>0&&!i,n=a.enqueue.error instanceof _?a.enqueue.error.message:null,m=()=>{o(""),a.enqueue.reset(),s()},f=()=>{i&&a.enqueue.mutate({url:r},{onSuccess:()=>m()})};return e.jsx(le,{open:t,onOpenChange:x=>!x&&m(),children:e.jsxs(ie,{className:"sm:max-w-[480px]",children:[e.jsxs(ce,{children:[e.jsx(de,{children:"Import from URL"}),e.jsxs(ue,{children:["Paste a direct link to a ",e.jsx("span",{className:"font-mono",children:".gguf"})," file — any HTTPS host, not just Hugging Face."]})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(se,{autoFocus:!0,value:l,onChange:x=>o(x.target.value),onKeyDown:x=>x.key==="Enter"&&f(),placeholder:"https://huggingface.co/owner/repo/resolve/main/model.Q4_K_M.gguf",className:"font-mono text-[12px]"}),d&&i&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2 text-[12px]",children:[e.jsx("span",{className:"text-muted",children:"Will save as "}),e.jsx("span",{className:"font-mono text-ink",children:d})]}),h&&e.jsxs("p",{className:"text-[12px]",style:{color:"var(--err)"},children:["Enter a valid http(s) link ending in ",e.jsx("span",{className:"font-mono",children:".gguf"})," (or an HF resolve URL)."]}),n&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:n})]}),e.jsxs(Fe,{children:[e.jsx(k,{variant:"outline",onClick:m,children:"Cancel"}),e.jsxs(k,{onClick:f,disabled:!i||a.enqueue.isPending,children:[e.jsx(me,{size:14}),a.enqueue.isPending?"Adding…":"Import"]})]})]})})}function jt(t,s){const l=(t.split("/").pop()??t).toLowerCase().replace(/-gguf$/,"");return s.some(o=>`${o.name} ${o.path}`.toLowerCase().includes(l))}function bt({presetQuery:t=""}){const[s,a]=b.useState(""),[l,o]=b.useState(""),[r,d]=b.useState(null),[i,h]=b.useState(!1);b.useEffect(()=>{t&&a(t)},[t]),b.useEffect(()=>{const j=setTimeout(()=>o(s.trim()),400);return()=>clearTimeout(j)},[s]);const n=ye(l),m=ne(),f=Y(),x=m.data?.models??[],y=ot(f.data?.gpus?.[0]?.vramMb),N=l.length>0,c=n.error instanceof _&&n.error.code==="hf_unreachable",v=n.data?.results??[];return e.jsxs("div",{children:[e.jsx(lt,{}),e.jsxs("div",{className:"mb-5 flex items-center gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(Z,{size:15,className:"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-faint"}),e.jsx(se,{value:s,onChange:j=>a(j.target.value),placeholder:"Search Hugging Face for GGUF models, e.g. qwen3.6 gguf",className:"pl-9"})]}),e.jsxs("button",{type:"button",onClick:()=>h(!0),className:"inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border bg-transparent px-3 py-2 text-[13px] font-medium text-ink transition-colors hover:bg-panel-2",children:[e.jsx(me,{size:14}),"Import from URL"]})]}),!N&&e.jsx(vt,{repos:rt,tier:y,models:x,onOpen:j=>d(j)}),N&&e.jsx("div",{className:"flex flex-col gap-2",children:n.isLoading?[0,1,2,3].map(j=>e.jsx(re,{className:"h-[58px] w-full rounded-lg"},j)):c?e.jsx(K,{message:"Hugging Face is unreachable — check your connection.",onRetry:()=>n.refetch()}):n.isError?e.jsx(K,{message:n.error instanceof _?n.error.message:"Search failed.",onRetry:()=>n.refetch()}):v.length===0?e.jsx(ae,{icon:e.jsx(Z,{size:24}),message:`No GGUF repos found for “${l}”.`}):v.map(j=>e.jsx(yt,{item:j,onOpen:()=>d(j.repo)},j.repo))}),e.jsx(fe,{repo:r,onClose:()=>d(null),onSearch:j=>{d(null),a(j)}}),e.jsx(gt,{open:i,onClose:()=>h(!1)})]})}function vt({repos:t,tier:s,models:a,onOpen:l}){return e.jsxs("div",{className:"mb-2",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-1.5 text-[12px] font-semibold uppercase tracking-wide text-faint",children:[e.jsx(We,{size:13}),"Featured"]}),e.jsx("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:t.map(o=>{const r=jt(o.repo,a);return e.jsxs("button",{type:"button",onClick:()=>l(o.repo),className:"flex flex-col gap-1.5 rounded-lg border border-border bg-panel px-4 py-3 text-left transition-colors hover:border-border-strong hover:bg-panel-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[o.gated&&e.jsx(H,{size:13,style:{color:"var(--warn)"},className:"shrink-0"}),e.jsx("span",{className:"truncate font-medium text-ink",children:o.name}),r&&e.jsx(ge,{})]}),e.jsx("p",{className:"line-clamp-2 text-[12px] text-muted",children:o.blurb}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-1.5 text-[11px] text-faint",children:[e.jsx("span",{children:"Suggested for your GPU:"}),e.jsx("span",{className:"rounded px-1.5 py-0.5 font-mono",style:{color:"var(--accent)",background:"color-mix(in srgb, var(--accent) 12%, transparent)"},children:o.quants[s]})]})]},o.repo)})})]})}function yt({item:t,onOpen:s}){return e.jsx("button",{type:"button",onClick:s,className:"group flex items-center gap-3 rounded-lg border border-border bg-panel px-4 py-3 text-left transition-colors hover:border-border-strong hover:bg-panel-2",children:e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[t.gated&&e.jsx(H,{size:13,style:{color:"var(--warn)"},className:"shrink-0"}),e.jsx("span",{className:"truncate font-medium text-ink",children:t.repo}),t.localCount>0&&e.jsx(ge,{count:t.localCount})]}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-3 text-[12px] text-muted",children:[e.jsxs("span",{children:[J(t.downloads)," downloads"]}),e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(et,{size:11})," ",J(t.likes)]}),t.updatedAt&&e.jsxs("span",{children:["updated ",wt(t.updatedAt)]})]})]})})}function ge({count:t}){return e.jsx("span",{className:"inline-flex shrink-0 items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium",style:{color:"var(--ok)",background:"color-mix(in srgb, var(--ok) 14%, transparent)"},children:t!=null?`↓ ${t} in library`:"✓ in library"})}function J(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:String(t)}function wt(t){const s=new Date(t);return Number.isNaN(s.getTime())?"":s.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function kt(t){const s=new Map;for(const o of t){const r=o.name.toLowerCase();(s.get(r)??s.set(r,[]).get(r)).push(o)}const a=[],l=new Set;for(const o of t){const r=o.name.toLowerCase();l.has(r)||(l.add(r),a.push(r))}return a.map(o=>({name:s.get(o)[0].name,variants:s.get(o)}))}function Pt(){const t=ne(),s=we(),a=ke(),l=ee(),o=Mt(),{data:r}=te(),d=r?.engine.state,i=l.load.isPending||d==="starting"||d==="stopping",h=l.load.isPending?l.load.variables?.key:d==="starting"?r?.model?.key:void 0,[n,m]=b.useState("library"),[f,x]=b.useState("all"),[y,N]=b.useState(!1),[c,v]=b.useState(null),[j,C]=b.useState(null),[$,D]=b.useState(null),[R,z]=b.useState(""),A=p=>{p.sourceRepo?D(p.sourceRepo):(z(p.name),m("discover"))},u=t.data?.scanning??!1,g=t.data?.models??[],S=s.data?.dirs??[],B=s.data?.primaryDir??"",w=g.filter(p=>!p.compatibleWithActiveEngine).length,F=g.filter(p=>!y&&!p.compatibleWithActiveEngine?!1:f==="all"?!0:f==="vision"?p.vision:f==="moe"?p.moe:f==="nextn"?(p.nextnLayers??0)>0:f==="embedding"?p.embedding:!0),T=kt(F),I=()=>{const p=j;p&&o.mutate(p.key,{onSuccess:()=>{L.success(`Deleted ${p.name}`),C(null)},onError:O=>{L.error(O instanceof _?O.message:"Could not delete model files."),C(null)}})};return e.jsxs("div",{className:"slim-scroll h-full w-full overflow-y-auto px-6 py-6",children:[e.jsx(De,{title:"Models",description:n==="library"?"GGUF models discovered in your folders — reuse what you already have, no re-downloading.":"Find and download GGUF models from Hugging Face, or import any direct .gguf URL.",actions:n==="library"?e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>a.rescan.mutate(),disabled:u,children:[e.jsx(Ve,{size:14,className:u?"tllm-pulse":""}),u?"Scanning…":"Rescan"]}):void 0}),e.jsx("div",{className:"mb-5 flex items-center gap-1 border-b border-border",children:["library","discover"].map(p=>e.jsx("button",{type:"button",onClick:()=>m(p),className:"-mb-px border-b-2 px-3 py-2 text-[13px] font-medium capitalize transition-colors",style:{borderColor:n===p?"var(--accent)":"transparent",color:n===p?"var(--ink)":"var(--muted)"},children:p==="library"?`Library${g.length?` (${g.length})`:""}`:"Discover"},p))}),n==="library"&&w>0&&e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-3 rounded-[var(--radius)] border border-border bg-panel px-4 py-2.5 text-[12px]",children:[e.jsx("span",{className:"text-muted",children:y?`Showing all models. ${w} can't load on the active engine.`:`${w} ${w===1?"model is":"models are"} hidden — the active engine can't load ${w===1?"it":"them"}.`}),e.jsx("button",{type:"button",onClick:()=>N(p=>!p),className:"shrink-0 font-medium text-accent hover:underline",children:y?"Show compatible only":"Show all"})]}),n==="discover"?e.jsx(bt,{presetQuery:R}):e.jsx(Nt,{modelsQ:t,mut:a,actions:l,loadBusy:i,loadingKey:h,dirs:S,primaryDir:B,scanning:u,models:g,filter:f,setFilter:x,groups:T,setOpenKey:v,setConfirmDelete:C,onDiscover:A}),e.jsx(He,{modelKey:c,onClose:()=>v(null),onViewRepo:p=>{v(null),D(p)}}),e.jsx(fe,{repo:$,onClose:()=>D(null),onSearch:p=>{D(null),z(p),m("discover")}}),e.jsx(_t,{model:j,onCancel:()=>C(null),onConfirm:I,deleting:o.isPending})]})}function Nt({modelsQ:t,mut:s,actions:a,loadBusy:l,loadingKey:o,dirs:r,primaryDir:d,scanning:i,models:h,filter:n,setFilter:m,groups:f,setOpenKey:x,setConfirmDelete:y,onDiscover:N}){return e.jsxs(e.Fragment,{children:[e.jsx(Ze,{dirs:r,primaryDir:d,mut:s}),h.length>0&&e.jsx("div",{className:"mb-4 flex items-center gap-2",children:["all","vision","moe","nextn","embedding"].map(c=>e.jsx(Dt,{active:n===c,onClick:()=>m(c),children:c==="all"?`All ${h.length}`:c==="vision"?"Vision":c==="moe"?"MoE":c==="nextn"?"NextN":"Embed"},c))}),t.isLoading?e.jsx("div",{className:"flex flex-col gap-2",children:[0,1,2].map(c=>e.jsx(re,{className:"h-[58px] w-full rounded-lg"},c))}):t.isError?e.jsx(K,{message:"Could not load models.",onRetry:()=>t.refetch()}):h.length===0?e.jsx(ae,{icon:e.jsx(Se,{size:24}),message:r.length===0?"No model folders yet. Add a folder above to discover the GGUF models you already have.":i?"Scanning your folders…":"No GGUF models found in your folders."}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map(c=>c.variants.length===1?e.jsx(je,{m:c.variants[0],onLoad:()=>a.load.mutate({key:c.variants[0].key}),onEject:()=>a.eject.mutate(),onTune:()=>x(c.variants[0].key),onDelete:()=>y(c.variants[0]),onDiscover:()=>N(c.variants[0]),busy:l,loadingThis:o===c.variants[0].key,ejecting:a.eject.isPending},c.variants[0].key):e.jsx(St,{group:c,onLoad:v=>a.load.mutate({key:v}),onEject:()=>a.eject.mutate(),onTune:v=>x(v),onDelete:v=>y(v),onDiscover:N,busy:l,loadingKey:o,ejecting:a.eject.isPending},c.name.toLowerCase()))})]})}function Mt(){const t=Ne();return Me({mutationFn:s=>Ce(s),onSuccess:()=>{t.invalidateQueries({queryKey:V.models}),t.invalidateQueries({queryKey:V.status})}})}function St({group:t,onLoad:s,onEject:a,onTune:l,onDelete:o,onDiscover:r,busy:d,loadingKey:i,ejecting:h}){const[n,m]=b.useState(!1),f=t.variants.some(x=>x.loaded);return e.jsxs("div",{className:"rounded-lg border border-border bg-panel",children:[e.jsxs("button",{type:"button",onClick:()=>m(x=>!x),className:"flex w-full items-center gap-3 px-4 py-3 text-left",children:[e.jsx(Pe,{size:16,className:`shrink-0 text-muted transition-transform ${n?"rotate-90":""}`}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"truncate font-medium text-ink",children:t.name}),f&&e.jsx(M,{tone:"ok",children:"loaded"})]}),e.jsxs("div",{className:"mt-0.5 truncate text-[12px] text-muted",children:[t.variants.length," variants",t.variants[0].arch?` · ${t.variants[0].arch}`:""]})]}),e.jsxs(oe,{variant:"mono",children:[t.variants.length," quants"]})]}),n&&e.jsx("div",{className:"flex flex-col gap-2 border-t border-border px-3 pb-3 pt-2",children:t.variants.map(x=>e.jsx(je,{m:x,child:!0,onLoad:()=>s(x.key),onEject:a,onTune:()=>l(x.key),onDelete:()=>o(x),onDiscover:()=>r(x),busy:d,loadingThis:i===x.key,ejecting:h},x.key))})]})}function je({m:t,child:s,onLoad:a,onEject:l,onTune:o,onDelete:r,onDiscover:d,busy:i,loadingThis:h,ejecting:n}){const m=!t.incomplete&&!t.parseError,f=t.compatibleWithActiveEngine!==!1,x=t.format==="gguf"?"llama.cpp":"MLX or vLLM",y=(t.nextnLayers??0)>0;return e.jsxs("div",{className:s?"group flex flex-col gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 sm:flex-row sm:items-center sm:gap-3":"group flex flex-col gap-2 rounded-lg border border-border bg-panel px-4 py-3 sm:flex-row sm:items-center sm:gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"min-w-0 break-words font-medium text-ink sm:truncate",children:s?t.quant:t.name}),t.loaded&&e.jsx(M,{tone:"ok",children:"loaded"}),t.vision&&e.jsx(M,{children:"vision"}),t.embedding&&e.jsx(M,{children:"embed"}),t.moe&&e.jsx(M,{children:"MoE"}),y&&e.jsx(M,{tone:"spec",children:"NextN"}),t.hasProfile&&e.jsx(M,{children:"tuned"}),t.incomplete&&e.jsx(M,{tone:"warn",children:"missing parts"}),t.parseError&&e.jsx(M,{tone:"err",children:"unreadable"}),!f&&e.jsxs(M,{tone:"warn",children:["needs ",x]})]}),e.jsxs("div",{className:"mt-0.5 truncate text-[12px] text-muted",children:[t.arch,t.dir?` · ${t.dir}`:""]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2 sm:flex-nowrap sm:gap-3",children:[!s&&e.jsx(oe,{variant:"mono",children:t.quant}),e.jsx(U,{children:Bt(t.sizeBytes)}),e.jsx(U,{children:t.nativeCtx?`${Ft(t.nativeCtx)} ctx`:"—"}),e.jsx(Lt,{m:t}),e.jsxs("div",{className:"ml-auto flex items-center gap-1 sm:ml-0",children:[e.jsxs(k,{size:"sm",onClick:a,disabled:!m||!f||i,title:m?f?"":`The active engine can't load this model — switch to ${x}`:"Model is incomplete or unreadable",children:[h?e.jsx(_e,{size:14,className:"animate-spin"}):e.jsx(xe,{size:14}),h?"Loading…":t.loaded?"Reload":"Load"]}),t.incomplete&&e.jsxs(k,{size:"sm",variant:"outline",onClick:d,title:"Download the missing shard files",children:[e.jsx(E,{size:14}),"Re-download"]}),t.loaded&&e.jsxs(k,{size:"sm",variant:"outline",onClick:l,disabled:n,title:"Eject model (stop the engine)",children:[e.jsx(Te,{size:14}),"Eject"]}),e.jsx(k,{size:"sm",variant:"ghost",onClick:o,disabled:!m,title:"Load settings",children:e.jsx(Oe,{size:14})}),e.jsxs(Ie,{children:[e.jsx(Ke,{"aria-label":"Model actions",className:"grid h-8 w-8 place-items-center rounded-md text-muted opacity-100 transition-opacity hover:bg-panel-2 hover:text-ink focus:opacity-100 data-[state=open]:opacity-100 sm:opacity-0 sm:group-hover:opacity-100",children:e.jsx(Le,{size:16})}),e.jsxs(Ue,{align:"end",children:[e.jsxs(W,{onSelect:d,children:[e.jsx(at,{size:14})," Find other quants…"]}),e.jsxs(W,{destructive:!0,disabled:t.loaded,onSelect:r,title:t.loaded?"Eject the model before deleting":void 0,children:[e.jsx(Je,{size:14})," Delete file…"]})]})]})]})]})]})}function _t({model:t,onCancel:s,onConfirm:a,deleting:l}){const o=t!==null,r=t?Ct(t):[],d=!!t?.loaded;return e.jsx($e,{open:o,onOpenChange:i=>!i&&s(),children:e.jsxs(ze,{children:[e.jsxs(Qe,{children:[e.jsx(Ge,{children:d?"Model is loaded":"Delete model files?"}),e.jsx(qe,{children:d?"This model is currently loaded in the running engine. Eject it first, then delete.":r.length>1?`This is a split model — all ${r.length} part files will be permanently deleted from disk. This cannot be undone.`:"This file will be permanently deleted from disk. This cannot be undone."})]}),!d&&r.length>0&&e.jsx("div",{className:"max-h-40 overflow-auto rounded-md border border-border bg-panel-2 p-2",children:r.map(i=>e.jsx("div",{className:"truncate font-mono text-[12px] text-muted",children:i},i))}),e.jsxs(Ee,{children:[e.jsx(Re,{children:"Cancel"}),!d&&e.jsx(Ae,{onClick:a,disabled:l,children:l?"Deleting…":"Delete"})]})]})})}function Ct(t){const s=t.path.includes("\\")?"\\":"/",l=t.path.slice(t.path.lastIndexOf(s)+1).match(/^(.*)-(\d{5})-of-(\d{5})\.gguf$/i);if(!l)return[t.path];const o=t.path.slice(0,t.path.lastIndexOf(s)),r=l[1],d=Number(l[3]),i=[];for(let h=1;h<=d;h++){const n=String(h).padStart(5,"0"),m=String(d).padStart(5,"0");i.push(`${o}${s}${r}-${n}-of-${m}.gguf`)}return i}function Dt({active:t,onClick:s,children:a}){return e.jsx("button",{type:"button",onClick:s,className:"rounded-full border px-3 py-1 text-[12px] font-medium transition-colors",style:{borderColor:t?"var(--accent)":"var(--border)",background:t?"color-mix(in srgb, var(--accent) 12%, transparent)":"transparent",color:t?"var(--accent)":"var(--muted)"},children:a})}function M({children:t,tone:s}){const a=s==="ok"?"var(--ok)":s==="warn"?"var(--warn)":s==="err"?"var(--err)":s==="spec"?"var(--accent)":"var(--muted)";return e.jsx("span",{className:"rounded px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide",style:{color:a,background:`color-mix(in srgb, ${a} 12%, transparent)`},children:t})}function U({children:t}){return e.jsx("div",{className:"w-[72px] text-right text-[13px] text-muted",children:t})}function Lt({m:t}){return t.liveTps!=null?e.jsx("div",{className:"w-[72px] text-right text-[13px]",title:"Live tokens/sec (loaded now)",children:e.jsxs("span",{className:"tllm-pulse inline-flex items-center gap-1 font-medium",style:{color:"var(--ok)"},children:[e.jsx("span",{className:"h-1.5 w-1.5 rounded-full",style:{background:"var(--ok)"}}),Math.round(t.liveTps)," t/s"]})}):t.lastTps!=null?e.jsxs("div",{className:"w-[72px] text-right text-[13px] text-ink",title:"Last-session tokens/sec",children:[Math.round(t.lastTps)," t/s"]}):t.benchTps!=null?e.jsxs("div",{className:"w-[72px] text-right text-[13px] text-muted",title:"Benchmark tokens/sec",children:[Math.round(t.benchTps)," t/s"]}):e.jsx(U,{children:"—"})}function Bt(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:`${Math.round(t/1e6)} MB`}function Ft(t){return t>=1024?`${Math.round(t/1024)}K`:String(t)}export{Pt as ModelsScreen};
|
|
1
|
+
import{j as e}from"./radix-BFvMxQq9.js";import{c as q,j as be,k as P,D as E,B as k,X,l as ve,m as Y,d as ee,u as te,A as _,t as L,I as se,n as ye,b as ne,o as we,p as ke,a as Ne,q as Me,r as Se,L as _e,s as V,v as Ce}from"./index-DdsLEQg8.js";import{r as b}from"./vendor-D_-14Whs.js";import{I as K,E as ae,S as De}from"./common-CsaPxOo6.js";import{S as re,B as oe,E as Le}from"./skeleton-BqBFt4sB.js";import{b as Be,h as le,j as ie,l as ce,m as de,n as ue,o as Fe,A as $e,p as ze,q as Qe,r as Ge,s as qe,t as Ee,u as Re,v as Ae,g as Te,D as Ie,c as Ke,d as Ue,f as W,a as Pe}from"./dialog-oym6ZR4Z.js";import{Z as xe,S as Z,M as He,a as Oe}from"./ModelDetailDialog-DOWC_r7x.js";import{E as Xe,R as Ve}from"./refresh-cw-35eljdhP.js";import{S as We}from"./sparkles-C1EIsU4T.js";import{M as Ze}from"./ModelDirs-BnEgYeD7.js";import{T as Je}from"./trash-2-BOZ6n1d2.js";import"./save-AXon2pXP.js";const Ye=[["path",{d:"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5",key:"mvr1a0"}]],et=q("heart",Ye);const tt=[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]],me=q("link-2",tt);const st=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],H=q("lock",st);const nt=[["path",{d:"M12 22V12",key:"d0xqtd"}],["path",{d:"M20.27 18.27 22 20",key:"er2am"}],["path",{d:"M21 10.498V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.729l7 4a2 2 0 0 0 2 .001l.98-.559",key:"tok1h1"}],["path",{d:"M3.29 7 12 12l8.71-5",key:"19ckod"}],["path",{d:"m7.5 4.27 8.997 5.148",key:"9yrvtv"}],["circle",{cx:"18.5",cy:"16.5",r:"2.5",key:"ke13xx"}]],at=q("package-search",nt),rt=[{repo:"unsloth/Qwen3.6-35B-A3B-GGUF",name:"Qwen3.6 35B-A3B",blurb:"Sparse MoE flagship — 35B total, 3B active. Fast for its size.",quants:{8:"IQ2_XXS",12:"IQ3_XXS",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Qwen3.6-27B-GGUF",name:"Qwen3.6 27B",blurb:"Dense 27B — strong general reasoning, broad quant range.",quants:{8:"IQ2_XS",12:"IQ3_M",16:"Q3_K_L",24:"Q5_K_M","32+":"Q6_K"}},{repo:"unsloth/Gemma-4-26B-A4B-GGUF",name:"Gemma-4 26B-A4B",blurb:"Google MoE with vision — 26B total, 4B active. Multimodal.",quants:{8:"IQ2_XXS",12:"IQ3_XXS",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Gemma-4-E4B-GGUF",name:"Gemma-4 E4B",blurb:"Compact 4B — runs anywhere, vision-capable, great laptop pick.",quants:{8:"Q4_K_M",12:"Q5_K_M",16:"Q6_K",24:"Q8_0","32+":"Q8_0"}},{repo:"unsloth/Qwen3.5-9B-GGUF",name:"Qwen3.5 9B",blurb:"Dense 9B — efficient, fits midrange GPUs at good quant.",quants:{8:"Q3_K_M",12:"Q4_K_M",16:"Q5_K_M",24:"Q6_K","32+":"Q8_0"}},{repo:"unsloth/GLM-5-Air-GGUF",name:"GLM-5 Air",blurb:"Zhipu MoE — efficient long-context generalist.",quants:{8:"IQ2_XS",12:"IQ3_M",16:"Q3_K_M",24:"Q4_K_M","32+":"Q5_K_M"}},{repo:"unsloth/Llama-3.3-70B-Instruct-GGUF",name:"Llama 3.3 70B",blurb:"Meta 70B — gated; accept the license + add a token to download.",gated:!0,quants:{8:"IQ1_M",12:"IQ2_XXS",16:"IQ2_M",24:"IQ3_M","32+":"Q4_K_M"}},{repo:"unsloth/gpt-oss-20b-GGUF",name:"GPT-OSS 20B",blurb:"OpenAI open-weights 20B — strong tool-use and reasoning.",quants:{8:"IQ2_M",12:"Q3_K_M",16:"Q4_K_M",24:"Q5_K_M","32+":"Q6_K"}}];function ot(t){if(!t)return"16";const s=t/1024;return s<10?"8":s<14?"12":s<20?"16":s<28?"24":"32+"}function lt(){const t=be(),s=P(),a=t.data?.downloads??[];if(a.length===0)return null;const l=a.filter(i=>i.status==="downloading"||i.status==="queued"||i.status==="paused"),o=a.filter(i=>i.status==="error"),r=a.filter(i=>i.status==="done"||i.status==="cancelled"),d=[...l,...o,...r];return e.jsxs("div",{className:"mb-5 rounded-lg border border-border bg-panel-2 p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2 text-[13px] font-medium text-ink",children:[e.jsx(E,{size:14,className:"text-muted"}),"Downloads",l.length>0&&e.jsxs("span",{className:"text-[12px] font-normal text-muted",children:["· ",l.length," active"]})]}),e.jsx("div",{className:"flex flex-col gap-2",children:d.map(i=>e.jsx(it,{d:i,onCancel:()=>s.cancel.mutate(i.id),onRemove:()=>s.remove.mutate(i.id),cancelling:s.cancel.isPending},i.id))})]})}function it({d:t,onCancel:s,onRemove:a,cancelling:l}){const o=t.total>0?Math.min(100,Math.round(t.received/t.total*100)):0,r=t.status==="downloading"||t.status==="queued"||t.status==="paused",d=t.status==="done",i=t.status==="error",h=t.status==="cancelled",n=i?"var(--err)":d?"var(--ok)":"var(--accent)";return e.jsxs("div",{className:"rounded-md border border-border bg-panel px-3 py-2.5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[d&&e.jsx(Be,{size:13,style:{color:"var(--ok)"},className:"shrink-0"}),e.jsx("span",{className:"truncate text-[13px] font-medium text-ink",children:t.name})]}),e.jsx("div",{className:"mt-0.5 truncate text-[11px] text-muted",children:e.jsx(ct,{d:t,pct:o})})]}),r&&e.jsxs(k,{size:"sm",variant:"outline",onClick:s,disabled:l,title:"Cancel download",children:[e.jsx(X,{size:13}),"Cancel"]}),(d||i||h)&&e.jsx("button",{type:"button","aria-label":"Remove from list",onClick:a,className:"rounded p-1 text-muted transition-colors hover:text-ink",children:e.jsx(X,{size:14})})]}),(r||i)&&e.jsx("div",{className:"mt-2 h-1.5 overflow-hidden rounded-full",style:{background:"var(--border)"},children:e.jsx("div",{className:"h-full rounded-full transition-all",style:{width:`${i?100:o}%`,background:n}})})]})}function ct({d:t,pct:s}){return t.status==="done"?e.jsx("span",{style:{color:"var(--ok)"},children:"✓ added to library"}):t.status==="error"?e.jsx("span",{style:{color:"var(--err)"},children:t.error??"Download failed"}):t.status==="cancelled"?e.jsx(e.Fragment,{children:"Cancelled"}):t.status==="paused"?e.jsxs(e.Fragment,{children:["Paused · ",Q(t.received)," of ",t.total>0?Q(t.total):"?"]}):t.status==="queued"?e.jsx(e.Fragment,{children:"Queued…"}):e.jsxs(e.Fragment,{children:[s,"% · ",Q(t.received)," of ",t.total>0?Q(t.total):"?",t.bytesPerSec>0?` · ${dt(t.bytesPerSec)}`:""]})}function Q(t){return t>=1e9?`${(t/1e9).toFixed(2)} GB`:`${Math.round(t/1e6)} MB`}function dt(t){return t>=1e6?`${(t/1e6).toFixed(1)} MB/s`:`${Math.round(t/1e3)} KB/s`}function G(t,s){if(!s)return"unknown";const o=(t/1e6*1.15+1e3)/s;return o<=.8?"fits":o<=.95?"tight":"overflow"}const pe={fits:"var(--ok)",tight:"var(--warn)",overflow:"var(--err)",cpu:"var(--muted)",unknown:"var(--faint)"},he={fits:"Fits comfortably on your GPU.",tight:"Tight fit — may slow under desktop load.",overflow:"Larger than your VRAM — will spill to system RAM.",cpu:"CPU-only — no GPU detected.",unknown:"Fit unknown — GPU VRAM not detected."};function fe({repo:t,onClose:s,onSearch:a}){const l=ve(t),o=Y(),r=P(),d=ee(),h=te().data?.engine.kind??"",n=l.data,m=o.data?.gpus?.[0]?.vramMb,f=!!n?.safetensors,[x,y]=b.useState("");b.useEffect(()=>{if(!n)return;const u=n.files.filter(w=>!w.mmproj);if(u.length===0)return;const g=u.filter(w=>G(w.sizeBytes,m)==="fits"),B=[...g.length>0?g:u].sort((w,F)=>{if(F.sizeBytes!==w.sizeBytes)return F.sizeBytes-w.sizeBytes;const T=/q\d_k/i.test(w.quant)?0:1,I=/q\d_k/i.test(F.quant)?0:1;return T-I})[0];y(B.name)},[n,m]);const N=b.useMemo(()=>n?n.files.filter(u=>!u.mmproj).sort((u,g)=>u.sizeBytes-g.sizeBytes):[],[n]),c=N.find(u=>u.name===x)??null,v=!!c?.downloaded,j=c?G(c.sizeBytes,m):"unknown",C=n?.gated??!1,$=C,D=r.enqueue.error instanceof _?r.enqueue.error.message:null,R=()=>{!n||!c||r.enqueue.mutate({repo:n.repo,rfilename:c.name,size:c.sizeBytes,sha256:c.sha256},{onSuccess:()=>{L.success(`Downloading ${c.name}`),s()}})},z=()=>{if(!n?.safetensors||!n.files.length)return;const u=n.repo.split("/").pop()??n.repo;let g=0;for(const S of n.files)r.enqueue.mutate({repo:n.repo,rfilename:S.name,size:S.sizeBytes,sha256:S.sha256,subdir:u}),g++;L.success(`Queued ${g} files for ${u}`),s()},A=()=>{const u=c?.localKey;u&&d.load.mutate({key:u},{onSuccess:()=>{L.success(`Loading ${c?.quant??"model"}`),s()},onError:g=>L.error(g instanceof _?g.message:"Could not load model.")})};return e.jsx(le,{open:!!t,onOpenChange:u=>!u&&s(),children:e.jsxs(ie,{className:"max-h-[88vh] overflow-y-auto sm:max-w-[560px]",children:[e.jsxs(ce,{children:[e.jsx(de,{className:"truncate pr-6",children:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[C&&e.jsx(H,{size:14,style:{color:"var(--warn)"}}),t]})}),e.jsx(ue,{children:n?`${n.downloads.toLocaleString()} downloads · ${n.likes.toLocaleString()} likes${n.license?` · ${n.license}`:""}`:"Loading repo…"})]}),l.isLoading?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"Loading repo…"}):l.isError?e.jsx(xt,{error:l.error,onRetry:()=>l.refetch(),onSearch:a?()=>a(mt(t)):void 0}):f?e.jsx(ut,{detail:n,vramMb:m,engineKind:h,onDownload:z,isPending:r.enqueue.isPending}):!n||N.length===0?e.jsx("div",{className:"py-10 text-center text-[13px] text-muted",children:"No GGUF files found in this repo."}):e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsxs("label",{className:"flex items-center gap-1.5 text-[12px] font-medium text-ink",children:["Quant",n.verifying&&e.jsx("span",{className:"text-[11px] font-normal text-faint",children:"· checking your library…"})]}),e.jsx("select",{value:x,onChange:u=>y(u.target.value),className:"w-full rounded-md border border-border bg-bg px-2 py-2 text-[13px] text-ink outline-none",children:N.map(u=>{const g=G(u.sizeBytes,m),S=!!u.downloaded,B=g==="fits"?"●":g==="tight"?"◐":g==="overflow"?"○":"·";return e.jsxs("option",{value:u.name,children:[u.quant," · ",pt(u.sizeBytes),u.parts>1?` · ${u.parts} parts`:""," · ",B,S?" · Downloaded":""]},u.name)})})]}),c&&e.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px]",children:[e.jsx("span",{className:"h-2.5 w-2.5 shrink-0 rounded-full",style:{background:pe[j]}}),e.jsxs("span",{className:"text-muted",children:[he[j],m?` (${(c.sizeBytes/1e9).toFixed(1)} GB file · ${(m/1024).toFixed(0)} GB VRAM)`:""]})]}),$&&e.jsxs("div",{className:"rounded-md border px-3 py-2.5 text-[12px]",style:{borderColor:"var(--warn)",background:"color-mix(in srgb, var(--warn) 10%, transparent)"},children:[e.jsx("p",{className:"text-ink",children:"This is a gated model."}),e.jsxs("p",{className:"mt-1 text-muted",children:["Accept the license on"," ",e.jsxs("a",{href:`https://huggingface.co/${n.repo}`,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-0.5 underline",style:{color:"var(--accent)"},children:["huggingface.co ",e.jsx(Xe,{size:11})]}),", then add a Hugging Face token in Settings → Models."]})]}),D&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:D}),e.jsx("div",{className:"flex items-center gap-2",children:v&&c?.localKey?e.jsxs(k,{className:"flex-1",onClick:A,disabled:d.load.isPending,children:[e.jsx(xe,{size:14}),"Load"]}):e.jsxs(k,{className:"flex-1",onClick:R,disabled:$||r.enqueue.isPending||!c,children:[e.jsx(E,{size:14}),r.enqueue.isPending?"Adding…":v?"Re-download":"Download"]})}),n.card&&e.jsxs("details",{className:"rounded-md border border-border bg-panel-2 px-3 py-2",children:[e.jsx("summary",{className:"cursor-pointer text-[12px] font-medium text-muted",children:"Model card"}),e.jsx("p",{className:"mt-2 whitespace-pre-wrap text-[12px] leading-relaxed text-muted",children:n.card})]})]})]})})}function ut({detail:t,vramMb:s,engineKind:a,onDownload:l,isPending:o}){const r=t.files.reduce((n,m)=>n+m.sizeBytes,0),d=G(r,s),i=a==="mlx"?"MLX model — runs on Apple Silicon via mlx-lm. Downloads as a directory of safetensors weights.":a==="vllm"?"HuggingFace model — runs via vLLM. Downloads as a directory of safetensors weights.":"Safetensors model — downloads as a directory of weight files.",h=a==="mlx"?"Download MLX model":"Download model";return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px] text-muted",children:i}),e.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 text-[12px]",children:[e.jsx("span",{className:"h-2.5 w-2.5 shrink-0 rounded-full",style:{background:pe[d]}}),e.jsxs("span",{className:"text-muted",children:[he[d],s?` (${(r/1e9).toFixed(1)} GB total · ${(s/1024).toFixed(0)} GB VRAM)`:`${(r/1e9).toFixed(1)} GB total`]})]}),e.jsxs(k,{className:"w-full",onClick:l,disabled:t.gated||o,children:[e.jsx(E,{size:14}),o?"Queuing…":h]})]})}function xt({error:t,onRetry:s,onSearch:a}){const l=t instanceof _?t.code:"",o=l==="hf_not_found",r=l==="hf_unreachable";return e.jsxs("div",{className:"flex flex-col items-center gap-3 py-10 text-center",children:[e.jsx("p",{className:"max-w-sm text-[13px] text-muted",children:o?"We couldn't find this exact model on Hugging Face — the local folder name may not match its repo. Try searching for it instead.":r?"Hugging Face is unreachable — check your connection.":t instanceof _?t.message:"Could not load this repo."}),e.jsxs("div",{className:"flex items-center gap-2",children:[o&&a&&e.jsx(k,{size:"sm",onClick:a,children:"Search Hugging Face"}),e.jsx(k,{size:"sm",variant:"outline",onClick:s,children:"Retry"})]})]})}function mt(t){return t?(t.split("/").pop()??t).replace(/[-_]?gguf$/i,"").replace(/[-_]+/g," ").trim():""}function pt(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:`${Math.round(t/1e6)} MB`}function ht(t){let s;try{s=new URL(t)}catch{return!1}return s.protocol!=="http:"&&s.protocol!=="https:"?!1:s.pathname.toLowerCase().endsWith(".gguf")?!0:/huggingface\.co\/.*\/resolve\/.*\.gguf$/i.test(`${s.host}${s.pathname}`)}function ft(t){try{const a=new URL(t).pathname.split("/").filter(Boolean).pop()??"";return decodeURIComponent(a)}catch{return""}}function gt({open:t,onClose:s}){const a=P(),[l,o]=b.useState(""),r=l.trim(),d=b.useMemo(()=>ft(r),[r]),i=r.length>0&&ht(r),h=r.length>0&&!i,n=a.enqueue.error instanceof _?a.enqueue.error.message:null,m=()=>{o(""),a.enqueue.reset(),s()},f=()=>{i&&a.enqueue.mutate({url:r},{onSuccess:()=>m()})};return e.jsx(le,{open:t,onOpenChange:x=>!x&&m(),children:e.jsxs(ie,{className:"sm:max-w-[480px]",children:[e.jsxs(ce,{children:[e.jsx(de,{children:"Import from URL"}),e.jsxs(ue,{children:["Paste a direct link to a ",e.jsx("span",{className:"font-mono",children:".gguf"})," file — any HTTPS host, not just Hugging Face."]})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(se,{autoFocus:!0,value:l,onChange:x=>o(x.target.value),onKeyDown:x=>x.key==="Enter"&&f(),placeholder:"https://huggingface.co/owner/repo/resolve/main/model.Q4_K_M.gguf",className:"font-mono text-[12px]"}),d&&i&&e.jsxs("div",{className:"rounded-md border border-border bg-panel-2 px-3 py-2 text-[12px]",children:[e.jsx("span",{className:"text-muted",children:"Will save as "}),e.jsx("span",{className:"font-mono text-ink",children:d})]}),h&&e.jsxs("p",{className:"text-[12px]",style:{color:"var(--err)"},children:["Enter a valid http(s) link ending in ",e.jsx("span",{className:"font-mono",children:".gguf"})," (or an HF resolve URL)."]}),n&&e.jsx("p",{className:"text-[12px]",style:{color:"var(--err)"},children:n})]}),e.jsxs(Fe,{children:[e.jsx(k,{variant:"outline",onClick:m,children:"Cancel"}),e.jsxs(k,{onClick:f,disabled:!i||a.enqueue.isPending,children:[e.jsx(me,{size:14}),a.enqueue.isPending?"Adding…":"Import"]})]})]})})}function jt(t,s){const l=(t.split("/").pop()??t).toLowerCase().replace(/-gguf$/,"");return s.some(o=>`${o.name} ${o.path}`.toLowerCase().includes(l))}function bt({presetQuery:t=""}){const[s,a]=b.useState(""),[l,o]=b.useState(""),[r,d]=b.useState(null),[i,h]=b.useState(!1);b.useEffect(()=>{t&&a(t)},[t]),b.useEffect(()=>{const j=setTimeout(()=>o(s.trim()),400);return()=>clearTimeout(j)},[s]);const n=ye(l),m=ne(),f=Y(),x=m.data?.models??[],y=ot(f.data?.gpus?.[0]?.vramMb),N=l.length>0,c=n.error instanceof _&&n.error.code==="hf_unreachable",v=n.data?.results??[];return e.jsxs("div",{children:[e.jsx(lt,{}),e.jsxs("div",{className:"mb-5 flex items-center gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(Z,{size:15,className:"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-faint"}),e.jsx(se,{value:s,onChange:j=>a(j.target.value),placeholder:"Search Hugging Face for GGUF models, e.g. qwen3.6 gguf",className:"pl-9"})]}),e.jsxs("button",{type:"button",onClick:()=>h(!0),className:"inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border bg-transparent px-3 py-2 text-[13px] font-medium text-ink transition-colors hover:bg-panel-2",children:[e.jsx(me,{size:14}),"Import from URL"]})]}),!N&&e.jsx(vt,{repos:rt,tier:y,models:x,onOpen:j=>d(j)}),N&&e.jsx("div",{className:"flex flex-col gap-2",children:n.isLoading?[0,1,2,3].map(j=>e.jsx(re,{className:"h-[58px] w-full rounded-lg"},j)):c?e.jsx(K,{message:"Hugging Face is unreachable — check your connection.",onRetry:()=>n.refetch()}):n.isError?e.jsx(K,{message:n.error instanceof _?n.error.message:"Search failed.",onRetry:()=>n.refetch()}):v.length===0?e.jsx(ae,{icon:e.jsx(Z,{size:24}),message:`No GGUF repos found for “${l}”.`}):v.map(j=>e.jsx(yt,{item:j,onOpen:()=>d(j.repo)},j.repo))}),e.jsx(fe,{repo:r,onClose:()=>d(null),onSearch:j=>{d(null),a(j)}}),e.jsx(gt,{open:i,onClose:()=>h(!1)})]})}function vt({repos:t,tier:s,models:a,onOpen:l}){return e.jsxs("div",{className:"mb-2",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-1.5 text-[12px] font-semibold uppercase tracking-wide text-faint",children:[e.jsx(We,{size:13}),"Featured"]}),e.jsx("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:t.map(o=>{const r=jt(o.repo,a);return e.jsxs("button",{type:"button",onClick:()=>l(o.repo),className:"flex flex-col gap-1.5 rounded-lg border border-border bg-panel px-4 py-3 text-left transition-colors hover:border-border-strong hover:bg-panel-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[o.gated&&e.jsx(H,{size:13,style:{color:"var(--warn)"},className:"shrink-0"}),e.jsx("span",{className:"truncate font-medium text-ink",children:o.name}),r&&e.jsx(ge,{})]}),e.jsx("p",{className:"line-clamp-2 text-[12px] text-muted",children:o.blurb}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-1.5 text-[11px] text-faint",children:[e.jsx("span",{children:"Suggested for your GPU:"}),e.jsx("span",{className:"rounded px-1.5 py-0.5 font-mono",style:{color:"var(--accent)",background:"color-mix(in srgb, var(--accent) 12%, transparent)"},children:o.quants[s]})]})]},o.repo)})})]})}function yt({item:t,onOpen:s}){return e.jsx("button",{type:"button",onClick:s,className:"group flex items-center gap-3 rounded-lg border border-border bg-panel px-4 py-3 text-left transition-colors hover:border-border-strong hover:bg-panel-2",children:e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[t.gated&&e.jsx(H,{size:13,style:{color:"var(--warn)"},className:"shrink-0"}),e.jsx("span",{className:"truncate font-medium text-ink",children:t.repo}),t.localCount>0&&e.jsx(ge,{count:t.localCount})]}),e.jsxs("div",{className:"mt-0.5 flex items-center gap-3 text-[12px] text-muted",children:[e.jsxs("span",{children:[J(t.downloads)," downloads"]}),e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(et,{size:11})," ",J(t.likes)]}),t.updatedAt&&e.jsxs("span",{children:["updated ",wt(t.updatedAt)]})]})]})})}function ge({count:t}){return e.jsx("span",{className:"inline-flex shrink-0 items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium",style:{color:"var(--ok)",background:"color-mix(in srgb, var(--ok) 14%, transparent)"},children:t!=null?`↓ ${t} in library`:"✓ in library"})}function J(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:String(t)}function wt(t){const s=new Date(t);return Number.isNaN(s.getTime())?"":s.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function kt(t){const s=new Map;for(const o of t){const r=o.name.toLowerCase();(s.get(r)??s.set(r,[]).get(r)).push(o)}const a=[],l=new Set;for(const o of t){const r=o.name.toLowerCase();l.has(r)||(l.add(r),a.push(r))}return a.map(o=>({name:s.get(o)[0].name,variants:s.get(o)}))}function Pt(){const t=ne(),s=we(),a=ke(),l=ee(),o=Mt(),{data:r}=te(),d=r?.engine.state,i=l.load.isPending||d==="starting"||d==="stopping",h=l.load.isPending?l.load.variables?.key:d==="starting"?r?.model?.key:void 0,[n,m]=b.useState("library"),[f,x]=b.useState("all"),[y,N]=b.useState(!1),[c,v]=b.useState(null),[j,C]=b.useState(null),[$,D]=b.useState(null),[R,z]=b.useState(""),A=p=>{p.sourceRepo?D(p.sourceRepo):(z(p.name),m("discover"))},u=t.data?.scanning??!1,g=t.data?.models??[],S=s.data?.dirs??[],B=s.data?.primaryDir??"",w=g.filter(p=>!p.compatibleWithActiveEngine).length,F=g.filter(p=>!y&&!p.compatibleWithActiveEngine?!1:f==="all"?!0:f==="vision"?p.vision:f==="moe"?p.moe:f==="nextn"?(p.nextnLayers??0)>0:f==="embedding"?p.embedding:!0),T=kt(F),I=()=>{const p=j;p&&o.mutate(p.key,{onSuccess:()=>{L.success(`Deleted ${p.name}`),C(null)},onError:O=>{L.error(O instanceof _?O.message:"Could not delete model files."),C(null)}})};return e.jsxs("div",{className:"slim-scroll h-full w-full overflow-y-auto px-6 py-6",children:[e.jsx(De,{title:"Models",description:n==="library"?"GGUF models discovered in your folders — reuse what you already have, no re-downloading.":"Find and download GGUF models from Hugging Face, or import any direct .gguf URL.",actions:n==="library"?e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>a.rescan.mutate(),disabled:u,children:[e.jsx(Ve,{size:14,className:u?"tllm-pulse":""}),u?"Scanning…":"Rescan"]}):void 0}),e.jsx("div",{className:"mb-5 flex items-center gap-1 border-b border-border",children:["library","discover"].map(p=>e.jsx("button",{type:"button",onClick:()=>m(p),className:"-mb-px border-b-2 px-3 py-2 text-[13px] font-medium capitalize transition-colors",style:{borderColor:n===p?"var(--accent)":"transparent",color:n===p?"var(--ink)":"var(--muted)"},children:p==="library"?`Library${g.length?` (${g.length})`:""}`:"Discover"},p))}),n==="library"&&w>0&&e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-3 rounded-[var(--radius)] border border-border bg-panel px-4 py-2.5 text-[12px]",children:[e.jsx("span",{className:"text-muted",children:y?`Showing all models. ${w} can't load on the active engine.`:`${w} ${w===1?"model is":"models are"} hidden — the active engine can't load ${w===1?"it":"them"}.`}),e.jsx("button",{type:"button",onClick:()=>N(p=>!p),className:"shrink-0 font-medium text-accent hover:underline",children:y?"Show compatible only":"Show all"})]}),n==="discover"?e.jsx(bt,{presetQuery:R}):e.jsx(Nt,{modelsQ:t,mut:a,actions:l,loadBusy:i,loadingKey:h,dirs:S,primaryDir:B,scanning:u,models:g,filter:f,setFilter:x,groups:T,setOpenKey:v,setConfirmDelete:C,onDiscover:A}),e.jsx(He,{modelKey:c,onClose:()=>v(null),onViewRepo:p=>{v(null),D(p)}}),e.jsx(fe,{repo:$,onClose:()=>D(null),onSearch:p=>{D(null),z(p),m("discover")}}),e.jsx(_t,{model:j,onCancel:()=>C(null),onConfirm:I,deleting:o.isPending})]})}function Nt({modelsQ:t,mut:s,actions:a,loadBusy:l,loadingKey:o,dirs:r,primaryDir:d,scanning:i,models:h,filter:n,setFilter:m,groups:f,setOpenKey:x,setConfirmDelete:y,onDiscover:N}){return e.jsxs(e.Fragment,{children:[e.jsx(Ze,{dirs:r,primaryDir:d,mut:s}),h.length>0&&e.jsx("div",{className:"mb-4 flex items-center gap-2",children:["all","vision","moe","nextn","embedding"].map(c=>e.jsx(Dt,{active:n===c,onClick:()=>m(c),children:c==="all"?`All ${h.length}`:c==="vision"?"Vision":c==="moe"?"MoE":c==="nextn"?"NextN":"Embed"},c))}),t.isLoading?e.jsx("div",{className:"flex flex-col gap-2",children:[0,1,2].map(c=>e.jsx(re,{className:"h-[58px] w-full rounded-lg"},c))}):t.isError?e.jsx(K,{message:"Could not load models.",onRetry:()=>t.refetch()}):h.length===0?e.jsx(ae,{icon:e.jsx(Se,{size:24}),message:r.length===0?"No model folders yet. Add a folder above to discover the GGUF models you already have.":i?"Scanning your folders…":"No GGUF models found in your folders."}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map(c=>c.variants.length===1?e.jsx(je,{m:c.variants[0],onLoad:()=>a.load.mutate({key:c.variants[0].key}),onEject:()=>a.eject.mutate(),onTune:()=>x(c.variants[0].key),onDelete:()=>y(c.variants[0]),onDiscover:()=>N(c.variants[0]),busy:l,loadingThis:o===c.variants[0].key,ejecting:a.eject.isPending},c.variants[0].key):e.jsx(St,{group:c,onLoad:v=>a.load.mutate({key:v}),onEject:()=>a.eject.mutate(),onTune:v=>x(v),onDelete:v=>y(v),onDiscover:N,busy:l,loadingKey:o,ejecting:a.eject.isPending},c.name.toLowerCase()))})]})}function Mt(){const t=Ne();return Me({mutationFn:s=>Ce(s),onSuccess:()=>{t.invalidateQueries({queryKey:V.models}),t.invalidateQueries({queryKey:V.status})}})}function St({group:t,onLoad:s,onEject:a,onTune:l,onDelete:o,onDiscover:r,busy:d,loadingKey:i,ejecting:h}){const[n,m]=b.useState(!1),f=t.variants.some(x=>x.loaded);return e.jsxs("div",{className:"rounded-lg border border-border bg-panel",children:[e.jsxs("button",{type:"button",onClick:()=>m(x=>!x),className:"flex w-full items-center gap-3 px-4 py-3 text-left",children:[e.jsx(Pe,{size:16,className:`shrink-0 text-muted transition-transform ${n?"rotate-90":""}`}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"truncate font-medium text-ink",children:t.name}),f&&e.jsx(M,{tone:"ok",children:"loaded"})]}),e.jsxs("div",{className:"mt-0.5 truncate text-[12px] text-muted",children:[t.variants.length," variants",t.variants[0].arch?` · ${t.variants[0].arch}`:""]})]}),e.jsxs(oe,{variant:"mono",children:[t.variants.length," quants"]})]}),n&&e.jsx("div",{className:"flex flex-col gap-2 border-t border-border px-3 pb-3 pt-2",children:t.variants.map(x=>e.jsx(je,{m:x,child:!0,onLoad:()=>s(x.key),onEject:a,onTune:()=>l(x.key),onDelete:()=>o(x),onDiscover:()=>r(x),busy:d,loadingThis:i===x.key,ejecting:h},x.key))})]})}function je({m:t,child:s,onLoad:a,onEject:l,onTune:o,onDelete:r,onDiscover:d,busy:i,loadingThis:h,ejecting:n}){const m=!t.incomplete&&!t.parseError,f=t.compatibleWithActiveEngine!==!1,x=t.format==="gguf"?"llama.cpp":"MLX or vLLM",y=(t.nextnLayers??0)>0;return e.jsxs("div",{className:s?"group flex flex-col gap-2 rounded-md border border-border bg-panel-2 px-3 py-2.5 sm:flex-row sm:items-center sm:gap-3":"group flex flex-col gap-2 rounded-lg border border-border bg-panel px-4 py-3 sm:flex-row sm:items-center sm:gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"min-w-0 break-words font-medium text-ink sm:truncate",children:s?t.quant:t.name}),t.loaded&&e.jsx(M,{tone:"ok",children:"loaded"}),t.vision&&e.jsx(M,{children:"vision"}),t.embedding&&e.jsx(M,{children:"embed"}),t.moe&&e.jsx(M,{children:"MoE"}),y&&e.jsx(M,{tone:"spec",children:"NextN"}),t.hasProfile&&e.jsx(M,{children:"tuned"}),t.incomplete&&e.jsx(M,{tone:"warn",children:"missing parts"}),t.parseError&&e.jsx(M,{tone:"err",children:"unreadable"}),!f&&e.jsxs(M,{tone:"warn",children:["needs ",x]})]}),e.jsxs("div",{className:"mt-0.5 truncate text-[12px] text-muted",children:[t.arch,t.dir?` · ${t.dir}`:""]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2 sm:flex-nowrap sm:gap-3",children:[!s&&e.jsx(oe,{variant:"mono",children:t.quant}),e.jsx(U,{children:Bt(t.sizeBytes)}),e.jsx(U,{children:t.nativeCtx?`${Ft(t.nativeCtx)} ctx`:"—"}),e.jsx(Lt,{m:t}),e.jsxs("div",{className:"ml-auto flex items-center gap-1 sm:ml-0",children:[e.jsxs(k,{size:"sm",onClick:a,disabled:!m||!f||i,title:m?f?"":`The active engine can't load this model — switch to ${x}`:"Model is incomplete or unreadable",children:[h?e.jsx(_e,{size:14,className:"animate-spin"}):e.jsx(xe,{size:14}),h?"Loading…":t.loaded?"Reload":"Load"]}),t.incomplete&&e.jsxs(k,{size:"sm",variant:"outline",onClick:d,title:"Download the missing shard files",children:[e.jsx(E,{size:14}),"Re-download"]}),t.loaded&&e.jsxs(k,{size:"sm",variant:"outline",onClick:l,disabled:n,title:"Eject model (stop the engine)",children:[e.jsx(Te,{size:14}),"Eject"]}),e.jsx(k,{size:"sm",variant:"ghost",onClick:o,disabled:!m,title:"Load settings",children:e.jsx(Oe,{size:14})}),e.jsxs(Ie,{children:[e.jsx(Ke,{"aria-label":"Model actions",className:"grid h-8 w-8 place-items-center rounded-md text-muted opacity-100 transition-opacity hover:bg-panel-2 hover:text-ink focus:opacity-100 data-[state=open]:opacity-100 sm:opacity-0 sm:group-hover:opacity-100",children:e.jsx(Le,{size:16})}),e.jsxs(Ue,{align:"end",children:[e.jsxs(W,{onSelect:d,children:[e.jsx(at,{size:14})," Find other quants…"]}),e.jsxs(W,{destructive:!0,disabled:t.loaded,onSelect:r,title:t.loaded?"Eject the model before deleting":void 0,children:[e.jsx(Je,{size:14})," Delete file…"]})]})]})]})]})]})}function _t({model:t,onCancel:s,onConfirm:a,deleting:l}){const o=t!==null,r=t?Ct(t):[],d=!!t?.loaded;return e.jsx($e,{open:o,onOpenChange:i=>!i&&s(),children:e.jsxs(ze,{children:[e.jsxs(Qe,{children:[e.jsx(Ge,{children:d?"Model is loaded":"Delete model files?"}),e.jsx(qe,{children:d?"This model is currently loaded in the running engine. Eject it first, then delete.":r.length>1?`This is a split model — all ${r.length} part files will be permanently deleted from disk. This cannot be undone.`:"This file will be permanently deleted from disk. This cannot be undone."})]}),!d&&r.length>0&&e.jsx("div",{className:"max-h-40 overflow-auto rounded-md border border-border bg-panel-2 p-2",children:r.map(i=>e.jsx("div",{className:"truncate font-mono text-[12px] text-muted",children:i},i))}),e.jsxs(Ee,{children:[e.jsx(Re,{children:"Cancel"}),!d&&e.jsx(Ae,{onClick:a,disabled:l,children:l?"Deleting…":"Delete"})]})]})})}function Ct(t){const s=t.path.includes("\\")?"\\":"/",l=t.path.slice(t.path.lastIndexOf(s)+1).match(/^(.*)-(\d{5})-of-(\d{5})\.gguf$/i);if(!l)return[t.path];const o=t.path.slice(0,t.path.lastIndexOf(s)),r=l[1],d=Number(l[3]),i=[];for(let h=1;h<=d;h++){const n=String(h).padStart(5,"0"),m=String(d).padStart(5,"0");i.push(`${o}${s}${r}-${n}-of-${m}.gguf`)}return i}function Dt({active:t,onClick:s,children:a}){return e.jsx("button",{type:"button",onClick:s,className:"rounded-full border px-3 py-1 text-[12px] font-medium transition-colors",style:{borderColor:t?"var(--accent)":"var(--border)",background:t?"color-mix(in srgb, var(--accent) 12%, transparent)":"transparent",color:t?"var(--accent)":"var(--muted)"},children:a})}function M({children:t,tone:s}){const a=s==="ok"?"var(--ok)":s==="warn"?"var(--warn)":s==="err"?"var(--err)":s==="spec"?"var(--accent)":"var(--muted)";return e.jsx("span",{className:"rounded px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide",style:{color:a,background:`color-mix(in srgb, ${a} 12%, transparent)`},children:t})}function U({children:t}){return e.jsx("div",{className:"w-[72px] text-right text-[13px] text-muted",children:t})}function Lt({m:t}){return t.liveTps!=null?e.jsx("div",{className:"w-[72px] text-right text-[13px]",title:"Live tokens/sec (loaded now)",children:e.jsxs("span",{className:"tllm-pulse inline-flex items-center gap-1 font-medium",style:{color:"var(--ok)"},children:[e.jsx("span",{className:"h-1.5 w-1.5 rounded-full",style:{background:"var(--ok)"}}),Math.round(t.liveTps)," t/s"]})}):t.lastTps!=null?e.jsxs("div",{className:"w-[72px] text-right text-[13px] text-ink",title:"Last-session tokens/sec",children:[Math.round(t.lastTps)," t/s"]}):t.benchTps!=null?e.jsxs("div",{className:"w-[72px] text-right text-[13px] text-muted",title:"Benchmark tokens/sec",children:[Math.round(t.benchTps)," t/s"]}):e.jsx(U,{children:"—"})}function Bt(t){return t>=1e9?`${(t/1e9).toFixed(1)} GB`:`${Math.round(t/1e6)} MB`}function Ft(t){return t>=1024?`${Math.round(t/1024)}K`:String(t)}export{Pt as ModelsScreen};
|