@shawnstack/quickforge 1.6.9 → 1.6.10

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.
@@ -1,5 +1,5 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{B as t,C as n,D as r,Rt as i,Vt as a,a as o,g as s,st as c,x as l,y as u}from"./icons-C7j5jdKo.js";import{n as d}from"./react-vendor-VqdnQHHS.js";import{V as f,b as p,ct as m,lt as h,pt as g,st as _}from"./index-_ut7awrd.js";var v=e(a(),1),y=d();function b(e){return e===`connected`?`bg-emerald-500/12 text-emerald-700 dark:text-emerald-300`:e===`error`?`bg-destructive/12 text-destructive`:e===`disabled`?`bg-muted text-muted-foreground`:`bg-amber-500/12 text-amber-700 dark:text-amber-300`}var x=12;function S({server:e,toggling:n,reconnecting:i,onToggle:a,onEdit:s,onDelete:c,onReconnect:l}){let d=e.tools?.slice(0,x)??[],f=e.toolCount??e.tools?.length??0,p=Math.max(0,f-d.length),_=e.enabled&&e.status!==`connected`;return(0,y.jsxs)(`div`,{className:`rounded-lg border border-border p-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,y.jsxs)(`div`,{className:`min-w-0`,children:[(0,y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,y.jsx)(`div`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.name}),(0,y.jsx)(`span`,{className:h(`rounded-full px-2 py-0.5 text-[11px]`,b(e.status)),children:e.status||`unknown`}),(0,y.jsx)(`span`,{className:`text-[11px] text-muted-foreground/60`,children:g(`mcpToolsCount`,{count:f})})]}),(0,y.jsx)(`div`,{className:`mt-1 truncate text-xs text-muted-foreground/65`,children:e.transport===`stdio`?`${e.command} ${(e.args||[]).join(` `)}`:e.url}),e.error?(0,y.jsx)(`div`,{className:`mt-1 text-xs text-destructive`,children:e.error}):null]}),(0,y.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1`,children:[(0,y.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":e.enabled,disabled:n,className:h(`relative h-6 w-11 rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-60`,e.enabled?`bg-emerald-500`:`bg-muted-foreground/30`),onClick:()=>a(e),title:e.enabled?g(`pauseTask`):g(`enable`),children:(0,y.jsx)(`span`,{className:h(`absolute left-0.5 top-0.5 size-5 rounded-full bg-white shadow transition-transform`,e.enabled?`translate-x-5`:`translate-x-0`)})}),_?(0,y.jsx)(m,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>l(e.name),disabled:i,"aria-label":g(`mcpReconnectServer`),title:g(`mcpReconnectServer`),children:i?(0,y.jsx)(t,{className:`size-4 animate-spin`}):(0,y.jsx)(u,{className:`size-4`})}):null,(0,y.jsx)(m,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>s(e),"aria-label":g(`editTask`),title:g(`editTask`),children:(0,y.jsx)(r,{className:`size-4`})}),(0,y.jsx)(m,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-destructive`,onClick:()=>c(e.name),"aria-label":g(`delete`),title:g(`delete`),children:(0,y.jsx)(o,{className:`size-4`})})]})]}),d.length>0?(0,y.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[d.map(e=>(0,y.jsx)(`span`,{className:`rounded-md bg-muted/28 px-1.5 py-0.5 text-[11px] text-muted-foreground/75`,title:e.quickForgeName,children:e.name},e.quickForgeName)),p>0?(0,y.jsx)(`span`,{className:`rounded-md px-1.5 py-0.5 text-[11px] text-muted-foreground/55`,children:g(`mcpMoreTools`,{count:p})}):null]}):null]})}function C(){return{name:``,transport:`stdio`,command:``,args:[],url:``,cwd:``,env:{}}}function w(e){return{name:e.name,transport:e.transport,command:e.command,args:e.args||[],url:e.url||``,cwd:e.cwd||``,env:e.env||{}}}function T(e){return(e||[]).join(`
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{B as t,C as n,D as r,Rt as i,Vt as a,a as o,g as s,st as c,x as l,y as u}from"./icons-C7j5jdKo.js";import{n as d}from"./react-vendor-VqdnQHHS.js";import{H as f,ct as p,dt as m,ht as h,ut as g,x as _}from"./index-DKmdePUP.js";var v=e(a(),1),y=d();function b(e){return e===`connected`?`bg-emerald-500/12 text-emerald-700 dark:text-emerald-300`:e===`error`?`bg-destructive/12 text-destructive`:e===`disabled`?`bg-muted text-muted-foreground`:`bg-amber-500/12 text-amber-700 dark:text-amber-300`}var x=12;function S({server:e,toggling:n,reconnecting:i,onToggle:a,onEdit:s,onDelete:c,onReconnect:l}){let d=e.tools?.slice(0,x)??[],f=e.toolCount??e.tools?.length??0,p=Math.max(0,f-d.length),_=e.enabled&&e.status!==`connected`;return(0,y.jsxs)(`div`,{className:`rounded-lg border border-border p-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,y.jsxs)(`div`,{className:`min-w-0`,children:[(0,y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,y.jsx)(`div`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.name}),(0,y.jsx)(`span`,{className:m(`rounded-full px-2 py-0.5 text-[11px]`,b(e.status)),children:e.status||`unknown`}),(0,y.jsx)(`span`,{className:`text-[11px] text-muted-foreground/60`,children:h(`mcpToolsCount`,{count:f})})]}),(0,y.jsx)(`div`,{className:`mt-1 truncate text-xs text-muted-foreground/65`,children:e.transport===`stdio`?`${e.command} ${(e.args||[]).join(` `)}`:e.url}),e.error?(0,y.jsx)(`div`,{className:`mt-1 text-xs text-destructive`,children:e.error}):null]}),(0,y.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1`,children:[(0,y.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":e.enabled,disabled:n,className:m(`relative h-6 w-11 rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-60`,e.enabled?`bg-emerald-500`:`bg-muted-foreground/30`),onClick:()=>a(e),title:e.enabled?h(`pauseTask`):h(`enable`),children:(0,y.jsx)(`span`,{className:m(`absolute left-0.5 top-0.5 size-5 rounded-full bg-white shadow transition-transform`,e.enabled?`translate-x-5`:`translate-x-0`)})}),_?(0,y.jsx)(g,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>l(e.name),disabled:i,"aria-label":h(`mcpReconnectServer`),title:h(`mcpReconnectServer`),children:i?(0,y.jsx)(t,{className:`size-4 animate-spin`}):(0,y.jsx)(u,{className:`size-4`})}):null,(0,y.jsx)(g,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>s(e),"aria-label":h(`editTask`),title:h(`editTask`),children:(0,y.jsx)(r,{className:`size-4`})}),(0,y.jsx)(g,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-destructive`,onClick:()=>c(e.name),"aria-label":h(`delete`),title:h(`delete`),children:(0,y.jsx)(o,{className:`size-4`})})]})]}),d.length>0?(0,y.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[d.map(e=>(0,y.jsx)(`span`,{className:`rounded-md bg-muted/28 px-1.5 py-0.5 text-[11px] text-muted-foreground/75`,title:e.quickForgeName,children:e.name},e.quickForgeName)),p>0?(0,y.jsx)(`span`,{className:`rounded-md px-1.5 py-0.5 text-[11px] text-muted-foreground/55`,children:h(`mcpMoreTools`,{count:p})}):null]}):null]})}function C(){return{name:``,transport:`stdio`,command:``,args:[],url:``,cwd:``,env:{}}}function w(e){return{name:e.name,transport:e.transport,command:e.command,args:e.args||[],url:e.url||``,cwd:e.cwd||``,env:e.env||{}}}function T(e){return(e||[]).join(`
2
2
  `)}function E(e){return Object.entries(e||{}).map(([e,t])=>`${e}=${t}`).join(`
3
3
  `)}function D(e){return e.split(`
4
4
  `).map(e=>e.trim()).filter(Boolean)}function O(e){let t={};for(let n of e.split(`
5
- `)){let e=n.trim();if(!e)continue;let r=e.indexOf(`=`);if(r<=0)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1).trim();i&&(t[i]=a)}return t}function k(e){let t={type:e.transport||`stdio`};e.transport===`stdio`?(t.command=e.command||``,t.args=e.args||[],e.cwd&&(t.cwd=e.cwd),e.env&&Object.keys(e.env).length>0&&(t.env=e.env)):(t.url=e.url||``,e.env&&Object.keys(e.env).length>0&&(t.headers=e.env));let n=e.name||`server`;return JSON.stringify({mcpServers:{[n]:t}},null,2)}function A(e){return!!(e&&typeof e==`object`&&!Array.isArray(e))}function j(e){let t;try{t=JSON.parse(e)}catch{throw Error(g(`mcpInvalidJson`))}if(!A(t))throw Error(g(`mcpInvalidConfigJson`));let n=``,r=null;if(A(t.mcpServers)){let e=Object.entries(t.mcpServers);if(e.length===0)throw Error(g(`mcpEmptyConfigJson`));let[i,a]=e[0];n=i,A(a)&&(r=a)}else r=t;if(!r)throw Error(g(`mcpInvalidConfigJson`));let i=String(r.transport||r.type||`stdio`);if(![`stdio`,`http`,`sse`].includes(i))throw Error(g(`mcpInvalidTransport`,{name:n||`server`}));let a=r.env??r.headers??{};return{name:n,transport:i,command:String(r.command||``),args:Array.isArray(r.args)?r.args:[],url:String(r.url||``),cwd:String(r.cwd||``),env:A(a)?a:{}}}var M=`mb-1 block text-xs text-muted-foreground/72`,N=`min-h-20 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,P=`flex h-9 w-full rounded-md border border-input bg-transparent px-3 text-sm outline-none focus:border-ring`;function F({value:e,onChange:t,isEdit:n,disabled:r}){let i=e.transport===`stdio`,a=n=>t({...e,...n});return(0,y.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,y.jsx)(`div`,{className:`text-xs text-muted-foreground/60`,children:g(n?`mcpEditServer`:`mcpAddServer`)}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-name`,children:g(`mcpServerName`)}),(0,y.jsx)(p,{id:`mcp-server-name`,value:e.name,onChange:e=>a({name:e.target.value}),placeholder:g(`mcpNamePlaceholder`),disabled:n||r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-transport`,children:g(`mcpTransport`)}),(0,y.jsxs)(`select`,{id:`mcp-server-transport`,className:P,value:e.transport,onChange:e=>a({transport:e.target.value}),disabled:r,children:[(0,y.jsx)(`option`,{value:`stdio`,children:`stdio`}),(0,y.jsx)(`option`,{value:`http`,children:`http`}),(0,y.jsx)(`option`,{value:`sse`,children:`sse`})]})]}),i?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-command`,children:g(`mcpCommand`)}),(0,y.jsx)(p,{id:`mcp-server-command`,value:e.command,onChange:e=>a({command:e.target.value}),placeholder:g(`mcpCommandPlaceholder`),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-args`,children:g(`mcpArgs`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-args`,className:N,value:T(e.args),onChange:e=>a({args:D(e.target.value)}),spellCheck:!1,disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-cwd`,children:g(`mcpCwd`)}),(0,y.jsx)(p,{id:`mcp-server-cwd`,value:e.cwd,onChange:e=>a({cwd:e.target.value}),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-env`,children:g(`mcpEnv`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-env`,className:N,value:E(e.env),onChange:e=>a({env:O(e.target.value)}),spellCheck:!1,disabled:r})]})]}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-url`,children:g(`mcpUrl`)}),(0,y.jsx)(p,{id:`mcp-server-url`,value:e.url,onChange:e=>a({url:e.target.value}),placeholder:g(`mcpUrlPlaceholder`),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-headers`,children:g(`mcpHeaders`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-headers`,className:N,value:E(e.env),onChange:e=>a({env:O(e.target.value)}),spellCheck:!1,disabled:r})]})]})]})}async function I(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function L({active:e=!0,className:r}){let[a,o]=(0,v.useState)([]),[u,d]=(0,v.useState)(!1),[p,b]=(0,v.useState)(!1),[x,T]=(0,v.useState)(new Set),[E,D]=(0,v.useState)(null),[O,A]=(0,v.useState)(``),[M,N]=(0,v.useState)(!1),[P,L]=(0,v.useState)(null),[R,z]=(0,v.useState)(C),[B,V]=(0,v.useState)(`form`),[H,U]=(0,v.useState)(``),[W,G]=(0,v.useState)(``),K=(0,v.useCallback)(e=>{o(e?.servers??[])},[]),q=(0,v.useCallback)(async()=>{d(!0),A(``);try{K(await I(await fetch(`/api/mcp/servers`)))}catch(e){A(e instanceof Error?e.message:g(`mcpLoadFailed`))}finally{d(!1)}},[K]);if((0,v.useEffect)(()=>{if(!e)return;let t=window.setTimeout(()=>{q()},0);return()=>window.clearTimeout(t)},[e,q]),!e)return null;let J=e=>{e===`json`&&(U(k(R)),G(``)),V(e)},Y=()=>{L(null),z(C()),V(`form`),N(!0),A(``)},X=e=>{let t=w(e);L(e),z(t),U(k(t)),G(``),V(`form`),N(!0),A(``)},Z=()=>{N(!1),L(null),U(``),G(``),A(``)},Q=e=>{z(e)},ee=e=>{U(e);try{let t=j(e);z(e=>({...t,name:t.name||e.name})),G(``)}catch(e){G(e instanceof Error?e.message:g(`mcpInvalidJson`))}},te=async()=>{if(!p){if(W&&B===`json`){A(W);return}b(!0),A(``);try{K(await I(await fetch(`/api/mcp/servers`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({server:{...R,enabled:P?.enabled??!0}})}))),Z()}catch(e){A(e instanceof Error?e.message:g(`mcpSaveFailed`))}finally{b(!1)}}},ne=async e=>{if(await f({description:g(`mcpDeleteConfirm`,{name:e}),confirmLabel:g(`confirmDelete`),cancelLabel:g(`cancel`),variant:`destructive`})){A(``);try{K(await I(await fetch(`/api/mcp/servers/${encodeURIComponent(e)}`,{method:`DELETE`})))}catch(e){A(e instanceof Error?e.message:g(`mcpDeleteFailed`))}}},re=async e=>{if(!x.has(e.name)){T(t=>new Set(t).add(e.name)),A(``);try{K(await I(await fetch(`/api/mcp/servers/${encodeURIComponent(e.name)}/enabled`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({enabled:!e.enabled})})))}catch(e){A(e instanceof Error?e.message:g(`mcpSaveFailed`))}finally{T(t=>{let n=new Set(t);return n.delete(e.name),n})}}},ie=async()=>{d(!0),A(``);try{K(await I(await fetch(`/api/mcp/reconnect`,{method:`POST`})))}catch(e){A(e instanceof Error?e.message:g(`mcpReconnectFailed`))}finally{d(!1)}},ae=async e=>{if(!E){D(e),A(``);try{K(await I(await fetch(`/api/mcp/reconnect/${encodeURIComponent(e)}`,{method:`POST`})))}catch(e){A(e instanceof Error?e.message:g(`mcpReconnectFailed`))}finally{D(null)}}},$=!!P,oe=!!R.name.trim()&&!!(R.transport===`stdio`?R.command.trim():R.url.trim());return M?(0,y.jsxs)(`div`,{className:h(`flex min-h-0 flex-1 flex-col overflow-hidden bg-background`,r),children:[(0,y.jsx)(`div`,{className:`border-b border-border px-6 py-5`,children:(0,y.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,y.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground`,onClick:Z,children:[(0,y.jsx)(i,{className:`size-4`}),g(`mcpConfiguredServers`)]}),(0,y.jsx)(`span`,{className:`text-sm font-medium text-foreground/90`,children:g($?`mcpEditServer`:`mcpAddServer`)})]})}),O?(0,y.jsx)(`div`,{className:`m-6 mb-0 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:O}):null,(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-6`,children:(0,y.jsxs)(`div`,{className:`mx-auto max-w-5xl space-y-5`,children:[(0,y.jsxs)(`div`,{className:`flex border-b border-border`,children:[(0,y.jsxs)(`button`,{type:`button`,onClick:()=>J(`form`),className:h(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,B===`form`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,y.jsx)(s,{className:`size-3.5`}),g(`mcpTabServer`)]}),(0,y.jsxs)(`button`,{type:`button`,onClick:()=>J(`json`),className:h(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,B===`json`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,y.jsx)(c,{className:`size-3.5`}),g(`mcpTabJson`)]})]}),(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:B===`form`?(0,y.jsx)(F,{value:R,onChange:Q,isEdit:$,disabled:p}):(0,y.jsxs)(`div`,{className:`space-y-2`,children:[(0,y.jsx)(`textarea`,{className:`min-h-96 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,value:H,onChange:e=>ee(e.target.value),spellCheck:!1}),W?(0,y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive`,children:W}):null,(0,y.jsxs)(`div`,{className:`inline-flex items-center gap-1.5 text-[11px] font-medium text-foreground/90`,children:[g(`mcpTabJson`),(0,y.jsx)(_,{label:g(`mcpImportConfigDescription`)})]})]})}),(0,y.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-border pt-3`,children:[(0,y.jsx)(m,{type:`button`,variant:`outline`,size:`sm`,onClick:Z,disabled:p,children:g(`cancel`)}),(0,y.jsxs)(m,{type:`button`,size:`sm`,onClick:()=>{te()},disabled:p||!oe,children:[p?(0,y.jsx)(t,{className:`mr-1.5 size-3.5 animate-spin`}):null,g(`save`)]})]})]})})]}):(0,y.jsxs)(`div`,{className:h(`flex min-h-0 flex-1 flex-col overflow-hidden bg-background`,r),children:[(0,y.jsx)(`div`,{className:`border-b border-border px-6 py-5`,children:(0,y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,y.jsx)(`h3`,{className:`text-sm font-medium text-foreground/90`,children:g(`mcpConfiguredServers`)}),(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,y.jsxs)(m,{type:`button`,variant:`ghost`,size:`sm`,onClick:Y,children:[(0,y.jsx)(n,{className:`mr-1.5 size-3.5`}),g(`mcpAddServer`)]}),(0,y.jsxs)(m,{type:`button`,variant:`ghost`,size:`sm`,onClick:ie,disabled:u,children:[u?(0,y.jsx)(t,{className:`mr-1.5 size-3.5 animate-spin`}):(0,y.jsx)(l,{className:`mr-1.5 size-3.5`}),g(`mcpReconnect`)]})]})]})}),O?(0,y.jsx)(`div`,{className:`m-6 mb-0 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:O}):null,(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-6`,children:(0,y.jsx)(`div`,{className:`mx-auto max-w-5xl space-y-5`,children:u&&a.length===0?(0,y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 rounded-lg border border-border py-8 text-sm text-muted-foreground`,children:[(0,y.jsx)(t,{className:`size-4 animate-spin`}),g(`loading`)]}):a.length===0?(0,y.jsx)(`div`,{className:`rounded-lg border border-border bg-muted/15 p-4 text-sm text-muted-foreground/72`,children:g(`mcpNoServersDescription`)}):a.map(e=>(0,y.jsx)(S,{server:e,toggling:x.has(e.name),reconnecting:E===e.name,onToggle:e=>{re(e)},onEdit:X,onDelete:e=>{ne(e)},onReconnect:e=>{ae(e)}},e.name))})})]})}export{L as McpServersPanel};
5
+ `)){let e=n.trim();if(!e)continue;let r=e.indexOf(`=`);if(r<=0)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1).trim();i&&(t[i]=a)}return t}function k(e){let t={type:e.transport||`stdio`};e.transport===`stdio`?(t.command=e.command||``,t.args=e.args||[],e.cwd&&(t.cwd=e.cwd),e.env&&Object.keys(e.env).length>0&&(t.env=e.env)):(t.url=e.url||``,e.env&&Object.keys(e.env).length>0&&(t.headers=e.env));let n=e.name||`server`;return JSON.stringify({mcpServers:{[n]:t}},null,2)}function A(e){return!!(e&&typeof e==`object`&&!Array.isArray(e))}function j(e){let t;try{t=JSON.parse(e)}catch{throw Error(h(`mcpInvalidJson`))}if(!A(t))throw Error(h(`mcpInvalidConfigJson`));let n=``,r=null;if(A(t.mcpServers)){let e=Object.entries(t.mcpServers);if(e.length===0)throw Error(h(`mcpEmptyConfigJson`));let[i,a]=e[0];n=i,A(a)&&(r=a)}else r=t;if(!r)throw Error(h(`mcpInvalidConfigJson`));let i=String(r.transport||r.type||`stdio`);if(![`stdio`,`http`,`sse`].includes(i))throw Error(h(`mcpInvalidTransport`,{name:n||`server`}));let a=r.env??r.headers??{};return{name:n,transport:i,command:String(r.command||``),args:Array.isArray(r.args)?r.args:[],url:String(r.url||``),cwd:String(r.cwd||``),env:A(a)?a:{}}}var M=`mb-1 block text-xs text-muted-foreground/72`,N=`min-h-20 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,P=`flex h-9 w-full rounded-md border border-input bg-transparent px-3 text-sm outline-none focus:border-ring`;function F({value:e,onChange:t,isEdit:n,disabled:r}){let i=e.transport===`stdio`,a=n=>t({...e,...n});return(0,y.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,y.jsx)(`div`,{className:`text-xs text-muted-foreground/60`,children:h(n?`mcpEditServer`:`mcpAddServer`)}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-name`,children:h(`mcpServerName`)}),(0,y.jsx)(_,{id:`mcp-server-name`,value:e.name,onChange:e=>a({name:e.target.value}),placeholder:h(`mcpNamePlaceholder`),disabled:n||r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-transport`,children:h(`mcpTransport`)}),(0,y.jsxs)(`select`,{id:`mcp-server-transport`,className:P,value:e.transport,onChange:e=>a({transport:e.target.value}),disabled:r,children:[(0,y.jsx)(`option`,{value:`stdio`,children:`stdio`}),(0,y.jsx)(`option`,{value:`http`,children:`http`}),(0,y.jsx)(`option`,{value:`sse`,children:`sse`})]})]}),i?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-command`,children:h(`mcpCommand`)}),(0,y.jsx)(_,{id:`mcp-server-command`,value:e.command,onChange:e=>a({command:e.target.value}),placeholder:h(`mcpCommandPlaceholder`),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-args`,children:h(`mcpArgs`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-args`,className:N,value:T(e.args),onChange:e=>a({args:D(e.target.value)}),spellCheck:!1,disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-cwd`,children:h(`mcpCwd`)}),(0,y.jsx)(_,{id:`mcp-server-cwd`,value:e.cwd,onChange:e=>a({cwd:e.target.value}),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-env`,children:h(`mcpEnv`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-env`,className:N,value:E(e.env),onChange:e=>a({env:O(e.target.value)}),spellCheck:!1,disabled:r})]})]}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-url`,children:h(`mcpUrl`)}),(0,y.jsx)(_,{id:`mcp-server-url`,value:e.url,onChange:e=>a({url:e.target.value}),placeholder:h(`mcpUrlPlaceholder`),disabled:r})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`label`,{className:M,htmlFor:`mcp-server-headers`,children:h(`mcpHeaders`)}),(0,y.jsx)(`textarea`,{id:`mcp-server-headers`,className:N,value:E(e.env),onChange:e=>a({env:O(e.target.value)}),spellCheck:!1,disabled:r})]})]})]})}async function I(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function L({active:e=!0,className:r}){let[a,o]=(0,v.useState)([]),[u,d]=(0,v.useState)(!1),[_,b]=(0,v.useState)(!1),[x,T]=(0,v.useState)(new Set),[E,D]=(0,v.useState)(null),[O,A]=(0,v.useState)(``),[M,N]=(0,v.useState)(!1),[P,L]=(0,v.useState)(null),[R,z]=(0,v.useState)(C),[B,V]=(0,v.useState)(`form`),[H,U]=(0,v.useState)(``),[W,G]=(0,v.useState)(``),K=(0,v.useCallback)(e=>{o(e?.servers??[])},[]),q=(0,v.useCallback)(async()=>{d(!0),A(``);try{K(await I(await fetch(`/api/mcp/servers`)))}catch(e){A(e instanceof Error?e.message:h(`mcpLoadFailed`))}finally{d(!1)}},[K]);if((0,v.useEffect)(()=>{if(!e)return;let t=window.setTimeout(()=>{q()},0);return()=>window.clearTimeout(t)},[e,q]),!e)return null;let J=e=>{e===`json`&&(U(k(R)),G(``)),V(e)},Y=()=>{L(null),z(C()),V(`form`),N(!0),A(``)},X=e=>{let t=w(e);L(e),z(t),U(k(t)),G(``),V(`form`),N(!0),A(``)},Z=()=>{N(!1),L(null),U(``),G(``),A(``)},Q=e=>{z(e)},ee=e=>{U(e);try{let t=j(e);z(e=>({...t,name:t.name||e.name})),G(``)}catch(e){G(e instanceof Error?e.message:h(`mcpInvalidJson`))}},te=async()=>{if(!_){if(W&&B===`json`){A(W);return}b(!0),A(``);try{K(await I(await fetch(`/api/mcp/servers`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({server:{...R,enabled:P?.enabled??!0}})}))),Z()}catch(e){A(e instanceof Error?e.message:h(`mcpSaveFailed`))}finally{b(!1)}}},ne=async e=>{if(await f({description:h(`mcpDeleteConfirm`,{name:e}),confirmLabel:h(`confirmDelete`),cancelLabel:h(`cancel`),variant:`destructive`})){A(``);try{K(await I(await fetch(`/api/mcp/servers/${encodeURIComponent(e)}`,{method:`DELETE`})))}catch(e){A(e instanceof Error?e.message:h(`mcpDeleteFailed`))}}},re=async e=>{if(!x.has(e.name)){T(t=>new Set(t).add(e.name)),A(``);try{K(await I(await fetch(`/api/mcp/servers/${encodeURIComponent(e.name)}/enabled`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({enabled:!e.enabled})})))}catch(e){A(e instanceof Error?e.message:h(`mcpSaveFailed`))}finally{T(t=>{let n=new Set(t);return n.delete(e.name),n})}}},ie=async()=>{d(!0),A(``);try{K(await I(await fetch(`/api/mcp/reconnect`,{method:`POST`})))}catch(e){A(e instanceof Error?e.message:h(`mcpReconnectFailed`))}finally{d(!1)}},ae=async e=>{if(!E){D(e),A(``);try{K(await I(await fetch(`/api/mcp/reconnect/${encodeURIComponent(e)}`,{method:`POST`})))}catch(e){A(e instanceof Error?e.message:h(`mcpReconnectFailed`))}finally{D(null)}}},$=!!P,oe=!!R.name.trim()&&!!(R.transport===`stdio`?R.command.trim():R.url.trim());return M?(0,y.jsxs)(`div`,{className:m(`flex min-h-0 flex-1 flex-col overflow-hidden bg-background`,r),children:[(0,y.jsx)(`div`,{className:`border-b border-border px-6 py-5`,children:(0,y.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,y.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground`,onClick:Z,children:[(0,y.jsx)(i,{className:`size-4`}),h(`mcpConfiguredServers`)]}),(0,y.jsx)(`span`,{className:`text-sm font-medium text-foreground/90`,children:h($?`mcpEditServer`:`mcpAddServer`)})]})}),O?(0,y.jsx)(`div`,{className:`m-6 mb-0 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:O}):null,(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-6`,children:(0,y.jsxs)(`div`,{className:`mx-auto max-w-5xl space-y-5`,children:[(0,y.jsxs)(`div`,{className:`flex border-b border-border`,children:[(0,y.jsxs)(`button`,{type:`button`,onClick:()=>J(`form`),className:m(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,B===`form`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,y.jsx)(s,{className:`size-3.5`}),h(`mcpTabServer`)]}),(0,y.jsxs)(`button`,{type:`button`,onClick:()=>J(`json`),className:m(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,B===`json`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,y.jsx)(c,{className:`size-3.5`}),h(`mcpTabJson`)]})]}),(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:B===`form`?(0,y.jsx)(F,{value:R,onChange:Q,isEdit:$,disabled:_}):(0,y.jsxs)(`div`,{className:`space-y-2`,children:[(0,y.jsx)(`textarea`,{className:`min-h-96 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,value:H,onChange:e=>ee(e.target.value),spellCheck:!1}),W?(0,y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive`,children:W}):null,(0,y.jsxs)(`div`,{className:`inline-flex items-center gap-1.5 text-[11px] font-medium text-foreground/90`,children:[h(`mcpTabJson`),(0,y.jsx)(p,{label:h(`mcpImportConfigDescription`)})]})]})}),(0,y.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-border pt-3`,children:[(0,y.jsx)(g,{type:`button`,variant:`outline`,size:`sm`,onClick:Z,disabled:_,children:h(`cancel`)}),(0,y.jsxs)(g,{type:`button`,size:`sm`,onClick:()=>{te()},disabled:_||!oe,children:[_?(0,y.jsx)(t,{className:`mr-1.5 size-3.5 animate-spin`}):null,h(`save`)]})]})]})})]}):(0,y.jsxs)(`div`,{className:m(`flex min-h-0 flex-1 flex-col overflow-hidden bg-background`,r),children:[(0,y.jsx)(`div`,{className:`border-b border-border px-6 py-5`,children:(0,y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,y.jsx)(`h3`,{className:`text-sm font-medium text-foreground/90`,children:h(`mcpConfiguredServers`)}),(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,y.jsxs)(g,{type:`button`,variant:`ghost`,size:`sm`,onClick:Y,children:[(0,y.jsx)(n,{className:`mr-1.5 size-3.5`}),h(`mcpAddServer`)]}),(0,y.jsxs)(g,{type:`button`,variant:`ghost`,size:`sm`,onClick:ie,disabled:u,children:[u?(0,y.jsx)(t,{className:`mr-1.5 size-3.5 animate-spin`}):(0,y.jsx)(l,{className:`mr-1.5 size-3.5`}),h(`mcpReconnect`)]})]})]})}),O?(0,y.jsx)(`div`,{className:`m-6 mb-0 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:O}):null,(0,y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-6`,children:(0,y.jsx)(`div`,{className:`mx-auto max-w-5xl space-y-5`,children:u&&a.length===0?(0,y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 rounded-lg border border-border py-8 text-sm text-muted-foreground`,children:[(0,y.jsx)(t,{className:`size-4 animate-spin`}),h(`loading`)]}):a.length===0?(0,y.jsx)(`div`,{className:`rounded-lg border border-border bg-muted/15 p-4 text-sm text-muted-foreground/72`,children:h(`mcpNoServersDescription`)}):a.map(e=>(0,y.jsx)(S,{server:e,toggling:x.has(e.name),reconnecting:E===e.name,onToggle:e=>{re(e)},onEdit:X,onDelete:e=>{ne(e)},onReconnect:e=>{ae(e)}},e.name))})})]})}export{L as McpServersPanel};
@@ -1 +1 @@
1
- import{i as e,n as t}from"./rolldown-runtime-DWdDZTNf.js";import{B as n,It as r,Rt as i,Vt as a,_ as o,n as s}from"./icons-C7j5jdKo.js";import{n as c}from"./react-vendor-VqdnQHHS.js";import{lt as l,pt as u,st as d}from"./index-_ut7awrd.js";var f=t({SkillsDialog:()=>_,SkillsManagerPanel:()=>g}),p=e(a(),1),m=c();async function h(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function g({active:e=!0,scope:t,project:a,embedded:c=!1,onClose:f,onSaved:g}){let[_,v]=(0,p.useState)([]),[y,b]=(0,p.useState)(()=>new Set),[x,S]=(0,p.useState)(``),[C,w]=(0,p.useState)([]),[T,E]=(0,p.useState)(!1),[D,O]=(0,p.useState)(!1),[k,A]=(0,p.useState)(``),j=t===`project`,[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(null),[I,L]=(0,p.useState)(!1),[R,z]=(0,p.useState)(``),B=(0,p.useCallback)(()=>{N(null),F(null),z(``)},[]),V=(0,p.useCallback)(()=>{B(),f?.()},[f,B]);(0,p.useEffect)(()=>{if(!e||j&&!a)return;let t=!1;return(async()=>{E(!0),A(``);try{let e=j?`/api/skills?projectId=${encodeURIComponent(a.id)}`:`/api/skills?scope=global`,n=await h(await fetch(e));if(t)return;v(Array.isArray(n.skills)?n.skills:[]),b(new Set(Array.isArray(n.selectedSkills)?n.selectedSkills:[])),w(Array.isArray(n.searchPaths)?n.searchPaths:[])}catch(e){t||A(e instanceof Error?e.message:u(`failedToLoadSkills`))}finally{t||E(!1)}})(),()=>{t=!0}},[e,a,j]),(0,p.useEffect)(()=>{if(!e||c)return;let t=e=>{e.key===`Escape`&&(M?B():D||V())};return document.addEventListener(`keydown`,t),()=>document.removeEventListener(`keydown`,t)},[e,V,c,D,M,B]);let H=(0,p.useMemo)(()=>{let e=x.trim().toLowerCase();return e?_.filter(t=>[t.name,t.displayName,t.description,t.source,t.compatibility,t.allowedTools,...t.tags??[],...t.triggers??[]].filter(Boolean).join(` `).toLowerCase().includes(e)):_},[x,_]),U=async e=>{N(e),F(null),z(``),L(!0);try{let t=new URLSearchParams({name:e});j&&a?(t.set(`scope`,`project`),t.set(`projectId`,a.id)):t.set(`scope`,`global`),F(await h(await fetch(`/api/skills/content?${t}`)))}catch(e){z(e instanceof Error?e.message:u(`failedToReadSkill`))}finally{L(!1)}};if(!e||j&&!a)return null;let W=e=>{if(D)return;let t=new Set(y);t.has(e)?t.delete(e):t.add(e),b(t),G(t)},G=async e=>{O(!0),A(``);try{let n=await h(await fetch(j?`/api/skills/project`:`/api/skills/global`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify(j?{projectId:a.id,selectedSkills:[...e]}:{selectedSkills:[...e]})}));g({scope:t,project:j?n.projects?.find(e=>e.id===a.id)??{...a,skills:n.selectedSkills}:void 0,projects:n.projects,selectedSkills:n.selectedSkills})}catch(e){b(y),A(e instanceof Error?e.message:u(`failedToSaveSkills`))}finally{O(!1)}},K=u(j?`projectSkills`:`globalSkills`),q=j?u(`projectSkillsDescription`,{project:a.name}):u(`globalSkillsDescription`),J=(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`div`,{className:`quickforge-settings-divider p-3`,children:(0,m.jsxs)(`div`,{className:`quickforge-settings-inline-field`,children:[(0,m.jsx)(o,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/60`}),(0,m.jsx)(`input`,{value:x,onChange:e=>S(e.target.value),placeholder:u(`searchSkills`),className:`quickforge-settings-input`,disabled:T||D})]})}),k?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:k}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsx)(`span`,{className:`quickforge-settings-row-title`,children:u(`availableSkills`)}),(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-info`,children:u(`selectedSkillsCount`,{count:y.size})})]}),(0,m.jsx)(`div`,{className:c?``:`max-h-[46vh] overflow-y-auto`,children:T?(0,m.jsxs)(`div`,{className:`quickforge-settings-empty-row inline-flex items-center gap-2`,children:[(0,m.jsx)(n,{className:`size-4 animate-spin`}),u(`loading`)]}):H.length===0?(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:u(`noMatchingSkills`)}):H.map(e=>{let t=y.has(e.name);return(0,m.jsxs)(`div`,{className:l(`quickforge-settings-list-item`,t&&`bg-muted/12`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-main`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-row-title`,children:e.displayName||e.name}),e.description?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:e.description}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-meta`,children:[e.source?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.source}):null,e.compatibility?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.compatibility}):null,e.allowedTools?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.allowedTools}):null,e.tags?.slice(0,5).map(e=>(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e},e))]})]}),(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-actions`,onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`label`,{className:`quickforge-settings-switch`,"aria-disabled":D?`true`:`false`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:t,disabled:D,onChange:()=>W(e.name),"aria-label":t?`Disable ${e.name}`:`Enable ${e.name}`}),(0,m.jsx)(`span`,{"aria-hidden":`true`})]}),(0,m.jsx)(`button`,{type:`button`,className:`quickforge-settings-icon-action`,onClick:()=>void U(e.name),disabled:D||I,title:u(`readSkill`),"aria-label":`${u(`readSkill`)}: ${e.displayName||e.name}`,children:(0,m.jsx)(r,{className:`size-4`})})]})]},e.name)})})]}),Y=(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`quickforge-settings-button quickforge-settings-button-secondary`,onClick:B,disabled:I,children:[(0,m.jsx)(i,{className:`mr-2 size-4`}),u(`backToSkillList`)]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-main min-w-0`,children:(0,m.jsx)(`div`,{className:`quickforge-settings-row-title truncate`,children:P?.displayName||P?.name||M})})]}),(0,m.jsx)(`div`,{className:`p-4`,children:I?(0,m.jsxs)(`div`,{className:`quickforge-settings-empty-row inline-flex items-center gap-2`,children:[(0,m.jsx)(n,{className:`size-4 animate-spin`}),u(`loading`)]}):R?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:R}):P?(0,m.jsxs)(m.Fragment,{children:[P.description?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description mb-3`,children:P.description}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-meta mb-3`,children:[P.version?(0,m.jsxs)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:[`v`,P.version]}):null,P.source?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.source}):null,P.compatibility?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.compatibility}):null,P.allowedTools?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.allowedTools}):null,P.license?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.license}):null,P.tags?.map(e=>(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e},e))]}),P.triggers?.length?(0,m.jsxs)(`div`,{className:`quickforge-settings-row-description mb-3`,children:[`Triggers: `,P.triggers.join(`, `)]}):null,P.instructions?(0,m.jsx)(`pre`,{className:`whitespace-pre-wrap break-words rounded-md border border-border bg-muted/30 px-4 py-3 font-mono text-sm leading-6 text-foreground/80`,children:P.instructions}):(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:u(`noSkillContent`)})]}):null})]});return c?(0,m.jsx)(`div`,{className:`quickforge-settings-stack`,children:(0,m.jsx)(`section`,{className:`quickforge-settings-section`,"aria-label":K,children:M?Y:(0,m.jsxs)(m.Fragment,{children:[C.length?(0,m.jsx)(`div`,{className:`px-5 pt-4`,children:(0,m.jsxs)(`span`,{className:`quickforge-settings-row-description break-all`,children:[u(`skillSearchPaths`),`: `,C.join(` · `)]})}):null,J]})})}):(0,m.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onClick:e=>{e.target===e.currentTarget&&!D&&V()},children:(0,m.jsxs)(`div`,{className:`flex max-h-[85vh] w-full max-w-2xl flex-col rounded-lg border border-border bg-background shadow-quickforge`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-title`,children:[K,(0,m.jsx)(d,{label:q})]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:q}),C.length?(0,m.jsxs)(`div`,{className:`quickforge-settings-row-description break-all`,children:[u(`skillSearchPaths`),`: `,C.join(` · `)]}):null]}),(0,m.jsx)(`button`,{type:`button`,className:`quickforge-settings-icon-action`,onClick:V,disabled:D,"aria-label":u(`close`),children:(0,m.jsx)(s,{className:`size-4`})})]}),(0,m.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:M?Y:J})]})})}function _({open:e,scope:t,project:n,onOpenChange:r,onSaved:i}){return(0,m.jsx)(g,{active:e,scope:t,project:n,onClose:()=>r(!1),onSaved:i})}export{f as n,_ as t};
1
+ import{i as e,n as t}from"./rolldown-runtime-DWdDZTNf.js";import{B as n,It as r,Rt as i,Vt as a,_ as o,n as s}from"./icons-C7j5jdKo.js";import{n as c}from"./react-vendor-VqdnQHHS.js";import{ct as l,dt as u,ht as d}from"./index-DKmdePUP.js";var f=t({SkillsDialog:()=>_,SkillsManagerPanel:()=>g}),p=e(a(),1),m=c();async function h(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function g({active:e=!0,scope:t,project:a,embedded:c=!1,onClose:f,onSaved:g}){let[_,v]=(0,p.useState)([]),[y,b]=(0,p.useState)(()=>new Set),[x,S]=(0,p.useState)(``),[C,w]=(0,p.useState)([]),[T,E]=(0,p.useState)(!1),[D,O]=(0,p.useState)(!1),[k,A]=(0,p.useState)(``),j=t===`project`,[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(null),[I,L]=(0,p.useState)(!1),[R,z]=(0,p.useState)(``),B=(0,p.useCallback)(()=>{N(null),F(null),z(``)},[]),V=(0,p.useCallback)(()=>{B(),f?.()},[f,B]);(0,p.useEffect)(()=>{if(!e||j&&!a)return;let t=!1;return(async()=>{E(!0),A(``);try{let e=j?`/api/skills?projectId=${encodeURIComponent(a.id)}`:`/api/skills?scope=global`,n=await h(await fetch(e));if(t)return;v(Array.isArray(n.skills)?n.skills:[]),b(new Set(Array.isArray(n.selectedSkills)?n.selectedSkills:[])),w(Array.isArray(n.searchPaths)?n.searchPaths:[])}catch(e){t||A(e instanceof Error?e.message:d(`failedToLoadSkills`))}finally{t||E(!1)}})(),()=>{t=!0}},[e,a,j]),(0,p.useEffect)(()=>{if(!e||c)return;let t=e=>{e.key===`Escape`&&(M?B():D||V())};return document.addEventListener(`keydown`,t),()=>document.removeEventListener(`keydown`,t)},[e,V,c,D,M,B]);let H=(0,p.useMemo)(()=>{let e=x.trim().toLowerCase();return e?_.filter(t=>[t.name,t.displayName,t.description,t.source,t.compatibility,t.allowedTools,...t.tags??[],...t.triggers??[]].filter(Boolean).join(` `).toLowerCase().includes(e)):_},[x,_]),U=async e=>{N(e),F(null),z(``),L(!0);try{let t=new URLSearchParams({name:e});j&&a?(t.set(`scope`,`project`),t.set(`projectId`,a.id)):t.set(`scope`,`global`),F(await h(await fetch(`/api/skills/content?${t}`)))}catch(e){z(e instanceof Error?e.message:d(`failedToReadSkill`))}finally{L(!1)}};if(!e||j&&!a)return null;let W=e=>{if(D)return;let t=new Set(y);t.has(e)?t.delete(e):t.add(e),b(t),G(t)},G=async e=>{O(!0),A(``);try{let n=await h(await fetch(j?`/api/skills/project`:`/api/skills/global`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify(j?{projectId:a.id,selectedSkills:[...e]}:{selectedSkills:[...e]})}));g({scope:t,project:j?n.projects?.find(e=>e.id===a.id)??{...a,skills:n.selectedSkills}:void 0,projects:n.projects,selectedSkills:n.selectedSkills})}catch(e){b(y),A(e instanceof Error?e.message:d(`failedToSaveSkills`))}finally{O(!1)}},K=d(j?`projectSkills`:`globalSkills`),q=j?d(`projectSkillsDescription`,{project:a.name}):d(`globalSkillsDescription`),J=(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`div`,{className:`quickforge-settings-divider p-3`,children:(0,m.jsxs)(`div`,{className:`quickforge-settings-inline-field`,children:[(0,m.jsx)(o,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/60`}),(0,m.jsx)(`input`,{value:x,onChange:e=>S(e.target.value),placeholder:d(`searchSkills`),className:`quickforge-settings-input`,disabled:T||D})]})}),k?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:k}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsx)(`span`,{className:`quickforge-settings-row-title`,children:d(`availableSkills`)}),(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-info`,children:d(`selectedSkillsCount`,{count:y.size})})]}),(0,m.jsx)(`div`,{className:c?``:`max-h-[46vh] overflow-y-auto`,children:T?(0,m.jsxs)(`div`,{className:`quickforge-settings-empty-row inline-flex items-center gap-2`,children:[(0,m.jsx)(n,{className:`size-4 animate-spin`}),d(`loading`)]}):H.length===0?(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:d(`noMatchingSkills`)}):H.map(e=>{let t=y.has(e.name);return(0,m.jsxs)(`div`,{className:u(`quickforge-settings-list-item`,t&&`bg-muted/12`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-main`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-row-title`,children:e.displayName||e.name}),e.description?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:e.description}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-meta`,children:[e.source?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.source}):null,e.compatibility?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.compatibility}):null,e.allowedTools?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e.allowedTools}):null,e.tags?.slice(0,5).map(e=>(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e},e))]})]}),(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-actions`,onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`label`,{className:`quickforge-settings-switch`,"aria-disabled":D?`true`:`false`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:t,disabled:D,onChange:()=>W(e.name),"aria-label":t?`Disable ${e.name}`:`Enable ${e.name}`}),(0,m.jsx)(`span`,{"aria-hidden":`true`})]}),(0,m.jsx)(`button`,{type:`button`,className:`quickforge-settings-icon-action`,onClick:()=>void U(e.name),disabled:D||I,title:d(`readSkill`),"aria-label":`${d(`readSkill`)}: ${e.displayName||e.name}`,children:(0,m.jsx)(r,{className:`size-4`})})]})]},e.name)})})]}),Y=(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`quickforge-settings-button quickforge-settings-button-secondary`,onClick:B,disabled:I,children:[(0,m.jsx)(i,{className:`mr-2 size-4`}),d(`backToSkillList`)]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-main min-w-0`,children:(0,m.jsx)(`div`,{className:`quickforge-settings-row-title truncate`,children:P?.displayName||P?.name||M})})]}),(0,m.jsx)(`div`,{className:`p-4`,children:I?(0,m.jsxs)(`div`,{className:`quickforge-settings-empty-row inline-flex items-center gap-2`,children:[(0,m.jsx)(n,{className:`size-4 animate-spin`}),d(`loading`)]}):R?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:R}):P?(0,m.jsxs)(m.Fragment,{children:[P.description?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description mb-3`,children:P.description}):null,(0,m.jsxs)(`div`,{className:`quickforge-settings-meta mb-3`,children:[P.version?(0,m.jsxs)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:[`v`,P.version]}):null,P.source?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.source}):null,P.compatibility?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.compatibility}):null,P.allowedTools?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.allowedTools}):null,P.license?(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:P.license}):null,P.tags?.map(e=>(0,m.jsx)(`span`,{className:`quickforge-settings-badge quickforge-settings-badge-muted`,children:e},e))]}),P.triggers?.length?(0,m.jsxs)(`div`,{className:`quickforge-settings-row-description mb-3`,children:[`Triggers: `,P.triggers.join(`, `)]}):null,P.instructions?(0,m.jsx)(`pre`,{className:`whitespace-pre-wrap break-words rounded-md border border-border bg-muted/30 px-4 py-3 font-mono text-sm leading-6 text-foreground/80`,children:P.instructions}):(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:d(`noSkillContent`)})]}):null})]});return c?(0,m.jsx)(`div`,{className:`quickforge-settings-stack`,children:(0,m.jsx)(`section`,{className:`quickforge-settings-section`,"aria-label":K,children:M?Y:(0,m.jsxs)(m.Fragment,{children:[C.length?(0,m.jsx)(`div`,{className:`px-5 pt-4`,children:(0,m.jsxs)(`span`,{className:`quickforge-settings-row-description break-all`,children:[d(`skillSearchPaths`),`: `,C.join(` · `)]})}):null,J]})})}):(0,m.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onClick:e=>{e.target===e.currentTarget&&!D&&V()},children:(0,m.jsxs)(`div`,{className:`flex max-h-[85vh] w-full max-w-2xl flex-col rounded-lg border border-border bg-background shadow-quickforge`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-title`,children:[K,(0,m.jsx)(l,{label:q})]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:q}),C.length?(0,m.jsxs)(`div`,{className:`quickforge-settings-row-description break-all`,children:[d(`skillSearchPaths`),`: `,C.join(` · `)]}):null]}),(0,m.jsx)(`button`,{type:`button`,className:`quickforge-settings-icon-action`,onClick:V,disabled:D,"aria-label":d(`close`),children:(0,m.jsx)(s,{className:`size-4`})})]}),(0,m.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:M?Y:J})]})})}function _({open:e,scope:t,project:n,onOpenChange:r,onSaved:i}){return(0,m.jsx)(g,{active:e,scope:t,project:n,onClose:()=>r(!1),onSaved:i})}export{f as n,_ as t};
package/dist/index.html CHANGED
@@ -11,7 +11,7 @@
11
11
  <meta name="apple-mobile-web-app-title" content="QuickForge" />
12
12
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
13
13
  <title>速构 QuickForge</title>
14
- <script type="module" crossorigin src="/assets/index-_ut7awrd.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-DKmdePUP.js"></script>
15
15
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-DWdDZTNf.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/pi-ai-Cr3rpCXT.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/lit-vendor-Dr3cpBGF.js">
@@ -20,9 +20,9 @@
20
20
  <link rel="modulepreload" crossorigin href="/assets/icons-C7j5jdKo.js">
21
21
  <link rel="modulepreload" crossorigin href="/assets/react-vendor-VqdnQHHS.js">
22
22
  <link rel="modulepreload" crossorigin href="/assets/logger-B65Akg8A.js">
23
- <link rel="modulepreload" crossorigin href="/assets/index-_ut7awrd.js">
24
- <link rel="modulepreload" crossorigin href="/assets/skills-dialog-Mnj8fZwq.js">
25
- <link rel="stylesheet" crossorigin href="/assets/index-Qof73j0o.css">
23
+ <link rel="modulepreload" crossorigin href="/assets/index-DKmdePUP.js">
24
+ <link rel="modulepreload" crossorigin href="/assets/skills-dialog-DvSnPPzu.js">
25
+ <link rel="stylesheet" crossorigin href="/assets/index-Bxg5fT2p.css">
26
26
  </head>
27
27
  <body>
28
28
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shawnstack/quickforge",
3
- "version": "1.6.9",
3
+ "version": "1.6.10",
4
4
  "description": "AI chat application with Agent access modes for local workspace tools. React + Vite + Tailwind CSS frontend, local Node.js storage server.",
5
5
  "keywords": [
6
6
  "ai",
@@ -18,12 +18,17 @@ const BACKUP_VERSION = 1
18
18
  const BACKUP_APP = 'quickforge'
19
19
  const IMPORT_UPLOAD_MAX_BYTES = Number(process.env.QUICKFORGE_IMPORT_UPLOAD_MAX_BYTES || 1024 * 1024 * 1024)
20
20
  const backupScopes = new Set(['all', 'config', 'sessions'])
21
- const restoreSectionIds = new Set(['settings', 'mcp', 'providerKeys', 'customProviders', 'projects', 'scheduledTasks', 'conversations'])
21
+ const settingsSectionIds = ['settings', 'mcp', 'providerKeys', 'customProviders', 'projects', 'scheduledTasks']
22
+ const exportSectionIds = new Set(settingsSectionIds)
23
+ const restoreSectionIds = new Set([...settingsSectionIds, 'conversations'])
22
24
  const restoreModes = new Set(['replace', 'merge'])
23
25
 
24
26
  function normalizeMode(value) {
25
27
  const mode = String(value || 'replace')
26
- return restoreModes.has(mode) ? mode : 'replace'
28
+ if (restoreModes.has(mode)) return mode
29
+ const error = new Error(`Invalid restore mode: ${mode}`)
30
+ error.statusCode = 400
31
+ throw error
27
32
  }
28
33
 
29
34
  function normalizeScope(value) {
@@ -36,25 +41,27 @@ function parseBoolean(value) {
36
41
  return text === '1' || text === 'true' || text === 'yes'
37
42
  }
38
43
 
39
- function extractCoreBackupFromText(text) {
40
- const backup = JSON.parse(text, (key, value) => (
41
- key === 'sessions' || key === 'sessionsMetadata' || key === 'sessions-metadata'
42
- ? undefined
43
- : value
44
- ))
45
- if (backup && typeof backup === 'object' && !Array.isArray(backup)) {
46
- if (backup.data && typeof backup.data === 'object' && !Array.isArray(backup.data)) {
47
- backup.scope = 'config'
48
- return backup
49
- }
50
- return {
51
- app: backup.app ?? BACKUP_APP,
52
- version: backup.version ?? BACKUP_VERSION,
53
- exportedAt: backup.exportedAt ?? null,
54
- scope: 'config',
55
- includeSecrets: backup.includeSecrets === true,
56
- data: backup,
44
+ function extractSettingsBackupFromText(text) {
45
+ let ignoredConversations = false
46
+ const backup = JSON.parse(text, (key, value) => {
47
+ if (key === 'sessions' || key === 'sessionsMetadata' || key === 'sessions-metadata') {
48
+ ignoredConversations = true
49
+ return undefined
57
50
  }
51
+ return value
52
+ })
53
+ if (backup && typeof backup === 'object' && !Array.isArray(backup)) {
54
+ const normalized = backup.data && typeof backup.data === 'object' && !Array.isArray(backup.data)
55
+ ? { ...backup, scope: 'config' }
56
+ : {
57
+ app: backup.app ?? BACKUP_APP,
58
+ version: backup.version ?? BACKUP_VERSION,
59
+ exportedAt: backup.exportedAt ?? null,
60
+ scope: 'config',
61
+ includeSecrets: backup.includeSecrets === true,
62
+ data: backup,
63
+ }
64
+ return { backup: normalized, ignoredConversations }
58
65
  }
59
66
  const error = new Error('Invalid backup file')
60
67
  error.statusCode = 400
@@ -92,9 +99,22 @@ async function readPendingImportBackup(token) {
92
99
  throw error
93
100
  }
94
101
  const file = path.join(storageDir, 'pending-imports', `${token}.json`)
95
- const backup = JSON.parse(await fs.readFile(file, 'utf8'))
102
+ try {
103
+ return JSON.parse(await fs.readFile(file, 'utf8'))
104
+ } catch (cause) {
105
+ if (cause?.code === 'ENOENT') {
106
+ const error = new Error('Import preview has expired. Please select the backup file again.')
107
+ error.statusCode = 400
108
+ throw error
109
+ }
110
+ throw cause
111
+ }
112
+ }
113
+
114
+ async function deletePendingImportBackup(token) {
115
+ if (!/^[0-9a-f-]{36}$/i.test(String(token || ''))) return
116
+ const file = path.join(storageDir, 'pending-imports', `${token}.json`)
96
117
  await fs.rm(file, { force: true })
97
- return backup
98
118
  }
99
119
 
100
120
  function backupTimestamp(date = new Date()) {
@@ -170,30 +190,48 @@ function normalizeSessionMetadata(sessions, metadata) {
170
190
  return nextMetadata
171
191
  }
172
192
 
193
+ function normalizeExportSections(value) {
194
+ if (value === null || value === undefined || value === '') return null
195
+ const items = Array.isArray(value) ? value : String(value).split(',')
196
+ const selected = new Set()
197
+ for (const item of items) {
198
+ const id = String(item).trim()
199
+ if (!exportSectionIds.has(id)) {
200
+ const error = new Error(`Invalid export section: ${id}`)
201
+ error.statusCode = 400
202
+ throw error
203
+ }
204
+ selected.add(id)
205
+ }
206
+ if (selected.size === 0) {
207
+ const error = new Error('No export sections selected')
208
+ error.statusCode = 400
209
+ throw error
210
+ }
211
+ return selected
212
+ }
213
+
173
214
  async function buildBackup(scope = 'all', options = {}) {
174
215
  const normalizedScope = normalizeScope(scope)
175
- const includeConfig = normalizedScope === 'all' || normalizedScope === 'config'
176
- const includeSessions = normalizedScope === 'all' || normalizedScope === 'sessions'
177
- const includeSecrets = Boolean(options.includeSecrets && includeConfig)
216
+ const selected = normalizeExportSections(options.sections)
217
+ const includeConfig = selected ? true : normalizedScope === 'all' || normalizedScope === 'config'
218
+ const includeSessions = selected ? false : normalizedScope === 'all' || normalizedScope === 'sessions'
219
+ const includeSecrets = selected ? selected.has('providerKeys') : Boolean(options.includeSecrets && includeConfig)
178
220
  const data = {}
179
221
 
180
222
  if (includeConfig) {
181
- const [settings, mcp, providerKeys, customProviders, projects, scheduledTasks] = await Promise.all([
182
- readStore('settings'),
183
- readStore('mcp'),
184
- includeSecrets ? readStore('provider-keys') : Promise.resolve(undefined),
185
- readStore('custom-providers'),
186
- readProjectConfigData(),
187
- readStore('scheduled-tasks'),
223
+ const shouldInclude = (id) => !selected || selected.has(id)
224
+ const entries = await Promise.all([
225
+ shouldInclude('settings') ? readStore('settings').then((value) => ['settings', value]) : null,
226
+ shouldInclude('mcp') ? readStore('mcp').then((value) => ['mcp', value]) : null,
227
+ shouldInclude('providerKeys') ? readStore('provider-keys').then((value) => ['providerKeys', value]) : null,
228
+ shouldInclude('customProviders') ? readStore('custom-providers').then((value) => ['customProviders', value]) : null,
229
+ shouldInclude('projects') ? readProjectConfigData().then((value) => ['projects', value]) : null,
230
+ shouldInclude('scheduledTasks') ? readStore('scheduled-tasks').then((value) => ['scheduledTasks', value]) : null,
188
231
  ])
189
- Object.assign(data, {
190
- settings,
191
- mcp,
192
- customProviders,
193
- projects,
194
- scheduledTasks,
195
- })
196
- if (includeSecrets) data.providerKeys = providerKeys
232
+ for (const entry of entries) {
233
+ if (entry) data[entry[0]] = entry[1]
234
+ }
197
235
  }
198
236
 
199
237
  if (includeSessions) {
@@ -211,7 +249,8 @@ async function buildBackup(scope = 'all', options = {}) {
211
249
  app: BACKUP_APP,
212
250
  version: BACKUP_VERSION,
213
251
  exportedAt: new Date().toISOString(),
214
- scope: normalizedScope,
252
+ scope: selected ? 'config' : normalizedScope,
253
+ exportedSections: selected ? settingsSectionIds.filter((id) => selected.has(id)) : undefined,
215
254
  includeSecrets,
216
255
  data,
217
256
  }
@@ -267,6 +306,42 @@ function normalizeBackupPayload(payload) {
267
306
  }
268
307
  }
269
308
 
309
+ function validateSettingsImportBackup(payload) {
310
+ const normalized = normalizeBackupPayload(payload)
311
+ const validSections = {}
312
+ const invalidSections = {}
313
+
314
+ for (const id of settingsSectionIds) {
315
+ const value = normalized.sections[id]
316
+ if (value === undefined) continue
317
+ try {
318
+ validSections[id] = id === 'projects'
319
+ ? assertProjectConfig(value)
320
+ : assertObjectSection(value, id)
321
+ } catch (error) {
322
+ invalidSections[id] = error instanceof Error ? error.message : `Invalid backup section: ${id}`
323
+ }
324
+ }
325
+
326
+ if (Object.keys(validSections).length === 0) {
327
+ const error = new Error('Backup does not contain any valid settings sections')
328
+ error.statusCode = 400
329
+ throw error
330
+ }
331
+
332
+ return {
333
+ backup: {
334
+ app: normalized.app,
335
+ version: normalized.version,
336
+ exportedAt: normalized.exportedAt,
337
+ scope: 'config',
338
+ includeSecrets: normalized.includeSecrets,
339
+ data: validSections,
340
+ },
341
+ invalidSections,
342
+ }
343
+ }
344
+
270
345
  function validateBackupPayload(payload) {
271
346
  const backup = normalizeBackupPayload(payload)
272
347
  const { sections } = backup
@@ -349,11 +424,20 @@ function backupWithSelectedSections(backup, selected) {
349
424
 
350
425
  function parseImportPayload(body) {
351
426
  const payload = body?.backup && typeof body.backup === 'object' ? body.backup : body
352
- const backup = validateBackupPayload(payload)
427
+ const normalized = normalizeBackupPayload(payload)
353
428
  const requestedSections = body?.backup && typeof body === 'object' ? body.sections : undefined
354
- const selected = normalizeRestoreSections(requestedSections, backup.sections)
429
+ const selected = normalizeRestoreSections(requestedSections, normalized.sections)
430
+ const filtered = selected ? backupWithSelectedSections(normalized, selected) : normalized
431
+ const backup = validateBackupPayload({
432
+ app: filtered.app,
433
+ version: filtered.version,
434
+ exportedAt: filtered.exportedAt,
435
+ scope: filtered.scope,
436
+ includeSecrets: filtered.includeSecrets,
437
+ data: filtered.sections,
438
+ })
355
439
  const mode = normalizeMode(body?.mode)
356
- return { backup: backupWithSelectedSections(backup, selected), mode }
440
+ return { backup, mode }
357
441
  }
358
442
 
359
443
  function countKeys(value) {
@@ -494,6 +578,7 @@ export async function handleBackupApi(req, res, url) {
494
578
  if (req.method === 'GET' && url.pathname === '/api/backup/export') {
495
579
  await ensureStorage()
496
580
  sendJson(res, 200, await buildBackup(url.searchParams.get('scope'), {
581
+ sections: url.searchParams.get('sections'),
497
582
  includeSecrets: parseBoolean(url.searchParams.get('includeSecrets')),
498
583
  }))
499
584
  return
@@ -509,10 +594,11 @@ export async function handleBackupApi(req, res, url) {
509
594
  if (req.method === 'POST' && url.pathname === '/api/backup/inspect-file') {
510
595
  await ensureStorage()
511
596
  const text = await readTextBody(req)
512
- const backup = extractCoreBackupFromText(text)
513
- const inspect = inspectBackup(backup)
514
- const token = await writePendingImportBackup(backup)
515
- sendJson(res, 200, { ...inspect, importToken: token })
597
+ const { backup, ignoredConversations } = extractSettingsBackupFromText(text)
598
+ const { backup: validBackup, invalidSections } = validateSettingsImportBackup(backup)
599
+ const inspect = inspectBackup(validBackup)
600
+ const token = await writePendingImportBackup(validBackup)
601
+ sendJson(res, 200, { ...inspect, invalidSections, ignoredConversations, importToken: token })
516
602
  return
517
603
  }
518
604
 
@@ -523,6 +609,7 @@ export async function handleBackupApi(req, res, url) {
523
609
  const { backup, mode } = parseImportPayload(importBody)
524
610
  const safetyBackupPath = await writeSafetyBackup(backup.sections.sessions !== undefined || backup.sections.sessionsMetadata !== undefined ? 'all' : 'config')
525
611
  const summary = await restoreValidatedBackup(backup, mode)
612
+ if (body?.importToken) await deletePendingImportBackup(body.importToken)
526
613
  sendJson(res, 200, { ok: true, safetyBackupPath, summary })
527
614
  return
528
615
  }
@@ -6,6 +6,7 @@ import { sendJson, readJsonBody } from '../utils/response.mjs'
6
6
  import { projectContextFromId } from '../project-config.mjs'
7
7
  import { readStore } from '../storage.mjs'
8
8
  import { logger } from '../utils/logger.mjs'
9
+ import { openPathInFileManager, openPathInIDEA, openPathInVSCode } from '../utils/platform.mjs'
9
10
  import {
10
11
  assertSafeWorkspacePath,
11
12
  resolveWorkspacePath,
@@ -745,6 +746,57 @@ async function handleWorkspaceResolvePath(req, res) {
745
746
  })
746
747
  }
747
748
 
749
+ export async function openWorkspaceExternalPath(context, inputPath, target, openers = {}) {
750
+ const relativePath = typeof inputPath === 'string' ? inputPath.trim() : ''
751
+ if (!relativePath) {
752
+ const error = new Error('path is required')
753
+ error.statusCode = 400
754
+ throw error
755
+ }
756
+ if (target !== 'explorer' && target !== 'vscode' && target !== 'idea') {
757
+ const error = new Error('target must be explorer, vscode, or idea')
758
+ error.statusCode = 400
759
+ throw error
760
+ }
761
+
762
+ const fullPath = resolveWorkspacePath(relativePath, context)
763
+ await assertSafeWorkspacePath(fullPath, context, {
764
+ allowSensitive: true,
765
+ ignoreMissing: true,
766
+ })
767
+ const stat = await fs.stat(fullPath).catch(() => null)
768
+
769
+ if (target === 'explorer') {
770
+ const directory = stat?.isDirectory() ? fullPath : path.dirname(fullPath)
771
+ await assertSafeWorkspacePath(directory, context, { allowSensitive: true })
772
+ await (openers.explorer ?? openPathInFileManager)(directory)
773
+ return { ok: true, opened: 'directory', target }
774
+ }
775
+
776
+ if (!stat?.isFile()) {
777
+ const error = new Error(`File does not exist: ${toWorkspaceRelative(fullPath, context)}`)
778
+ error.statusCode = 400
779
+ throw error
780
+ }
781
+ const opener = target === 'vscode'
782
+ ? (openers.vscode ?? openPathInVSCode)
783
+ : (openers.idea ?? openPathInIDEA)
784
+ await opener(fullPath)
785
+ return { ok: true, opened: 'file', target }
786
+ }
787
+
788
+ async function handleWorkspaceOpenExternal(req, res) {
789
+ const body = await readJsonBody(req, 16 * 1024)
790
+ const projectId = typeof body?.projectId === 'string' ? body.projectId : ''
791
+ if (!projectId) {
792
+ const error = new Error('projectId is required')
793
+ error.statusCode = 400
794
+ throw error
795
+ }
796
+ const context = await projectContextFromId(projectId)
797
+ sendJson(res, 200, await openWorkspaceExternalPath(context, body?.path, body?.target))
798
+ }
799
+
748
800
  async function handleGitStatus(req, res, url) {
749
801
  const context = await projectContextFromUrl(url)
750
802
  sendJson(res, 200, await listGitStatus(context))
@@ -938,6 +990,10 @@ export async function handleWorkspaceApi(req, res, url) {
938
990
  await handleWorkspaceResolvePath(req, res)
939
991
  return
940
992
  }
993
+ if (req.method === 'POST' && url.pathname === '/api/workspace/open-external') {
994
+ await handleWorkspaceOpenExternal(req, res)
995
+ return
996
+ }
941
997
 
942
998
  const error = new Error('Not found')
943
999
  error.statusCode = 404
@@ -186,8 +186,8 @@ export async function openPathInFileManager(targetPath) {
186
186
  export async function openPathInVSCode(targetPath) {
187
187
  const resolved = path.resolve(String(targetPath || ''))
188
188
  const stat = await fs.stat(resolved).catch(() => null)
189
- if (!stat || !stat.isDirectory()) {
190
- const error = new Error(`Directory does not exist: ${resolved}`)
189
+ if (!stat || (!stat.isDirectory() && !stat.isFile())) {
190
+ const error = new Error(`Path does not exist: ${resolved}`)
191
191
  error.statusCode = 400
192
192
  throw error
193
193
  }
@@ -234,8 +234,8 @@ export async function openPathInVSCode(targetPath) {
234
234
  export async function openPathInIDEA(targetPath) {
235
235
  const resolved = path.resolve(String(targetPath || ''))
236
236
  const stat = await fs.stat(resolved).catch(() => null)
237
- if (!stat || !stat.isDirectory()) {
238
- const error = new Error(`Directory does not exist: ${resolved}`)
237
+ if (!stat || (!stat.isDirectory() && !stat.isFile())) {
238
+ const error = new Error(`Path does not exist: ${resolved}`)
239
239
  error.statusCode = 400
240
240
  throw error
241
241
  }
@@ -1 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{D as t,Ft as n,Rt as r,Vt as i,a,dt as ee,l as o}from"./icons-C7j5jdKo.js";import{i as s,n as c}from"./react-vendor-VqdnQHHS.js";import{$ as te,Q as ne,V as l,Z as re,ct as u,et as ie,lt as ae,pt as d,st as f,tt as oe}from"./index-_ut7awrd.js";var p=e(i(),1),se=s(),m=c(),h=144,g=82,_=4,v=8;function y(e){return JSON.stringify({provider:e.provider,modelId:e.id,api:e.api,baseUrl:e.baseUrl})}function b(e){if(!e)return{mode:`inherit`};try{let t=JSON.parse(e);return{mode:`fixed`,provider:String(t.provider||``),modelId:String(t.modelId||``),api:t.api?String(t.api):void 0,baseUrl:t.baseUrl?String(t.baseUrl):void 0}}catch{return{mode:`inherit`}}}function x(e){return!e||e.mode!==`fixed`?``:JSON.stringify({provider:e.provider,modelId:e.modelId,api:e.api,baseUrl:e.baseUrl})}function ce(e){return e.name||`${e.provider}/${e.id}`}function S(){return{name:``,label:``,description:``,systemPrompt:``,allowedTools:[`read_file`,`grep_files`],maxRuntimeMs:`1800000`,maxToolCalls:`300`,enabledAsSubagent:!0,modelMode:`inherit`,fixedModelValue:``,thinkingLevel:`inherit`}}function le(e){return{name:e.name,label:e.label,description:e.description??``,systemPrompt:e.systemPrompt??``,allowedTools:e.allowedTools??[],maxRuntimeMs:String(e.maxRuntimeMs??18e5),maxToolCalls:String(e.maxToolCalls??300),enabledAsSubagent:e.enabledAsSubagent,modelMode:e.model?.mode===`fixed`?`fixed`:`inherit`,fixedModelValue:x(e.model),thinkingLevel:e.thinkingLevel??`inherit`}}function ue(e){return{name:e.name.trim().toLowerCase(),label:e.label.trim(),description:e.description.trim(),systemPrompt:e.systemPrompt.trim(),allowedTools:e.allowedTools,maxRuntimeMs:Number(e.maxRuntimeMs||18e5),maxToolCalls:Number(e.maxToolCalls||300),enabledAsSubagent:e.enabledAsSubagent,model:e.modelMode===`fixed`?b(e.fixedModelValue):{mode:`inherit`},thinkingLevel:e.thinkingLevel}}function C(e){return!!(e.name.trim()&&e.label.trim()&&e.allowedTools.length>0)}async function w(e,t){let n=await fetch(e,{...t,headers:{"content-type":`application/json`,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`请求失败`);return r}function T(){let[e,i]=(0,p.useState)([]),[s,c]=(0,p.useState)([]),[x,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(()=>S()),[A,j]=(0,p.useState)(!1),[M,N]=(0,p.useState)(``),[P,F]=(0,p.useState)(!1),[I,de]=(0,p.useState)(),[L,fe]=(0,p.useState)([]),[pe,me]=(0,p.useState)(`off`),[R,z]=(0,p.useState)(``),[B,V]=(0,p.useState)(null),[H,U]=(0,p.useState)(null);async function W(){let[e,t]=await Promise.all([w(`/api/agent-profiles`),w(`/api/agent-profiles/available-tools`)]);i(e.agents),c(t.tools)}(0,p.useEffect)(()=>{let e=!1;async function t(){try{let[t,n]=await Promise.all([w(`/api/agent-profiles`),w(`/api/agent-profiles/available-tools`)]);if(e)return;i(t.agents),c(n.tools)}catch(t){e||z(t instanceof Error?t.message:d(`requestFailed`))}}return t(),()=>{e=!0}},[]),(0,p.useEffect)(()=>{let e=!1;async function t(){try{let t=await te(),n=await ne(t);fe(n);let r=await ie(t),i=r.model??await oe(t)??n[0];if(e)return;de(i),me(r.thinkingLevel??re(i))}catch{}}return t(),()=>{e=!0}},[]),(0,p.useEffect)(()=>{if(!B)return;let e=()=>{V(null),U(null)},t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),window.addEventListener(`scroll`,e,!0),document.addEventListener(`keydown`,t),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e),window.removeEventListener(`scroll`,e,!0),document.removeEventListener(`keydown`,t)}},[B]);let G=(0,p.useMemo)(()=>e.find(e=>e.id===E)??null,[e,E]),K=(0,p.useMemo)(()=>e.find(e=>e.id===B)??null,[e,B]),q=!!G?.readonly,J=!!(G?.readonly&&!G?.builtin),Y=(0,p.useMemo)(()=>L.find(e=>y(e)===O.fixedModelValue),[O.fixedModelValue,L]),X=O.modelMode===`fixed`&&!!Y&&Y?.reasoning!==!0;function he(e,t){if(e.stopPropagation(),B===t){V(null),U(null);return}let n=e.currentTarget.getBoundingClientRect(),r=Math.max(v,Math.min(n.right-h,window.innerWidth-h-v)),i=n.bottom+_,a=n.top-_-g;U({left:r,top:i+g<=window.innerHeight-v?i:Math.max(v,a)}),V(t)}function Z(e,t){k(n=>({...n,[e]:t}))}function ge(e){k(t=>({...t,allowedTools:t.allowedTools.includes(e)?t.allowedTools.filter(t=>t!==e):[...t.allowedTools,e]}))}function _e(){D(null),k(S()),N(``),z(``),T(!0)}function Q(e){D(e.id),k(le(e)),N(``),z(``),T(!0)}function $(){A||P||(T(!1),D(null),k(S()),N(``))}async function ve(){let e=M.trim();if(!e){z(d(`aiFillAgentInputRequired`));return}if(!I){z(d(`aiFillAgentNoModel`));return}F(!0),z(``);try{let t=await w(`/api/agent-profiles/ai-fill`,{method:`POST`,body:JSON.stringify({instruction:e,model:I,thinkingLevel:pe})});k(e=>({...e,name:t.agent.name,label:t.agent.label,description:t.agent.description,systemPrompt:t.agent.systemPrompt}))}catch(e){z(e instanceof Error?e.message:d(`aiFillAgentFailed`))}finally{F(!1)}}async function ye(){if(C(O)){j(!0),z(``);try{let e=G?.builtin?{model:O.modelMode===`fixed`?b(O.fixedModelValue):{mode:`inherit`}}:ue({...O,thinkingLevel:X?`off`:O.thinkingLevel});E?await w(`/api/agent-profiles/${encodeURIComponent(E)}`,{method:`PATCH`,body:JSON.stringify(e)}):await w(`/api/agent-profiles`,{method:`POST`,body:JSON.stringify(e)}),$(),await W()}catch(e){z(e instanceof Error?e.message:d(`requestFailed`))}finally{j(!1)}}}async function be(e){if(e.builtin||e.readonly)return;let t=!e.enabledAsSubagent,n=e.enabledAsSubagent;i(n=>n.map(n=>n.id===e.id?{...n,enabledAsSubagent:t}:n)),V(null);try{await w(`/api/agent-profiles/${encodeURIComponent(e.id)}`,{method:`PATCH`,body:JSON.stringify({enabledAsSubagent:t})})}catch(t){i(t=>t.map(t=>t.id===e.id?{...t,enabledAsSubagent:n}:t)),z(t instanceof Error?t.message:d(`requestFailed`))}}async function xe(e){if(!(e.builtin||e.readonly)&&await l({description:d(`confirmDeleteAgent`),confirmLabel:d(`confirmDelete`),cancelLabel:d(`cancel`),variant:`destructive`})){z(``);try{await w(`/api/agent-profiles/${encodeURIComponent(e.id)}`,{method:`DELETE`}),await W()}catch(e){z(e instanceof Error?e.message:d(`requestFailed`))}}}return x?(0,m.jsxs)(`div`,{className:`quickforge-settings-stack`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-heading`,children:(0,m.jsxs)(`h3`,{className:`quickforge-settings-title`,children:[G?.builtin?d(`builtinAgentModelSettings`):d(G?`editAgent`:`createAgent`),(0,m.jsx)(f,{label:G?.builtin?d(`builtinAgentModelOnly`):G?.readonly?d(`readonlyAgentDescription`):d(`agentsDescription`)})]})}),(0,m.jsxs)(`section`,{className:`quickforge-settings-section`,"aria-label":d(G?`editAgent`:`createAgent`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`button`,{className:`quickforge-settings-button quickforge-settings-button-secondary`,type:`button`,onClick:$,disabled:A||P,children:[(0,m.jsx)(r,{className:`mr-2 size-4`}),d(`back`)]}),(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-row-title`,children:G?.builtin?d(`builtinAgentModelSettings`):d(G?`editAgent`:`createAgent`)}),G?.builtin?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:d(`builtinAgentModelOnly`)}):G?.readonly?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:d(`readonlyAgentDescription`)}):null]})]}),(0,m.jsx)(`div`,{className:`px-5 py-4`,children:(0,m.jsxs)(`div`,{className:`space-y-4`,children:[(0,m.jsxs)(`div`,{className:`rounded-2xl border border-border bg-muted/20 p-3`,children:[(0,m.jsxs)(`div`,{className:`mb-2 flex items-center gap-2 text-sm font-medium text-foreground`,children:[(0,m.jsx)(o,{className:`size-4 text-primary`}),d(`aiFillAgent`),(0,m.jsx)(f,{label:d(`aiFillAgentDescription`)})]}),(0,m.jsx)(`textarea`,{className:`min-h-20 w-full resize-y rounded-xl border border-input bg-background px-3 py-2 text-sm outline-none transition-colors placeholder:text-muted-foreground/65 focus:border-ring disabled:opacity-60`,value:M,disabled:q||P,onChange:e=>N(e.target.value),placeholder:d(`aiFillAgentPlaceholder`)}),(0,m.jsx)(`div`,{className:`mt-2 flex justify-end`,children:(0,m.jsxs)(u,{variant:`outline`,size:`sm`,onClick:()=>void ve(),disabled:q||P||!M.trim(),children:[(0,m.jsx)(o,{className:`mr-1 size-3.5`}),d(P?`aiFillAgentLoading`:`aiFillAgent`)]})})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentName`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.name,disabled:q,onChange:e=>Z(`name`,e.target.value),placeholder:`reviewer`})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentLabel`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.label,disabled:q,onChange:e=>Z(`label`,e.target.value),placeholder:d(`agentLabelPlaceholder`)})]})]}),G?(0,m.jsxs)(`div`,{className:`rounded-xl border border-border bg-muted/20 px-3 py-2 text-sm`,children:[(0,m.jsx)(`div`,{className:`text-xs font-medium text-muted-foreground`,children:d(`agentSourcePath`)}),(0,m.jsx)(`div`,{className:`mt-1 truncate font-mono text-xs text-foreground`,title:G.source?`${G.source}${G.relativePath?` · ${G.relativePath}`:``}`:void 0,children:G.source?`${G.source}${G.relativePath?` · ${G.relativePath}`:``}`:G.builtin?d(`builtinAgent`):`-`})]}):null,(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentDescription`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.description,disabled:q,onChange:e=>Z(`description`,e.target.value)})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentSystemPrompt`),(0,m.jsx)(`textarea`,{className:`mt-1 min-h-36 w-full resize-y rounded-xl border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.systemPrompt,disabled:q,onChange:e=>Z(`systemPrompt`,e.target.value)})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentModelMode`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.modelMode,disabled:J,onChange:e=>Z(`modelMode`,e.target.value),children:[(0,m.jsx)(`option`,{value:`inherit`,children:d(`agentModelInherit`)}),(0,m.jsx)(`option`,{value:`fixed`,children:d(`agentModelFixed`)})]})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentFixedModel`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.fixedModelValue,disabled:J||O.modelMode!==`fixed`,onChange:e=>Z(`fixedModelValue`,e.target.value),children:[(0,m.jsx)(`option`,{value:``,children:d(`agentModelInherit`)}),L.map(e=>(0,m.jsx)(`option`,{value:y(e),children:ce(e)},y(e)))]})]})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`agentThinkingLevel`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:X&&O.thinkingLevel!==`inherit`?`off`:O.thinkingLevel,disabled:q||X,onChange:e=>Z(`thinkingLevel`,e.target.value),children:[(0,m.jsx)(`option`,{value:`inherit`,children:d(`agentThinkingInherit`)}),(0,m.jsx)(`option`,{value:`off`,children:d(`thinkingOff`)}),(0,m.jsx)(`option`,{value:`low`,children:d(`thinkingLow`)}),(0,m.jsx)(`option`,{value:`medium`,children:d(`thinkingMedium`)}),(0,m.jsx)(`option`,{value:`high`,children:d(`thinkingHigh`)}),(0,m.jsx)(`option`,{value:`xhigh`,children:d(`thinkingXHigh`)})]}),(0,m.jsx)(`span`,{className:`mt-1 block text-xs text-muted-foreground`,children:d(X?`agentThinkingUnsupported`:`agentThinkingDescription`)})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`div`,{className:`mb-2 text-sm font-medium text-foreground`,children:d(`allowedTools`)}),(0,m.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2`,children:s.map(e=>(0,m.jsxs)(`label`,{className:`flex items-start gap-2 rounded-xl border border-border bg-muted/20 p-3 text-sm disabled:opacity-60`,children:[(0,m.jsx)(`input`,{type:`checkbox`,className:`mt-1`,disabled:q,checked:O.allowedTools.includes(e.name),onChange:()=>ge(e.name)}),(0,m.jsxs)(`span`,{children:[(0,m.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,m.jsx)(`span`,{className:`ml-2 font-mono text-xs text-muted-foreground`,children:e.name}),e.riskLevel===`dangerous`?(0,m.jsx)(`span`,{className:`ml-2 rounded-full bg-amber-500/10 px-2 py-0.5 text-xs text-amber-700`,children:d(`highRiskTool`)}):null,(0,m.jsx)(`span`,{className:`mt-1 block text-xs text-muted-foreground`,children:e.description})]})]},e.name))})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`maxRuntimeMs`),(0,m.jsx)(`input`,{type:`number`,className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.maxRuntimeMs,disabled:q,onChange:e=>Z(`maxRuntimeMs`,e.target.value)})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[d(`maxToolCalls`),(0,m.jsx)(`input`,{type:`number`,className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.maxToolCalls,disabled:q,onChange:e=>Z(`maxToolCalls`,e.target.value)})]})]}),(0,m.jsxs)(`label`,{className:`flex items-center gap-2 text-sm text-foreground`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:O.enabledAsSubagent,disabled:q,onChange:e=>Z(`enabledAsSubagent`,e.target.checked)}),d(`enabledAsSubagent`)]}),R?(0,m.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:R}):null]})}),(0,m.jsxs)(`div`,{className:`quickforge-settings-divider flex justify-end gap-2 px-5 py-4`,children:[(0,m.jsx)(u,{variant:`outline`,onClick:$,disabled:A||P,children:d(`cancel`)}),(0,m.jsx)(u,{onClick:ye,disabled:A||P||J||!G?.builtin&&!C(O)||O.modelMode===`fixed`&&!O.fixedModelValue,children:d(`save`)})]})]})]}):(0,m.jsxs)(`div`,{className:`quickforge-settings-stack`,children:[(0,m.jsxs)(`section`,{className:`quickforge-settings-section`,"aria-label":d(`agentsTab`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-title`,children:[(0,m.jsx)(n,{className:`size-4 text-primary`}),d(`agentsTab`)]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:d(`agentsDescription`)})]}),(0,m.jsx)(`button`,{className:`quickforge-settings-button quickforge-settings-button-primary`,type:`button`,onClick:_e,children:d(`createAgent`)})]}),R?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:R}):null,e.length===0?(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:d(`loading`)}):e.map(e=>(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item quickforge-agent-profile-row`,role:`button`,tabIndex:0,onClick:()=>Q(e),onKeyDown:t=>{t.target===t.currentTarget&&(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),Q(e))},children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-main quickforge-agent-profile-row-main`,children:[(0,m.jsx)(`span`,{className:ae(`quickforge-agent-profile-status-dot`,e.enabledAsSubagent?`quickforge-agent-profile-status-dot--enabled`:null),"aria-label":e.enabledAsSubagent?d(`enabled`):d(`disabled`),title:e.enabledAsSubagent?d(`enabled`):d(`disabled`)}),(0,m.jsxs)(`div`,{className:`quickforge-agent-profile-summary`,children:[(0,m.jsx)(`span`,{className:`quickforge-agent-profile-label`,title:e.label,children:e.label}),(0,m.jsx)(`span`,{className:`quickforge-agent-profile-name quickforge-settings-mono`,title:e.name,children:e.name}),(0,m.jsxs)(`span`,{className:`quickforge-agent-profile-description`,title:e.description||d(`noDescription`),children:[`· `,e.description||d(`noDescription`)]}),(0,m.jsxs)(`span`,{className:`quickforge-agent-profile-name quickforge-settings-mono`,title:e.model?.mode===`fixed`?`${e.model.provider}/${e.model.modelId}`:d(`agentModelInherit`),children:[`· `,e.model?.mode===`fixed`?`${e.model.provider}/${e.model.modelId}`:d(`agentModelInherit`)]})]})]}),(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-actions`,onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`label`,{className:`quickforge-settings-switch`,"aria-disabled":e.builtin||e.readonly?`true`:`false`,title:e.enabledAsSubagent?d(`disableAsSubagent`):d(`enableAsSubagent`),children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:e.enabledAsSubagent,disabled:e.builtin||e.readonly,onChange:()=>void be(e)}),(0,m.jsx)(`span`,{"aria-hidden":`true`})]}),(0,m.jsx)(`button`,{className:`quickforge-settings-icon-action`,type:`button`,onClick:t=>he(t,e.id),title:d(`moreActions`),"aria-label":d(`moreActions`),"aria-haspopup":`menu`,"aria-expanded":B===e.id,children:(0,m.jsx)(ee,{className:`size-4`})})]})]},e.id))]}),K&&H?(0,se.createPortal)((0,m.jsxs)(`div`,{className:`fixed z-50 w-36 overflow-hidden rounded-xl border border-border bg-popover py-1 text-sm shadow-quickforge`,style:{left:H.left,top:H.top},role:`menu`,"aria-label":d(`moreActions`),onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`button`,{className:`flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,type:`button`,role:`menuitem`,disabled:K.readonly&&!K.builtin,onClick:()=>{V(null),U(null),Q(K)},children:[(0,m.jsx)(t,{className:`size-3.5`}),K.builtin?d(`builtinAgentModelSettings`):d(`editTask`)]}),(0,m.jsxs)(`button`,{className:`flex w-full items-center gap-2 px-3 py-2 text-left text-destructive hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,type:`button`,role:`menuitem`,disabled:K.builtin||K.readonly,onClick:()=>{V(null),U(null),xe(K)},children:[(0,m.jsx)(a,{className:`size-3.5`}),d(`delete`)]})]}),document.body):null]})}export{T as AgentProfilesPage};
@@ -1,2 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,B as n,C as r,N as i,R as a,Vt as o,c as s,n as c}from"./icons-C7j5jdKo.js";import{n as l}from"./react-vendor-VqdnQHHS.js";import{A as u,N as d,T as f,ct as p,lt as m,pt as h}from"./index-_ut7awrd.js";import{n as ee,t as g}from"./xterm-CGiQzDiR.js";var _=e(o(),1);async function v(e,t){let n=await fetch(e,{cache:`no-store`,...t}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Request failed: ${n.status}`);return r}function y(){return v(`/api/terminal/capabilities`)}function b(e){return v(`/api/terminal/sessions${e?`?projectId=${encodeURIComponent(e)}`:``}`)}function x(e){return v(`/api/terminal/sessions`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)})}function S(e){return v(`/api/terminal/sessions/${encodeURIComponent(e)}`,{method:`DELETE`})}function C(e,t){return v(`/api/terminal/sessions/${encodeURIComponent(e)}/input`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({data:t})})}function w(){return``}function te(){let e=w();if(e){let t=new URL(e);return t.protocol=t.protocol===`https:`?`wss:`:`ws:`,t.toString().replace(/\/$/,``)}return`${location.protocol===`https:`?`wss:`:`ws:`}//${location.host}`}function T(){let[e,t]=(0,_.useState)(()=>f());return(0,_.useEffect)(()=>{if(typeof document>`u`)return;let e=document.documentElement,n=()=>t(f());n();let r=new MutationObserver(n);return r.observe(e,{attributes:!0,attributeFilter:[`class`]}),()=>r.disconnect()},[]),e}var E=l(),D={light:{background:`#ffffff`,foreground:`#1f2937`,cursor:`#1f2937`,selectionBackground:`#dbeafe`},dark:{background:`#171717`,foreground:`#e5e7eb`,cursor:`#e5e7eb`,selectionBackground:`#3f3f46`}};function ne({session:e,active:t,height:n,onReady:r,onExited:i,onConnectionError:a}){let o=T(),s=D[o],c=(0,_.useRef)(null),l=(0,_.useRef)(null),f=(0,_.useRef)(null),p=(0,_.useRef)(null),m=(0,_.useRef)(null),v=(0,_.useRef)(null);return(0,_.useEffect)(()=>{let t=c.current;if(!t)return;let n=!1,o=!1,_=!1,y=!1,b=t=>{n||_||y||(y=!0,a(e.id,t))},x=d(),S=new ee({cursorBlink:!0,convertEol:!1,fontFamily:getComputedStyle(document.documentElement).getPropertyValue(`--font-mono`).trim()||`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace`,fontSize:x.fontSize,lineHeight:x.lineHeight,scrollback:5e3,theme:s}),C=new g;S.loadAddon(C),S.open(t),S.writeln(`\x1b[2mConnected to ${e.cwd}\x1b[0m`),l.current=S,f.current=C;let w=()=>{if(t.isConnected)try{C.fit();let{cols:e,rows:t}=S,n=p.current;n?.readyState===WebSocket.OPEN&&n.send(JSON.stringify({type:`resize`,cols:e,rows:t}))}catch{}},T=new WebSocket(`${te()}/api/terminal/sessions/${encodeURIComponent(e.id)}/ws`);p.current=T,T.addEventListener(`open`,()=>{o=!0,y=!1,a(e.id,void 0),m.current=S.onData(e=>{T.readyState===WebSocket.OPEN&&T.send(JSON.stringify({type:`input`,data:e}))}),window.setTimeout(w,0)}),T.addEventListener(`message`,t=>{try{let n=JSON.parse(String(t.data));n.type===`ready`?r(e.id):n.type===`output`?S.write(n.data):n.type===`exit`?(_=!0,S.writeln(``),S.writeln(`\x1b[33m[process exited with code ${n.exitCode??`unknown`}]\x1b[0m`),i(e.id)):n.type===`error`&&S.writeln(`\x1b[31m${n.message}\x1b[0m`)}catch{}}),T.addEventListener(`error`,()=>{b(h(o?`terminalConnectionClosedUnexpectedly`:`terminalConnectionFailed`))}),T.addEventListener(`close`,e=>{m.current?.dispose(),m.current=null,!(n||_)&&(!e.wasClean||e.code!==1e3)&&b(h(o?`terminalConnectionClosedUnexpectedly`:`terminalConnectionFailed`))});let E=new ResizeObserver(()=>w());E.observe(t),v.current=E;let D=()=>{let e=d();S.options.fontSize=e.fontSize,S.options.lineHeight=e.lineHeight,window.setTimeout(w,0)};return window.addEventListener(u,D),window.setTimeout(w,50),()=>{n=!0,window.removeEventListener(u,D),E.disconnect(),v.current=null,m.current?.dispose(),m.current=null,T.close(),p.current=null,S.dispose(),l.current=null,f.current=null}},[o,a,i,r,e.cwd,e.id,s]),(0,_.useEffect)(()=>{if(!t)return;let e=f.current,n=l.current;window.setTimeout(()=>{try{e?.fit(),n?.focus()}catch{}},0)},[t,n]),(0,E.jsx)(`div`,{className:t?`h-full min-h-0 w-full pl-2 md:pl-3`:`hidden`,"aria-hidden":!t,children:(0,E.jsx)(`div`,{ref:c,className:`h-full min-h-0 w-full`})})}var re=180,ie=.7,ae=320;function O(e,t){let n=t?t.name:`Terminal`,r=new Set(e.map(e=>e.name));if(n!==`Terminal`&&!r.has(n))return n;let i=1;for(;r.has(`${n} ${i}`);)i+=1;return`${n} ${i}`}function k(e,t){let n=e?.terminalShellProfiles||[],r=t||e?.defaultTerminalShellProfileId||``;return n.find(e=>e.id===r)||n[0]}function A({project:e,onCollapse:o,pendingCommand:l,onPendingCommandHandled:u,variant:d=`dock`,singleSession:f=!1,panelInstanceId:ee,panelSessionId:g,onPanelSessionReady:v}){let[w,te]=(0,_.useState)(null),[T,D]=(0,_.useState)([]),[A,j]=(0,_.useState)(),[M,oe]=(0,_.useState)(ae),[N,se]=(0,_.useState)(!0),[P,ce]=(0,_.useState)(!1),[le,F]=(0,_.useState)(),[ue,I]=(0,_.useState)({}),[L,R]=(0,_.useState)(!1),[z,de]=(0,_.useState)(!1),B=(0,_.useRef)(!1),V=(0,_.useRef)(!1),H=(0,_.useRef)(new Set),fe=(0,_.useRef)(l),U=(0,_.useRef)(new Set),W=(0,_.useRef)(new Set),G=(0,_.useRef)(new Map),K=(0,_.useRef)(!0),pe=(0,_.useRef)(v),[me,he]=(0,_.useState)(()=>new Set),q=(0,_.useRef)(null),ge=(0,_.useRef)(null),J=e?.id,Y=d===`panel`&&!!ee,X=(0,_.useMemo)(()=>T.find(e=>e.id===A)??T[0],[A,T]);(0,_.useEffect)(()=>{fe.current=l},[l]),(0,_.useEffect)(()=>{pe.current=v},[v]),(0,_.useEffect)(()=>()=>{K.current=!1},[]);let _e=(0,_.useCallback)(async()=>{let e=await b(J);return D(e.sessions),j(t=>t&&e.sessions.some(e=>e.id===t)?t:e.sessions[0]?.id),e.sessions},[J]),ve=(0,_.useCallback)(async(e,t)=>{if(B.current)return;let n=k(w,t);B.current=!0,ce(!0),F(void 0),I({});try{let t=await x({projectId:J,name:O(e,n),cols:120,rows:30,shellProfileId:n?.id,shellProfileName:n?.name});D(e=>[...e,t]),j(t.id)}catch(e){F(e instanceof Error?e.message:h(`terminalCreateFailed`))}finally{B.current=!1,ce(!1)}},[w,J]);(0,_.useEffect)(()=>{let e=!1;return(async()=>{se(!0),F(void 0);try{let[t,n]=await Promise.all([y(),b(J)]);if(e)return;if(te(t),t.enabled&&Y&&g&&n.sessions.some(e=>e.id===g)){V.current=!0,D(n.sessions),j(g);return}if(t.enabled&&Y&&!V.current){V.current=!0;let r=k(t);try{let t=await x({projectId:J,name:O(n.sessions,r),cols:120,rows:30,shellProfileId:r?.id,shellProfileName:r?.name});if(e){S(t.id).catch(()=>{});return}D([...n.sessions,t]),j(t.id),pe.current?.(t.id);return}catch(t){e||F(t instanceof Error?t.message:h(`terminalCreateFailed`))}}if(D(n.sessions),j(n.sessions[0]?.id),t.enabled&&n.sessions.length===0&&!fe.current){let n=k(t);x({projectId:J,name:O([],n),cols:120,rows:30,shellProfileId:n?.id,shellProfileName:n?.name}).then(t=>{if(e){S(t.id).catch(()=>{});return}D([t]),j(t.id)}).catch(t=>{e||F(t instanceof Error?t.message:h(`terminalCreateFailed`))})}}catch(t){e||F(t instanceof Error?t.message:h(`terminalUnavailable`))}finally{e||se(!1)}})(),()=>{e=!0}},[Y,g,J]),(0,_.useEffect)(()=>{if(!L)return;let e=e=>{ge.current?.contains(e.target)||R(!1)},t=e=>{e.key===`Escape`&&R(!1)};return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[L]),(0,_.useEffect)(()=>{if(!z)return;let e=e=>{e.key===`Escape`&&de(!1)};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[z]),(0,_.useEffect)(()=>{if(!l||H.current.has(l.id)||G.current.has(l.id)||U.current.has(l.id)||N||P||!w)return;if(!w.enabled){H.current.add(l.id),window.setTimeout(()=>{F(w.reason||h(`terminalUnavailable`)),u?.(l.id)},0);return}let e=X&&!X.exited?X:T.find(e=>!e.exited);if(e){G.current.set(l.id,e.id),window.setTimeout(()=>{K.current&&j(e.id)},0);return}U.current.add(l.id),window.setTimeout(()=>{K.current&&F(void 0)},0);let t=k(w);x({projectId:J,name:O(T,t),cols:120,rows:30,shellProfileId:t?.id,shellProfileName:t?.name}).then(e=>{if(!K.current){S(e.id).catch(()=>{});return}G.current.set(l.id,e.id),D(t=>t.some(t=>t.id===e.id)?t:[...t,e]),j(e.id)}).catch(e=>{K.current&&(F(e instanceof Error?e.message:h(`terminalCommandExecuteFailed`)),H.current.add(l.id),u?.(l.id))}).finally(()=>{U.current.delete(l.id)})},[X,w,P,N,u,l,J,T]),(0,_.useEffect)(()=>{if(!l||H.current.has(l.id)||W.current.has(l.id))return;let e=G.current.get(l.id),t=e?T.find(t=>t.id===e):X&&!X.exited?X:T.find(e=>!e.exited);!t||t.exited||!me.has(t.id)||(W.current.add(l.id),window.setTimeout(()=>{K.current&&(j(t.id),F(void 0))},0),(async()=>{try{if(l.execute){let e=l.command.split(`
2
- `),n=e.flatMap((t,n)=>n<e.length-1?[t,`\r`]:[t]);n.push(`\r`),await C(t.id,n.join(``))}else await C(t.id,l.command)}catch(e){K.current&&F(e instanceof Error?e.message:h(`terminalCommandExecuteFailed`))}finally{H.current.add(l.id),W.current.delete(l.id),G.current.delete(l.id),K.current&&u?.(l.id)}})())},[X,u,l,me,T]);let ye=async e=>{F(void 0),I(t=>{if(!t[e])return t;let n={...t};return delete n[e],n});let t=T.filter(t=>t.id!==e);D(t),A===e&&j(t[0]?.id);try{await S(e)}catch(e){F(e instanceof Error?e.message:h(`terminalCloseFailed`)),_e().catch(()=>{})}},be=(0,_.useCallback)(e=>{D(t=>t.map(t=>t.id===e?{...t,exited:!0}:t)),he(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},[]),xe=(0,_.useCallback)(e=>{he(t=>{if(t.has(e))return t;let n=new Set(t);return n.add(e),n})},[]),Se=(0,_.useCallback)((e,t)=>{I(n=>{if(!t){if(!n[e])return n;let t={...n};return delete t[e],t}return n[e]===t?n:{...n,[e]:t}})},[]),Ce=e=>{q.current={startY:e.clientY,startHeight:M},e.currentTarget.setPointerCapture(e.pointerId)},we=e=>{let t=q.current;if(!t)return;let n=Math.max(re,Math.floor(window.innerHeight*ie));oe(Math.min(n,Math.max(re,t.startHeight+t.startY-e.clientY)))},Te=e=>{q.current=null;try{e.currentTarget.releasePointerCapture(e.pointerId)}catch{}},Z=w?.terminalShellProfiles||[],Ee=w?.defaultTerminalShellProfileId||``,De=Z.find(e=>e.id===Ee)||Z[0],Oe=!!(w&&T.length>=w.maxSessions),ke=P||Oe,Ae=X?ue[X.id]:void 0,je=Y&&X?[X]:T,Q=le??Ae,$=d===`panel`,Me=$&&f,Ne=$?void 0:z?Q?`calc(100% - 4.25rem)`:`calc(100% - 2.25rem)`:Q?M-72:M-45;return(0,E.jsxs)(`div`,{className:m($?`flex min-h-0 flex-1 flex-col bg-background`:`shrink-0 border-t border-border bg-background`,z&&`quickforge-terminal-fullscreen z-40 flex flex-col border-t-0`),style:z||$?void 0:{height:M},children:[!z&&!$?(0,E.jsx)(`div`,{className:`h-1 cursor-row-resize bg-transparent hover:bg-border`,onPointerDown:Ce,onPointerMove:we,onPointerUp:Te,onPointerCancel:Te}):null,(0,E.jsxs)(`div`,{className:`flex h-9 items-center gap-1 border-b border-border px-2`,children:[(0,E.jsx)(s,{className:`size-4 shrink-0 text-muted-foreground/60`}),(0,E.jsx)(`div`,{className:`flex min-w-0 flex-1 items-center gap-1 overflow-x-auto`,children:je.map(e=>{let t=m(`flex max-w-44 shrink-0 items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground/72`,X?.id===e.id&&`bg-muted/28 text-foreground/90`);return Me?(0,E.jsxs)(`div`,{className:t,title:`${e.name} — ${e.cwd}`,children:[(0,E.jsx)(`span`,{className:m(`size-1.5 rounded-full`,e.exited?`bg-muted-foreground/40`:`bg-emerald-500/80`)}),(0,E.jsx)(`span`,{className:`truncate`,children:e.name})]},e.id):(0,E.jsxs)(`button`,{type:`button`,className:m(t,`hover:bg-muted/20 hover:text-foreground/85`),onClick:()=>j(e.id),title:`${e.name} — ${e.cwd}`,children:[(0,E.jsx)(`span`,{className:m(`size-1.5 rounded-full`,e.exited?`bg-muted-foreground/40`:`bg-emerald-500/80`)}),(0,E.jsx)(`span`,{className:`truncate`,children:e.name}),(0,E.jsx)(`span`,{role:`button`,tabIndex:0,className:`ml-1 rounded-sm p-0.5 opacity-60 hover:bg-background hover:opacity-100`,onClick:t=>{t.stopPropagation(),ye(e.id)},onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),t.stopPropagation(),ye(e.id))},"aria-label":h(`terminalCloseSession`,{name:e.name}),children:(0,E.jsx)(c,{className:`size-3`})})]},e.id)})}),Me?null:(0,E.jsxs)(`div`,{className:`relative shrink-0`,ref:ge,children:[(0,E.jsxs)(`div`,{className:`flex items-center overflow-hidden rounded-md border border-border bg-background`,children:[(0,E.jsx)(`button`,{type:`button`,className:`inline-flex h-7 w-7 items-center justify-center text-foreground/85 transition-colors hover:bg-muted/20 disabled:pointer-events-none disabled:opacity-50`,onClick:()=>void ve(T),disabled:ke,title:De?h(`terminalNewWithProfile`,{name:De.name}):h(`terminalNew`),"aria-label":h(`terminalNew`),children:P?(0,E.jsx)(n,{className:`size-3.5 animate-spin`}):(0,E.jsx)(r,{className:`size-3.5`})}),Z.length>0?(0,E.jsx)(`button`,{type:`button`,className:`inline-flex h-7 w-7 items-center justify-center border-l border-border text-muted-foreground/72 transition-colors hover:bg-muted/20 hover:text-foreground/85 disabled:pointer-events-none disabled:opacity-50`,onClick:()=>R(e=>!e),disabled:ke,title:h(`terminalSelectShell`),"aria-label":h(`terminalSelectShell`),"aria-expanded":L,children:(0,E.jsx)(t,{className:`size-3.5`})}):null]}),L?(0,E.jsxs)(`div`,{className:m(`absolute right-0 z-30 w-64 overflow-hidden rounded-lg border border-border bg-background p-1.5 shadow-[0_16px_38px_-22px_rgb(15_23_42_/_0.65)]`,$?`top-9`:`bottom-9`),children:[(0,E.jsx)(`div`,{className:`px-2 pb-1.5 pt-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/60`,children:h(`terminalNewWith`)}),Z.map(e=>(0,E.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs text-muted-foreground/80 hover:bg-muted/20 hover:text-foreground/90`,onClick:()=>{R(!1),ve(T,e.id)},children:[(0,E.jsx)(`span`,{className:`inline-flex size-5 shrink-0 items-center justify-center rounded bg-muted/20 text-[10px] text-muted-foreground/70`,children:e.name.slice(0,1).toUpperCase()}),(0,E.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,E.jsx)(`span`,{className:`block truncate font-medium`,children:e.name}),(0,E.jsx)(`span`,{className:`block truncate font-mono text-[11px] text-muted-foreground/55`,children:e.command})]})]},e.id))]}):null]}),Me?null:(0,E.jsx)(p,{variant:`ghost`,size:`icon`,className:`size-7`,onClick:()=>de(e=>!e),title:h(z?`terminalExitFullscreen`:`terminalFullscreen`),"aria-label":h(z?`terminalExitFullscreen`:`terminalFullscreen`),children:z?(0,E.jsx)(i,{className:`size-3.5`}):(0,E.jsx)(a,{className:`size-3.5`})}),(0,E.jsx)(p,{variant:`ghost`,size:`icon`,className:m(`size-7`,$&&`hidden`),onClick:o,title:h(`terminalCollapse`),"aria-label":h(`terminalCollapse`),children:(0,E.jsx)(t,{className:`size-3.5`})})]}),Q?(0,E.jsx)(`div`,{className:`border-b border-border px-3 py-1.5 text-xs text-destructive`,children:Q}):null,(0,E.jsx)(`div`,{className:m(`min-h-0 bg-background`,$&&`flex-1`),style:Ne===void 0?void 0:{height:Ne},children:N?(0,E.jsxs)(`div`,{className:`flex h-full items-center justify-center gap-2 text-xs text-muted-foreground/60`,children:[(0,E.jsx)(n,{className:`size-4 animate-spin`}),` `,h(`terminalStarting`)]}):w&&!w.enabled?(0,E.jsx)(`div`,{className:`flex h-full items-center justify-center px-4 text-center text-xs text-muted-foreground/60`,children:w.reason||h(`terminalUnavailable`)}):T.length===0?(0,E.jsx)(`div`,{className:`flex h-full items-center justify-center text-xs text-muted-foreground/60`,children:h(`terminalNoSessions`)}):T.map(e=>(0,E.jsx)(ne,{session:e,active:e.id===X?.id,height:z?window.innerHeight-36:$?0:M,onReady:xe,onExited:be,onConnectionError:Se},e.id))})]})}export{A as TerminalDock,T as t};