@ian2018cs/agenthub 0.1.84 → 0.1.86
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.
|
@@ -151,7 +151,7 @@ ${ue}`:ue:je.push({type:"assistant",content:ue,timestamp:new Date,isStreaming:!0
|
|
|
151
151
|
.xterm-screen:focus {
|
|
152
152
|
outline: none !important;
|
|
153
153
|
}
|
|
154
|
-
`;if(typeof document<"u"){const r=document.createElement("style");r.type="text/css",r.innerText=Nc,document.head.appendChild(r)}function Tc({selectedProject:r,selectedSession:o,initialCommand:c,isPlainShell:u=!1,onProcessComplete:l,minimal:m=!1,autoConnect:d=!1}){const s=n.useRef(null),p=n.useRef(null),t=n.useRef(null),x=n.useRef(null),[h,a]=n.useState(!1),[i,y]=n.useState(!1),[j,w]=n.useState(!1),[b,k]=n.useState(null),[f,N]=n.useState(!1),S=n.useRef(r),I=n.useRef(o),D=n.useRef(c),T=n.useRef(u),R=n.useRef(l);n.useEffect(()=>{S.current=r,I.current=o,D.current=c,T.current=u,R.current=l});const M=n.useCallback(async()=>{if(!(f||h))try{const ne=localStorage.getItem("auth-token");if(!ne){console.error("No authentication token found for Shell WebSocket connection");return}const ie=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/shell?token=${encodeURIComponent(ne)}`;x.current=new WebSocket(ie),x.current.onopen=()=>{a(!0),N(!1),setTimeout(()=>{t.current&&p.current&&(t.current.fit(),x.current.send(JSON.stringify({type:"init",projectPath:S.current.fullPath||S.current.path,sessionId:T.current?null:I.current?.id,hasSession:T.current?!1:!!I.current,provider:T.current?"plain-shell":I.current?.__provider||"claude",cols:p.current.cols,rows:p.current.rows,initialCommand:D.current,isPlainShell:T.current})))},100)},x.current.onmessage=le=>{try{const xe=JSON.parse(le.data);if(xe.type==="output"){let Ce=xe.data;if(T.current&&R.current){const be=Ce.replace(/\x1b\[[0-9;]*m/g,"");if(be.includes("Process exited with code 0"))R.current(0);else if(be.match(/Process exited with code (\d+)/)){const Se=parseInt(be.match(/Process exited with code (\d+)/)[1]);Se!==0&&R.current(Se)}}p.current&&p.current.write(Ce)}else xe.type==="url_open"&&window.open(xe.url,"_blank")}catch(xe){console.error("[Shell] Error handling WebSocket message:",xe,le.data)}},x.current.onclose=le=>{a(!1),N(!1),p.current&&(p.current.clear(),p.current.write("\x1B[2J\x1B[H"))},x.current.onerror=le=>{a(!1),N(!1)}}catch{a(!1),N(!1)}},[f,h]),E=n.useCallback(()=>{!i||h||f||(N(!0),M())},[i,h,f,M]),W=n.useCallback(()=>{x.current&&(x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"terminate"})),x.current.close(),x.current=null),p.current&&(p.current.clear(),p.current.write("\x1B[2J\x1B[H")),a(!1),N(!1)},[]),X=n.useMemo(()=>o?o.summary||"New Session":null,[o]),C=n.useMemo(()=>X?X.slice(0,30):null,[X]),$=n.useMemo(()=>X?X.slice(0,50):null,[X]),te=()=>{w(!0),x.current&&(x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"terminate"})),x.current.close(),x.current=null),p.current&&(p.current.dispose(),p.current=null,t.current=null),a(!1),y(!1),setTimeout(()=>{w(!1)},200)};return n.useEffect(()=>{const ne=o?.id||null;b!==null&&b!==ne&&i&&W(),k(ne)},[o?.id,i,W]),n.useEffect(()=>{if(!s.current||!r||j||p.current)return;p.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff",extendedAnsi:["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"]}}),t.current=new Vn.FitAddon;const ne=new Zn.WebglAddon,G=new Qn.WebLinksAddon;p.current.loadAddon(t.current),p.current.loadAddon(G);try{p.current.loadAddon(ne)}catch{console.warn("[Shell] WebGL renderer unavailable, using Canvas fallback")}p.current.open(s.current),p.current.attachCustomKeyEventHandler(le=>(le.ctrlKey||le.metaKey)&&le.key==="c"&&p.current.hasSelection()?(document.execCommand("copy"),!1):(le.ctrlKey||le.metaKey)&&le.key==="v"?(navigator.clipboard.readText().then(xe=>{x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"input",data:xe}))}).catch(()=>{}),!1):!0),setTimeout(()=>{t.current&&(t.current.fit(),p.current&&x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"resize",cols:p.current.cols,rows:p.current.rows})))},100),y(!0),p.current.onData(le=>{x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"input",data:le}))});const ie=new ResizeObserver(()=>{t.current&&p.current&&setTimeout(()=>{t.current.fit(),x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"resize",cols:p.current.cols,rows:p.current.rows}))},50)});return s.current&&ie.observe(s.current),()=>{ie.disconnect(),x.current&&(x.current.readyState===WebSocket.OPEN||x.current.readyState===WebSocket.CONNECTING)&&x.current.close(),x.current=null,p.current&&(p.current.dispose(),p.current=null)}},[r?.path||r?.fullPath,j]),n.useEffect(()=>{!d||!i||f||h||E()},[d,i,f,h,E]),r?m?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:s,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${h?"bg-green-500":"bg-red-500"}`}),o&&e.jsxs("span",{className:"text-xs text-blue-300",children:["(",C,"...)"]}),!o&&e.jsx("span",{className:"text-xs text-gray-400",children:"(新会话)"}),!i&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),j&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[h&&e.jsxs("button",{onClick:W,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Shell 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:te,disabled:j||h,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Shell(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:s,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),i&&!h&&!f&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:E,className:"px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",title:"Connect to shell",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"在 Shell 中继续"})]}),e.jsx("p",{className:"text-gray-400 text-sm mt-3 px-2",children:u?`Run ${c||"command"} in ${r.displayName}`:o?`Resume session: ${$}...`:"Start a new Claude session"})]})}),f&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Shell..."})]}),e.jsx("p",{className:"text-gray-400 text-sm mt-3 px-2",children:u?`Running ${c||"command"} in ${r.displayName}`:`Starting Claude CLI in ${r.displayName}`})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开交互式 Shell"})]})})}function Sc({project:r,session:o=null,command:c=null,isPlainShell:u=null,autoConnect:l=!0,onComplete:m=null,onClose:d=null,title:s=null,className:p="",showHeader:t=!0,compact:x=!1,minimal:h=!1}){const[a,i]=n.useState(!1),y=u!==null?u:c!==null,j=n.useCallback(w=>{i(!0),m&&m(w)},[m]);return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${p}`,children:[!h&&t&&s&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:s}),a&&e.jsx("span",{className:"text-xs text-green-400",children:"(已完成)"})]}),d&&e.jsx("button",{onClick:d,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Tc,{selectedProject:r,selectedSession:o,initialCommand:c,isPlainShell:y,onProcessComplete:j,minimal:h,autoConnect:h?!0:l})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${p}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Shell 需要一个项目"})]})})}function Xc({selectedProject:r,minimal:o=!1,autoConnect:c=!1}){const u=n.useRef(null),l=n.useRef(null),m=n.useRef(null),d=n.useRef(null),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),j=n.useRef(r);n.useEffect(()=>{j.current=r});const w=n.useCallback(async()=>{if(!(i||s))try{const N=localStorage.getItem("auth-token");if(!N){console.error("No authentication token found for Codex WebSocket connection");return}const I=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/codex?token=${encodeURIComponent(N)}`;d.current=new WebSocket(I),d.current.onopen=()=>{p(!0),y(!1),setTimeout(()=>{m.current&&l.current&&(m.current.fit(),d.current.send(JSON.stringify({type:"init",projectPath:j.current.fullPath||j.current.path,cols:l.current.cols,rows:l.current.rows})))},100)},d.current.onmessage=D=>{try{const T=JSON.parse(D.data);T.type==="output"?l.current&&l.current.write(T.data):T.type==="url_open"&&window.open(T.url,"_blank")}catch(T){console.error("[CodexShell] Error handling WebSocket message:",T)}},d.current.onclose=()=>{p(!1),y(!1),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H"))},d.current.onerror=()=>{p(!1),y(!1)}}catch{p(!1),y(!1)}},[i,s]),b=n.useCallback(()=>{!t||s||i||(y(!0),w())},[t,s,i,w]),k=n.useCallback(()=>{d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H")),p(!1),y(!1)},[]),f=()=>{a(!0),d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.dispose(),l.current=null,m.current=null),p(!1),x(!1),setTimeout(()=>a(!1),200)};return n.useEffect(()=>{if(!u.current||!r||h||l.current)return;l.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff"}}),m.current=new Vn.FitAddon;const N=new Zn.WebglAddon,S=new Qn.WebLinksAddon;l.current.loadAddon(m.current),l.current.loadAddon(S);try{l.current.loadAddon(N)}catch{console.warn("[CodexShell] WebGL renderer unavailable, using Canvas fallback")}l.current.open(u.current),l.current.attachCustomKeyEventHandler(D=>(D.ctrlKey||D.metaKey)&&D.key==="c"&&l.current.hasSelection()?(document.execCommand("copy"),!1):(D.ctrlKey||D.metaKey)&&D.key==="v"?(navigator.clipboard.readText().then(T=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:T}))}).catch(()=>{}),!1):!0),setTimeout(()=>{m.current&&(m.current.fit(),l.current&&d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows})))},100),x(!0),l.current.onData(D=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:D}))});const I=new ResizeObserver(()=>{m.current&&l.current&&setTimeout(()=>{m.current.fit(),d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows}))},50)});return u.current&&I.observe(u.current),()=>{I.disconnect(),d.current&&(d.current.readyState===WebSocket.OPEN||d.current.readyState===WebSocket.CONNECTING)&&d.current.close(),d.current=null,l.current&&(l.current.dispose(),l.current=null)}},[r?.path||r?.fullPath,h]),n.useEffect(()=>{!c||!t||i||s||b()},[c,t,i,s,b]),r?o?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${s?"bg-green-500":"bg-red-500"}`}),e.jsx("span",{className:"text-xs text-gray-300 font-medium",children:"Codex"}),!t&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),h&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[s&&e.jsxs("button",{onClick:k,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Codex 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:f,disabled:h||s,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Codex(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!t&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),t&&!s&&!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:b,className:"px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"启动 Codex"})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["在 ",r.displayName," 中启动 Codex CLI"]})]})}),i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Codex..."})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["正在 ",r.displayName," 中启动 Codex CLI"]})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开 Codex"})]})})}function Mc({project:r,autoConnect:o=!0,onClose:c=null,className:u="",showHeader:l=!0,minimal:m=!1}){return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${u}`,children:[!m&&l&&c&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:"Codex"}),e.jsx("button",{onClick:c,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Xc,{selectedProject:r,minimal:m,autoConnect:m?!0:o})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${u}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Codex 需要一个项目"})]})})}function Oc({selectedProject:r,minimal:o=!1,autoConnect:c=!1}){const u=n.useRef(null),l=n.useRef(null),m=n.useRef(null),d=n.useRef(null),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),j=n.useRef(r);n.useEffect(()=>{j.current=r});const w=n.useCallback(async()=>{if(!(i||s))try{const N=localStorage.getItem("auth-token");if(!N){console.error("No authentication token found for Gemini WebSocket connection");return}const I=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/gemini?token=${encodeURIComponent(N)}`;d.current=new WebSocket(I),d.current.onopen=()=>{p(!0),y(!1),setTimeout(()=>{m.current&&l.current&&(m.current.fit(),d.current.send(JSON.stringify({type:"init",projectPath:j.current.fullPath||j.current.path,cols:l.current.cols,rows:l.current.rows})))},100)},d.current.onmessage=D=>{try{const T=JSON.parse(D.data);T.type==="output"?l.current&&l.current.write(T.data):T.type==="url_open"&&window.open(T.url,"_blank")}catch(T){console.error("[GeminiShell] Error handling WebSocket message:",T)}},d.current.onclose=()=>{p(!1),y(!1),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H"))},d.current.onerror=()=>{p(!1),y(!1)}}catch{p(!1),y(!1)}},[i,s]),b=n.useCallback(()=>{!t||s||i||(y(!0),w())},[t,s,i,w]),k=n.useCallback(()=>{d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H")),p(!1),y(!1)},[]),f=()=>{a(!0),d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.dispose(),l.current=null,m.current=null),p(!1),x(!1),setTimeout(()=>a(!1),200)};return n.useEffect(()=>{if(!u.current||!r||h||l.current)return;l.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff"}}),m.current=new Vn.FitAddon;const N=new Zn.WebglAddon,S=new Qn.WebLinksAddon;l.current.loadAddon(m.current),l.current.loadAddon(S);try{l.current.loadAddon(N)}catch{console.warn("[GeminiShell] WebGL renderer unavailable, using Canvas fallback")}l.current.open(u.current),l.current.attachCustomKeyEventHandler(D=>(D.ctrlKey||D.metaKey)&&D.key==="c"&&l.current.hasSelection()?(document.execCommand("copy"),!1):(D.ctrlKey||D.metaKey)&&D.key==="v"?(navigator.clipboard.readText().then(T=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:T}))}).catch(()=>{}),!1):!0),setTimeout(()=>{m.current&&(m.current.fit(),l.current&&d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows})))},100),x(!0),l.current.onData(D=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:D}))});const I=new ResizeObserver(()=>{m.current&&l.current&&setTimeout(()=>{m.current.fit(),d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows}))},50)});return u.current&&I.observe(u.current),()=>{I.disconnect(),d.current&&(d.current.readyState===WebSocket.OPEN||d.current.readyState===WebSocket.CONNECTING)&&d.current.close(),d.current=null,l.current&&(l.current.dispose(),l.current=null)}},[r?.path||r?.fullPath,h]),n.useEffect(()=>{!c||!t||i||s||b()},[c,t,i,s,b]),r?o?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${s?"bg-green-500":"bg-red-500"}`}),e.jsx("span",{className:"text-xs text-gray-300 font-medium",children:"Gemini"}),!t&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),h&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[s&&e.jsxs("button",{onClick:k,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Gemini 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:f,disabled:h||s,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Gemini(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!t&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),t&&!s&&!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:b,className:"px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"启动 Gemini"})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["在 ",r.displayName," 中启动 Gemini CLI"]})]})}),i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Gemini..."})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["正在 ",r.displayName," 中启动 Gemini CLI"]})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开 Gemini"})]})})}function Cc({project:r,autoConnect:o=!0,onClose:c=null,className:u="",showHeader:l=!0,minimal:m=!1}){return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${u}`,children:[!m&&l&&c&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:"Gemini"}),e.jsx("button",{onClick:c,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Oc,{selectedProject:r,minimal:m,autoConnect:m?!0:o})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${u}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Gemini 需要一个项目"})]})})}class Ec extends lt.Component{constructor(o){super(o),this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(o){return{hasError:!0}}componentDidCatch(o,c){console.error("ErrorBoundary caught an error:",o,c),this.setState({error:o,errorInfo:c})}render(){return this.state.hasError?e.jsx("div",{className:"flex flex-col items-center justify-center p-8 text-center",children:e.jsxs("div",{className:"bg-red-50 border border-red-200 rounded-lg p-6 max-w-md",children:[e.jsxs("div",{className:"flex items-center mb-4",children:[e.jsx("div",{className:"flex-shrink-0",children:e.jsx("svg",{className:"h-5 w-5 text-red-400",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z",clipRule:"evenodd"})})}),e.jsx("h3",{className:"ml-3 text-sm font-medium text-red-800",children:"出现问题"})]}),e.jsxs("div",{className:"text-sm text-red-700",children:[e.jsx("p",{className:"mb-2",children:"加载聊天界面时出现错误。"}),this.props.showDetails&&this.state.error&&e.jsxs("details",{className:"mt-4",children:[e.jsx("summary",{className:"cursor-pointer text-xs font-mono",children:"错误详情"}),e.jsxs("pre",{className:"mt-2 text-xs bg-red-100 p-2 rounded overflow-auto max-h-40",children:[this.state.error.toString(),this.state.errorInfo&&this.state.errorInfo.componentStack]})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx("button",{onClick:()=>{this.setState({hasError:!1,error:null,errorInfo:null}),this.props.onRetry&&this.props.onRetry()},className:"bg-red-600 text-white px-4 py-2 rounded text-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500",children:"重试"})})]})}):this.props.children}}const jr=({children:r,content:o,position:c="top",className:u="",delay:l=500})=>{const[m,d]=n.useState(!1),[s,p]=n.useState(null),t=()=>{const i=setTimeout(()=>{d(!0)},l);p(i)},x=()=>{s&&(clearTimeout(s),p(null)),d(!1)},h=()=>{switch(c){case"top":return"bottom-full left-1/2 transform -translate-x-1/2 mb-2";case"bottom":return"top-full left-1/2 transform -translate-x-1/2 mt-2";case"left":return"right-full top-1/2 transform -translate-y-1/2 mr-2";case"right":return"left-full top-1/2 transform -translate-y-1/2 ml-2";default:return"bottom-full left-1/2 transform -translate-x-1/2 mb-2"}},a=()=>{switch(c){case"top":return"top-full left-1/2 transform -translate-x-1/2 border-t-gray-900 dark:border-t-gray-100";case"bottom":return"bottom-full left-1/2 transform -translate-x-1/2 border-b-gray-900 dark:border-b-gray-100";case"left":return"left-full top-1/2 transform -translate-y-1/2 border-l-gray-900 dark:border-l-gray-100";case"right":return"right-full top-1/2 transform -translate-y-1/2 border-r-gray-900 dark:border-r-gray-100";default:return"top-full left-1/2 transform -translate-x-1/2 border-t-gray-900 dark:border-t-gray-100"}};return o?e.jsxs("div",{className:"relative inline-block",onMouseEnter:t,onMouseLeave:x,children:[r,m&&e.jsxs("div",{className:nt("absolute z-50 px-2 py-1 text-xs font-medium text-white bg-gray-900 dark:bg-gray-100 dark:text-gray-900 rounded shadow-lg whitespace-nowrap pointer-events-none","animate-in fade-in-0 zoom-in-95 duration-200",h(),u),children:[o,e.jsx("div",{className:nt("absolute w-0 h-0 border-4 border-transparent",a())})]})]}):r};function Dc(){const[r,o]=n.useState(null),[c,u]=n.useState([]),[l,m]=n.useState(!1),d=n.useRef(null),s=n.useRef(null),p=n.useRef(0),{token:t}=Xt();n.useEffect(()=>{d.current&&(clearTimeout(d.current),d.current=null),s.current&&(s.current.close(),s.current=null),t?(p.current=0,x()):(m(!1),o(null));const a=()=>{if(document.visibilityState==="visible"){const i=s.current?.readyState;(i===void 0||i===3||i===2)&&(d.current&&(clearTimeout(d.current),d.current=null),p.current=0,x())}};return document.addEventListener("visibilitychange",a),()=>{document.removeEventListener("visibilitychange",a),d.current&&clearTimeout(d.current),s.current&&s.current.close()}},[t]);const x=()=>{try{const a=t||localStorage.getItem("auth-token");if(!a){console.warn("No authentication token found for WebSocket connection");return}const y=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws?token=${encodeURIComponent(a)}`,j=new WebSocket(y);s.current=j,j.onopen=()=>{p.current=0,m(!0),o(j)},j.onmessage=w=>{try{const b=JSON.parse(w.data);u(k=>[...k,b])}catch(b){console.error("Error parsing WebSocket message:",b)}},j.onclose=()=>{if(m(!1),o(null),s.current=null,localStorage.getItem("auth-token")){const b=Math.min(1e3*Math.pow(2,p.current),15e3);p.current+=1,d.current=setTimeout(()=>{x()},b)}},j.onerror=w=>{console.error("WebSocket error:",w)}}catch(a){console.error("Error creating WebSocket connection:",a)}};return{ws:r,sendMessage:a=>{r&&l?r.send(JSON.stringify(a)):console.warn("WebSocket not connected")},messages:c,isConnected:l}}const ws=n.createContext({ws:null,sendMessage:()=>{},messages:[],isConnected:!1}),Ns=()=>{const r=n.useContext(ws);if(!r)throw new Error("useWebSocketContext must be used within a WebSocketProvider");return r},Pc=({children:r})=>{const o=Dc();return e.jsx(ws.Provider,{value:o,children:r})};function Ac({selectedProject:r,selectedSession:o,activeTab:c,setActiveTab:u,ws:l,sendMessage:m,messages:d,isMobile:s,isPWA:p,onMenuClick:t,isLoading:x,onInputFocusChange:h,onSessionActive:a,onSessionInactive:i,onSessionProcessing:y,onSessionNotProcessing:j,processingSessions:w,onReplaceTemporarySession:b,onNavigateToSession:k,onShowSettings:f,autoScrollToBottom:N,sendByCtrlEnter:S,externalMessageUpdate:I,limitStatus:D,onLimitBlocked:T,checkLimitStatus:R}){const{showConfirm:M}=it(),{hasPermission:E}=Xt(),{isConnected:W}=Ns(),[X,C]=n.useState(null),[$,te]=n.useState(null),[ne,G]=n.useState(600),[ie,le]=n.useState(!1),[xe,Ce]=n.useState(!1),be=n.useRef(null),Se=async ye=>{const Xe="previewTabAcknowledged";if(!localStorage.getItem(Xe)){const Ee=await M("此功能的对话记录不会显示在当前网页的会话列表中,与 Chat 是两套独立的系统,请注意区分。",{title:"预览功能提示",subtitle:ye==="codex"?"Codex":"Gemini CLI",variant:"warning",confirmText:"我知道了,继续",cancelText:"取消",checkboxLabel:"不再提醒"});if(!Ee?.confirmed)return;Ee.checked&&localStorage.setItem(Xe,"1")}u(ye)};n.useEffect(()=>{c==="shell"&&R&&R()},[c,R]);const Re=["png","jpg","jpeg","gif","svg","webp","ico","bmp"],se=(ye,Xe=null)=>{const Ee=ye.split(".").pop()?.toLowerCase();if(Re.includes(Ee)){te({name:ye.split("/").pop(),path:ye,projectName:r?.name,projectPath:r?.path});return}const Fe={name:ye.split("/").pop(),path:ye,projectName:r?.name,diffInfo:Xe};C(Fe)},we=()=>{C(null),Ce(!1)},$e=()=>{Ce(!xe)},We=ye=>{s||(le(!0),ye.preventDefault())};return n.useEffect(()=>{const ye=Ee=>{if(!ie)return;const Fe=be.current?.parentElement;if(!Fe)return;const Ne=Fe.getBoundingClientRect(),Be=Ne.right-Ee.clientX,Pe=300,Ae=Ne.width*.8;Be>=Pe&&Be<=Ae&&G(Be)},Xe=()=>{le(!1)};return ie&&(document.addEventListener("mousemove",ye),document.addEventListener("mouseup",Xe),document.body.style.cursor="col-resize",document.body.style.userSelect="none"),()=>{document.removeEventListener("mousemove",ye),document.removeEventListener("mouseup",Xe),document.body.style.cursor="",document.body.style.userSelect=""}},[ie]),x?e.jsxs("div",{className:"h-full flex flex-col",children:[s&&e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsx("button",{onClick:t,className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 pwa-menu-button",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-4",children:e.jsx("div",{className:"w-full h-full rounded-full border-4 border-gray-200 border-t-blue-500",style:{animation:"spin 1s linear infinite",WebkitAnimation:"spin 1s linear infinite",MozAnimation:"spin 1s linear infinite"}})}),e.jsxs("h2",{className:"text-xl font-semibold mb-2",children:["正在加载 ",et]}),e.jsx("p",{children:"正在设置您的工作区..."})]})})]}):r?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsxs("div",{className:"flex items-center justify-between relative",children:[e.jsxs("div",{className:"flex items-center space-x-2 min-w-0 flex-1",children:[s&&e.jsx("button",{onClick:t,onTouchStart:ye=>{ye.preventDefault(),t()},className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 touch-manipulation active:scale-95 pwa-menu-button flex-shrink-0",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})}),e.jsx("div",{className:"min-w-0 flex items-center gap-2 flex-1 overflow-x-auto scrollbar-hide",children:e.jsx("div",{className:"min-w-0 flex-1",children:c==="chat"&&o?e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white whitespace-nowrap overflow-x-auto scrollbar-hide",children:o.summary||"新会话"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName}),e.jsxs("span",{className:`inline-flex items-center gap-1 text-xs ${W?"text-green-600 dark:text-green-400":"text-red-500 dark:text-red-400 animate-pulse"}`,children:[W?e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.288 15.038a5.25 5.25 0 017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z"})}):e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.412 15.655L9.75 21.75l3.745-4.012M9.257 13.5H3.75l2.659-2.849m2.048-2.194L14.25 2.25 12 10.5h8.25l-4.707 5.043M6.53 9.345A3.778 3.778 0 0112 8.25c1.372 0 2.585.59 3.43 1.53M3 3l18 18"})}),e.jsx("span",{className:"hidden sm:inline",children:W?"连接正常":"连接异常"})]})]})]}):c==="chat"&&!o?e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white",children:"新会话"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName}),e.jsxs("span",{className:`inline-flex items-center gap-1 text-xs ${W?"text-green-600 dark:text-green-400":"text-red-500 dark:text-red-400 animate-pulse"}`,children:[W?e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.288 15.038a5.25 5.25 0 017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z"})}):e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.412 15.655L9.75 21.75l3.745-4.012M9.257 13.5H3.75l2.659-2.849m2.048-2.194L14.25 2.25 12 10.5h8.25l-4.707 5.043M6.53 9.345A3.778 3.778 0 0112 8.25c1.372 0 2.585.59 3.43 1.53M3 3l18 18"})}),e.jsx("span",{className:"hidden sm:inline",children:W?"连接正常":"连接异常"})]})]})]}):e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white",children:c==="files"?"项目文件":"项目"}),e.jsx("div",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName})]})})})]}),e.jsx("div",{className:"flex-shrink-0 hidden sm:block",children:e.jsxs("div",{className:"relative flex bg-gray-100 dark:bg-gray-800 rounded-lg p-1",children:[e.jsx(jr,{content:"Chat",position:"bottom",children:e.jsx("button",{onClick:()=>u("chat"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md ${c==="chat"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Chat"})]})})}),e.jsx(jr,{content:"Files",position:"bottom",children:e.jsx("button",{onClick:()=>u("files"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="files"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-5l-2-2H5a2 2 0 00-2 2z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Files"})]})})}),E("claude_shell")&&e.jsx(jr,{content:D&&!D.allowed?"使用已达上限":"Claude Code",position:"bottom",children:e.jsx("button",{onClick:()=>{if(D&&!D.allowed){T?.(D.reason);return}u("shell")},className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${D&&!D.allowed?"opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-500":c==="shell"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z",fill:"#D97757",fillRule:"nonzero"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Claude Code"})]})})}),E("codex_shell")&&e.jsx(jr,{content:"Codex",position:"bottom",children:e.jsx("button",{onClick:()=>Se("codex"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="codex"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"currentColor",fillRule:"evenodd",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Codex"})]})})}),E("gemini_shell")&&e.jsx(jr,{content:"Gemini CLI",position:"bottom",children:e.jsx("button",{onClick:()=>Se("gemini"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="gemini"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsxs("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"#3186FF"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-0)"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-1)"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-2)"}),e.jsxs("defs",{children:[e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-0",x1:"7",x2:"11",y1:"15.5",y2:"12",children:[e.jsx("stop",{stopColor:"#08B962"}),e.jsx("stop",{offset:"1",stopColor:"#08B962",stopOpacity:"0"})]}),e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-1",x1:"8",x2:"11.5",y1:"5.5",y2:"11",children:[e.jsx("stop",{stopColor:"#F94543"}),e.jsx("stop",{offset:"1",stopColor:"#F94543",stopOpacity:"0"})]}),e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-2",x1:"3.5",x2:"17.5",y1:"13.5",y2:"12",children:[e.jsx("stop",{stopColor:"#FABC12"}),e.jsx("stop",{offset:".46",stopColor:"#FABC12",stopOpacity:"0"})]})]})]}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Gemini CLI"})]})})})]})})]})}),e.jsxs("div",{className:"flex-1 flex min-h-0 overflow-hidden",children:[e.jsxs("div",{className:`flex-1 flex flex-col min-h-0 overflow-hidden ${X?"mr-0":""} ${xe?"hidden":""}`,children:[e.jsx("div",{className:`h-full ${c==="chat"?"block":"hidden"}`,children:e.jsx(Ec,{showDetails:!0,children:e.jsx(kc,{selectedProject:r,selectedSession:o,ws:l,sendMessage:m,messages:d,onFileOpen:se,onInputFocusChange:h,onSessionActive:a,onSessionInactive:i,onSessionProcessing:y,onSessionNotProcessing:j,processingSessions:w,onReplaceTemporarySession:b,onNavigateToSession:k,onShowSettings:f,autoScrollToBottom:N,sendByCtrlEnter:S,externalMessageUpdate:I,limitStatus:D,onLimitExceeded:T,checkLimitStatus:R})})}),c==="files"&&e.jsx("div",{className:"h-full overflow-hidden",children:e.jsx(wc,{selectedProject:r})}),c==="shell"&&e.jsxs("div",{className:"h-full w-full overflow-hidden relative",children:[e.jsx(Sc,{project:r,session:o,showHeader:!1}),D&&!D.allowed&&e.jsx("div",{className:"absolute inset-0 bg-black/60 z-50 flex items-center justify-center",children:e.jsxs("div",{className:"bg-card border border-border rounded-lg shadow-xl p-6 mx-4 max-w-md text-center",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-4 bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-6 h-6 text-red-600 dark:text-red-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})}),e.jsx("h3",{className:"text-lg font-semibold text-foreground mb-2",children:D.reason==="total_limit_exceeded"?"使用上限已达到":"今日使用上限已达到"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:D.reason==="total_limit_exceeded"?"您已达到使用上限,请联系管理员提升额度。":"您已达到今日使用上限,请明日再来或联系管理员提升额度。"}),e.jsx("button",{onClick:()=>u("chat"),className:"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",children:"返回 Chat"})]})})]}),c==="codex"&&e.jsx("div",{className:"h-full w-full overflow-hidden relative",children:e.jsx(Mc,{project:r,showHeader:!1})}),c==="gemini"&&e.jsx("div",{className:"h-full w-full overflow-hidden relative",children:e.jsx(Cc,{project:r,showHeader:!1})}),e.jsx("div",{className:`h-full overflow-hidden ${c==="preview"?"block":"hidden"}`})]}),X&&!s&&e.jsxs(e.Fragment,{children:[!xe&&e.jsx("div",{ref:be,onMouseDown:We,className:"flex-shrink-0 w-1 bg-gray-200 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 cursor-col-resize transition-colors relative group",title:"Drag to resize",children:e.jsx("div",{className:"absolute inset-y-0 left-1/2 -translate-x-1/2 w-1 bg-blue-500 dark:bg-blue-600 opacity-0 group-hover:opacity-100 transition-opacity"})}),e.jsx("div",{className:`flex-shrink-0 border-l border-gray-200 dark:border-gray-700 h-full overflow-hidden ${xe?"flex-1":""}`,style:xe?{}:{width:`${ne}px`},children:e.jsx($n,{file:X,onClose:we,projectPath:r?.path,isSidebar:!0,isExpanded:xe,onToggleExpand:$e})})]})]}),X&&s&&e.jsx($n,{file:X,onClose:we,projectPath:r?.path,isSidebar:!1}),$&&e.jsx(ks,{file:$,onClose:()=>te(null)})]}):e.jsxs("div",{className:"h-full flex flex-col",children:[s&&e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsx("button",{onClick:t,className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 pwa-menu-button",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400 max-w-md mx-auto px-6",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-6 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-5l-2-2H5a2 2 0 00-2 2z"})})}),e.jsx("h2",{className:"text-2xl font-semibold mb-3 text-gray-900 dark:text-white",children:"选择您的项目"}),e.jsxs("p",{className:"text-gray-600 dark:text-gray-300 mb-6 leading-relaxed",children:["从侧边栏选择一个项目,开始与 ",et," 进行交流。每个项目包含您的聊天会话和文件历史。"]}),e.jsx("div",{className:"bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4 border border-blue-200 dark:border-blue-800",children:e.jsxs("p",{className:"text-sm text-blue-700 dark:text-blue-300",children:["💡 ",e.jsx("strong",{children:"提示:"})," ",s?"点击上方菜单按钮访问项目":E("create_project")?"点击侧边栏中的文件夹图标创建新项目":"点击侧边栏中的「使用项目模板」按钮来创建项目"]})})]})})]})}const Lc=lt.memo(Ac);function Ic({activeTab:r,setActiveTab:o,isInputFocused:c}){const u=[{id:"chat",icon:Cr,onClick:()=>o("chat")},{id:"shell",icon:Fn,onClick:()=>o("shell")},{id:"files",icon:Qt,onClick:()=>o("files")}];return e.jsx("div",{className:`fixed bottom-0 left-0 right-0 bg-background border-t border-border z-50 ios-bottom-safe transform transition-transform duration-300 ease-in-out shadow-lg ${c?"translate-y-full":"translate-y-0"}`,children:e.jsx("div",{className:"flex items-center justify-around py-1",children:u.map(l=>{const m=l.icon,d=r===l.id;return e.jsxs("button",{onClick:l.onClick,onTouchStart:s=>{s.preventDefault(),l.onClick()},className:`flex items-center justify-center p-2 rounded-lg min-h-[40px] min-w-[40px] relative touch-manipulation ${d?"text-blue-600 dark:text-blue-400":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white"}`,"aria-label":l.id,children:[e.jsx(m,{className:"w-5 h-5"}),d&&e.jsx("div",{className:"absolute top-0 left-1/2 transform -translate-x-1/2 w-6 h-0.5 bg-blue-600 dark:bg-blue-400 rounded-full"})]},l.id)})})})}const Ts=n.createContext(),eo=()=>{const r=n.useContext(Ts);if(!r)throw new Error("useTheme must be used within a ThemeProvider");return r},_c=({children:r})=>{const[o,c]=n.useState(()=>{const m=localStorage.getItem("theme");return m?m==="dark":window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)").matches:!1});n.useEffect(()=>{if(o){document.documentElement.classList.add("dark"),localStorage.setItem("theme","dark");const m=document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');m&&m.setAttribute("content","black-translucent");const d=document.querySelector('meta[name="theme-color"]');d&&d.setAttribute("content","#0c1117")}else{document.documentElement.classList.remove("dark"),localStorage.setItem("theme","light");const m=document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');m&&m.setAttribute("content","default");const d=document.querySelector('meta[name="theme-color"]');d&&d.setAttribute("content","#ffffff")}},[o]),n.useEffect(()=>{if(!window.matchMedia)return;const m=window.matchMedia("(prefers-color-scheme: dark)"),d=s=>{localStorage.getItem("theme")||c(s.matches)};return m.addEventListener("change",d),()=>m.removeEventListener("change",d)},[]);const l={isDarkMode:o,toggleDarkMode:()=>{c(m=>!m)}};return e.jsx(Ts.Provider,{value:l,children:r})},zc=["Bash(git log:*)","Bash(git diff:*)","Bash(git status:*)","Write","Read","Edit","Glob","Grep","MultiEdit","Task","TodoWrite","TodoRead","WebFetch","WebSearch"];function Rc({skipPermissions:r,setSkipPermissions:o,allowedTools:c,setAllowedTools:u,disallowedTools:l,setDisallowedTools:m,newAllowedTool:d,setNewAllowedTool:s,newDisallowedTool:p,setNewDisallowedTool:t}){const x=y=>{y&&!c.includes(y)&&(u([...c,y]),s(""))},h=y=>{u(c.filter(j=>j!==y))},a=y=>{y&&!l.includes(y)&&(m([...l,y]),t(""))},i=y=>{m(l.filter(j=>j!==y))};return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"bg-sky-50 dark:bg-sky-900/20 border border-sky-200 dark:border-sky-800 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Qr,{className:"w-5 h-5 text-sky-500 flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm text-sky-800 dark:text-sky-200",children:[e.jsx("span",{className:"font-medium",children:"提示:"}),"此权限设置仅对 ",e.jsx("span",{className:"font-medium",children:"Chat(聊天)"})," 生效,对 ",e.jsx("span",{className:"font-medium",children:"Shell(终端)"})," 无效。Shell 是直接的系统终端,不受此权限控制。"]})]})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Wt,{className:"w-5 h-5 text-orange-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"权限设置"})]}),e.jsx("div",{className:"bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 rounded-lg p-4",children:e.jsxs("label",{className:"flex items-center gap-3",children:[e.jsx("input",{type:"checkbox",checked:r,onChange:y=>o(y.target.checked),className:"w-4 h-4 text-blue-600 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 rounded focus:ring-blue-500 focus:ring-2"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-orange-900 dark:text-orange-100",children:"跳过权限提示(请谨慎使用)"}),e.jsx("div",{className:"text-sm text-orange-700 dark:text-orange-300",children:"等同于 --dangerously-skip-permissions 标志"})]})]})})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Ft,{className:"w-5 h-5 text-green-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"允许的工具"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"自动允许而不提示权限的工具"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(at,{value:d,onChange:y=>s(y.target.value),placeholder:'e.g., "Bash(git log:*)" or "Write"',onKeyPress:y=>{y.key==="Enter"&&(y.preventDefault(),x(d))},className:"flex-1 h-10"}),e.jsxs(B,{onClick:()=>x(d),disabled:!d,size:"sm",className:"h-10 px-4",children:[e.jsx(_t,{className:"w-4 h-4 mr-2 sm:mr-0"}),e.jsx("span",{className:"sm:hidden",children:"添加"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:"快速添加常用工具:"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:zc.map(y=>e.jsx(B,{variant:"outline",size:"sm",onClick:()=>x(y),disabled:c.includes(y),className:"text-xs h-8",children:y},y))})]}),e.jsxs("div",{className:"space-y-2",children:[c.map(y=>e.jsxs("div",{className:"flex items-center justify-between bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3",children:[e.jsx("span",{className:"font-mono text-sm text-green-800 dark:text-green-200",children:y}),e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>h(y),className:"text-green-600 hover:text-green-700",children:e.jsx(Ue,{className:"w-4 h-4"})})]},y)),c.length===0&&e.jsx("div",{className:"text-center py-6 text-gray-500 dark:text-gray-400",children:"未配置允许的工具"})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Wt,{className:"w-5 h-5 text-red-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"阻止的工具"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"自动阻止而不提示权限的工具"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(at,{value:p,onChange:y=>t(y.target.value),placeholder:'e.g., "Bash(rm:*)"',onKeyPress:y=>{y.key==="Enter"&&(y.preventDefault(),a(p))},className:"flex-1 h-10"}),e.jsxs(B,{onClick:()=>a(p),disabled:!p,size:"sm",className:"h-10 px-4",children:[e.jsx(_t,{className:"w-4 h-4 mr-2 sm:mr-0"}),e.jsx("span",{className:"sm:hidden",children:"添加"})]})]}),e.jsxs("div",{className:"space-y-2",children:[l.map(y=>e.jsxs("div",{className:"flex items-center justify-between bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3",children:[e.jsx("span",{className:"font-mono text-sm text-red-800 dark:text-red-200",children:y}),e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>i(y),className:"text-red-600 hover:text-red-700",children:e.jsx(Ue,{className:"w-4 h-4"})})]},y)),l.length===0&&e.jsx("div",{className:"text-center py-6 text-gray-500 dark:text-gray-400",children:"未配置阻止的工具"})]})]}),e.jsxs("div",{className:"bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4",children:[e.jsx("h4",{className:"font-medium text-blue-900 dark:text-blue-100 mb-2",children:"工具模式示例:"}),e.jsxs("ul",{className:"text-sm text-blue-800 dark:text-blue-200 space-y-1",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(git log:*)"'})," - 允许所有 git log 命令"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(git diff:*)"'})," - 允许所有 git diff 命令"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Write"'})," - 允许所有 Write 工具使用"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(rm:*)"'})," - 阻止所有 rm 命令(危险)"]})]})]})]})}function $c({permissionMode:r,setPermissionMode:o}){return e.jsx("div",{className:"space-y-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Ft,{className:"w-5 h-5 text-green-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"权限模式"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"控制 Codex 如何处理文件修改和命令执行"}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="default"?"bg-gray-100 dark:bg-gray-800 border-gray-400 dark:border-gray-500":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("default"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="default",onChange:()=>o("default"),className:"mt-1 w-4 h-4 text-green-600"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-foreground",children:"默认"}),e.jsx("div",{className:"text-sm text-muted-foreground",children:"仅受信任的命令(ls、cat、grep、git status 等)会自动运行。其他命令将被跳过。可以写入工作区。"})]})]})}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="acceptEdits"?"bg-green-50 dark:bg-green-900/20 border-green-400 dark:border-green-600":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("acceptEdits"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="acceptEdits",onChange:()=>o("acceptEdits"),className:"mt-1 w-4 h-4 text-green-600"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-green-900 dark:text-green-100",children:"接受编辑"}),e.jsx("div",{className:"text-sm text-green-700 dark:text-green-300",children:"所有命令在工作区内自动运行。沙盒执行的完全自动模式。"})]})]})}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="bypassPermissions"?"bg-orange-50 dark:bg-orange-900/20 border-orange-400 dark:border-orange-600":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("bypassPermissions"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="bypassPermissions",onChange:()=>o("bypassPermissions"),className:"mt-1 w-4 h-4 text-orange-600"}),e.jsxs("div",{children:[e.jsxs("div",{className:"font-medium text-orange-900 dark:text-orange-100 flex items-center gap-2",children:["跳过权限",e.jsx(Wt,{className:"w-4 h-4"})]}),e.jsx("div",{className:"text-sm text-orange-700 dark:text-orange-300",children:"无限制的完全系统访问。所有命令自动运行,具有完全的磁盘和网络访问权限。请谨慎使用。"})]})]})}),e.jsxs("details",{className:"text-sm",children:[e.jsx("summary",{className:"cursor-pointer text-muted-foreground hover:text-foreground",children:"技术详情"}),e.jsxs("div",{className:"mt-2 p-3 bg-gray-50 dark:bg-gray-900/50 rounded-lg text-xs text-muted-foreground space-y-2",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Default:"})," sandboxMode=workspace-write, approvalPolicy=untrusted. Trusted commands: cat, cd, grep, head, ls, pwd, tail, git status/log/diff/show, find (without -exec), etc."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Accept Edits:"})," sandboxMode=workspace-write, approvalPolicy=never. All commands auto-execute within project directory."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Bypass Permissions:"})," sandboxMode=danger-full-access, approvalPolicy=never. Full system access, use only in trusted environments."]}),e.jsx("p",{className:"text-xs opacity-75",children:"您可以在聊天界面中使用模式按钮为每个会话覆盖此设置。"})]})]})]})})}function Wc({agent:r,...o}){return r==="claude"?e.jsx(Rc,{...o}):r==="codex"?e.jsx($c,{...o}):null}const Hc=r=>{switch(r){case"stdio":return e.jsx(Fn,{className:"w-4 h-4"});case"sse":return e.jsx(Or,{className:"w-4 h-4"});case"http":return e.jsx(lr,{className:"w-4 h-4"});default:return e.jsx(en,{className:"w-4 h-4"})}};function Fc({servers:r,onAdd:o,onEdit:c,onDelete:u,testResults:l,serverTools:m,onDiscoverRepo:d}){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(en,{className:"w-5 h-5 text-purple-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"MCP 服务器"})]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Model Context Protocol 服务器为 ",et," 提供额外的工具和数据源"]}),e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs(B,{onClick:o,className:"bg-purple-600 hover:bg-purple-700 text-white",size:"sm",children:[e.jsx(_t,{className:"w-4 h-4 mr-2"}),"添加 MCP 服务器"]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs(B,{onClick:d,variant:"outline",size:"sm",children:[e.jsx(tn,{className:"w-4 h-4 mr-2"}),"MCP 商店"]})})]}),e.jsxs("div",{className:"space-y-2",children:[r.map(s=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[Hc(s.type),e.jsx("span",{className:"font-medium text-foreground",children:s.name}),e.jsx(tt,{variant:"outline",className:"text-xs",children:s.type}),e.jsx(tt,{variant:"outline",className:"text-xs",title:s.scope==="local"&&s.projectPath?s.projectPath:void 0,children:s.scope==="local"?`local${s.projectPath?` · ${s.projectPath.split("/").filter(Boolean).pop()}`:""}`:s.scope==="user"?"user":s.scope})]}),e.jsxs("div",{className:"text-sm text-muted-foreground space-y-1",children:[s.type==="stdio"&&s.config?.command&&e.jsxs("div",{children:["命令:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.command})]}),(s.type==="sse"||s.type==="http")&&s.config?.url&&e.jsxs("div",{children:["URL:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.url})]}),s.config?.args&&s.config.args.length>0&&e.jsxs("div",{children:["参数:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.args.join(" ")})]})]}),l?.[s.id]&&e.jsx("div",{className:`mt-2 p-2 rounded text-xs ${l[s.id].success?"bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200":"bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200"}`,children:e.jsx("div",{className:"font-medium",children:l[s.id].message})}),m?.[s.id]&&m[s.id].tools?.length>0&&e.jsxs("div",{className:"mt-2 p-2 rounded text-xs bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200",children:[e.jsxs("div",{className:"font-medium",children:["工具(",m[s.id].tools.length,"):"]}),e.jsxs("div",{className:"flex flex-wrap gap-1 mt-1",children:[m[s.id].tools.slice(0,5).map((p,t)=>e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:p.name},t)),m[s.id].tools.length>5&&e.jsxs("span",{className:"text-xs opacity-75",children:["+",m[s.id].tools.length-5," 更多"]})]})]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-4",children:[e.jsx(B,{onClick:()=>c(s),variant:"ghost",size:"sm",className:"text-gray-600 hover:text-gray-700",title:"编辑服务器",children:e.jsx(On,{className:"w-4 h-4"})}),e.jsx(B,{onClick:()=>u(s.id,s.scope,s.projectPath),variant:"ghost",size:"sm",className:"text-red-600 hover:text-red-700",title:"删除服务器",children:e.jsx(xt,{className:"w-4 h-4"})})]})]})},s.id)),r.length===0&&e.jsx("div",{className:"text-center py-8 text-gray-500 dark:text-gray-400",children:"未配置 MCP 服务器"})]})]})}function Bc(r){return e.jsx(Fc,{...r})}const Uc=[{key:"ANTHROPIC_DEFAULT_OPUS_MODEL",label:"Opus 模型",placeholder:"例如: claude-opus-4-6",description:"覆盖 opus 别名使用的模型,Plan Mode 激活时也用于 opusplan"},{key:"ANTHROPIC_DEFAULT_SONNET_MODEL",label:"Sonnet 模型",placeholder:"例如: claude-sonnet-4-5-20250929",description:"覆盖 sonnet 别名使用的模型,Plan Mode 未激活时也用于 opusplan"},{key:"ANTHROPIC_DEFAULT_HAIKU_MODEL",label:"Haiku 模型",placeholder:"例如: claude-haiku-4-5-20251001",description:"覆盖 haiku 别名使用的模型,也用于后台功能"},{key:"CLAUDE_CODE_SUBAGENT_MODEL",label:"Subagent 模型",placeholder:"例如: claude-haiku-4-5-20251001",description:"覆盖子代理(subagents)使用的模型"}],Gc=n.forwardRef(function({onStatusChange:o},c){const[u,l]=n.useState({}),[m,d]=n.useState({}),[s,p]=n.useState(!0),[t,x]=n.useState(!1),[h,a]=n.useState(null),[i,y]=n.useState(null),j=JSON.stringify(u)!==JSON.stringify(m);n.useEffect(()=>{o?.({saving:t,hasChanges:j})},[t,j,o]),n.useEffect(()=>{w()},[]),n.useEffect(()=>{if(h){const f=setTimeout(()=>a(null),3e3);return()=>clearTimeout(f)}},[h]);const w=async()=>{try{p(!0),y(null);const f=await Y("/api/settings/models");if(f.ok){const N=await f.json();l(N.models||{}),d(N.models||{})}else{const N=await f.json();y(N.error||"加载模型配置失败")}}catch(f){y(f.message)}finally{p(!1)}},b=async()=>{try{x(!0),a(null);const f=await Y("/api/settings/models",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({models:u})});if(f.ok)return a("success"),d({...u}),!0;{const N=await f.json();return a("error"),y(N.error||"保存失败"),!1}}catch(f){return a("error"),y(f.message),!1}finally{x(!1)}},k=()=>{l({...m}),a(null)};return n.useImperativeHandle(c,()=>({save:b,reset:k,get hasChanges(){return j},get saving(){return t}}),[j,t,u,m]),s?e.jsxs("div",{className:"flex items-center justify-center py-12",children:[e.jsx("div",{className:"animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500"}),e.jsx("span",{className:"ml-3 text-sm text-muted-foreground",children:"加载模型配置..."})]}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-start gap-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3",children:[e.jsx(Qr,{className:"w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0"}),e.jsxs("div",{className:"text-sm text-blue-700 dark:text-blue-300",children:[e.jsxs("p",{children:["自定义模型 ID 来覆盖 ",et," 和 Claude Code 使用的默认模型。留空表示使用默认模型。"]}),e.jsx("p",{className:"mt-1 text-blue-600 dark:text-blue-400",children:"非 Claude 模型将按 Sonnet 定价计费,但统计中会记录实际模型 ID。"})]})]}),i&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3 text-sm text-red-600 dark:text-red-400",children:i}),h==="success"&&e.jsx("div",{className:"bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3 text-sm text-green-600 dark:text-green-400",children:"模型配置已保存"}),Uc.map(f=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"font-medium text-sm text-foreground",children:f.label}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:f.description})]}),e.jsx("input",{type:"text",value:u[f.key]||"",onChange:N=>l(S=>({...S,[f.key]:N.target.value})),placeholder:f.placeholder,className:"w-full text-sm bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-900 dark:text-gray-100 rounded-lg focus:ring-blue-500 focus:border-blue-500 px-3 py-2"}),e.jsx("p",{className:"text-xs text-muted-foreground font-mono",children:f.key})]})},f.key))]})});function Yc({onClose:r,onInstalled:o,onOpenRepoManager:c,projects:u=[]}){const{showAlert:l}=it(),[m,d]=n.useState([]),[s,p]=n.useState([]),[t,x]=n.useState(!0),[h,a]=n.useState(null),[i,y]=n.useState(""),[j,w]=n.useState("all"),[b,k]=n.useState(null),[f,N]=n.useState(null),[S,I]=n.useState("user"),[D,T]=n.useState("");n.useEffect(()=>{R()},[]);const R=async(C=!1)=>{try{x(!0),a(null),C&&await Y("/api/skills/repos/refresh",{method:"POST"});const[$,te]=await Promise.all([Y("/api/skills/available"),Y("/api/skills/repos")]);if($.ok){const ne=await $.json();d(ne.skills||[])}if(te.ok){const ne=await te.json();p(ne.repos||[])}}catch($){a($.message)}finally{x(!1)}},M=C=>{N(C),I("user"),T("")},E=()=>{N(null),I("user"),T("")},W=async()=>{const C=f;if(C){if(S==="local"&&!D){l("请选择要安装到的项目",{variant:"warning"});return}try{N(null),k(C.name);const $={skillPath:C.path};S==="local"&&D&&($.projectPath=D);const te=await Y(`/api/skills/install/${C.name}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify($)});if(te.ok)d(ne=>ne.map(G=>G.name===C.name?{...G,installed:!0}:G)),o?.();else{const ne=await te.json();l(ne.error||"安装技能失败",{variant:"error"})}}catch($){l($.message,{variant:"error"})}finally{k(null),I("user"),T("")}}},X=m.filter(C=>{if(i){const $=i.toLowerCase();if(!C.name.toLowerCase().includes($)&&!C.title?.toLowerCase().includes($)&&!C.description?.toLowerCase().includes($))return!1}return!(j!=="all"&&C.repository!==j)});return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-background rounded-xl shadow-xl w-full max-w-4xl max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-border",children:[e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:"Skills 管理"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(B,{variant:"ghost",size:"sm",onClick:()=>R(!0),disabled:t,children:[e.jsx(st,{className:`w-4 h-4 ${t?"animate-spin":""}`}),e.jsx("span",{className:"ml-1 hidden sm:inline",children:"刷新"})]}),e.jsxs(B,{variant:"ghost",size:"sm",onClick:c,children:[e.jsx(Ht,{className:"w-4 h-4"}),e.jsx("span",{className:"ml-1 hidden sm:inline",children:"仓库管理"})]}),e.jsx(B,{variant:"ghost",size:"icon",onClick:r,children:e.jsx(Ue,{className:"w-5 h-5"})})]})]}),e.jsx("div",{className:"px-4 pt-4 pb-2"}),e.jsxs("div",{className:"px-4 pb-4 flex flex-wrap gap-3",children:[e.jsx("div",{className:"flex-1 min-w-[200px]",children:e.jsxs("div",{className:"relative",children:[e.jsx(St,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(at,{type:"text",placeholder:"搜索技能名称或描述...",value:i,onChange:C=>y(C.target.value),className:"pl-10"})]})}),e.jsxs("select",{value:j,onChange:C=>w(C.target.value),className:"px-3 py-2 rounded-md border border-border bg-background text-foreground text-sm min-w-[120px]",children:[e.jsx("option",{value:"all",children:"全部"}),s.map(C=>e.jsxs("option",{value:`${C.owner}/${C.repo}`,children:[C.owner,"/",C.repo]},`${C.owner}/${C.repo}`))]})]}),e.jsxs("div",{className:"flex-1 overflow-auto px-4 pb-4",children:[h&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 text-red-800 dark:text-red-200 text-sm mb-4",children:h}),t?e.jsx("div",{className:"text-center py-8 text-muted-foreground",children:"加载中..."}):X.length===0?e.jsx("div",{className:"text-center py-8 text-muted-foreground",children:m.length===0?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"没有可用的技能"}),e.jsx("p",{className:"text-xs mt-2",children:"请先添加技能仓库"}),e.jsxs(B,{variant:"outline",size:"sm",className:"mt-4",onClick:c,children:[e.jsx(Ht,{className:"w-4 h-4 mr-2"}),"管理仓库"]})]}):e.jsx("p",{children:"没有找到匹配的技能"})}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:X.map(C=>{const $=b===C.name,te=f?.name===C.name;return e.jsx("div",{className:"border border-border rounded-lg p-4 hover:border-amber-500/50 transition-colors",children:e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"mb-2",children:[e.jsx("h4",{className:"font-medium text-foreground",children:C.title||C.name}),e.jsxs("div",{className:"flex items-center gap-1 mt-1",children:[e.jsxs("span",{className:"text-xs text-muted-foreground",children:["skills/",C.name]}),e.jsx(tt,{variant:"outline",className:"text-xs ml-2",children:C.repository})]})]}),C.description&&e.jsx("p",{className:"text-sm text-muted-foreground flex-1 line-clamp-3 mb-3",children:C.description}),te&&e.jsxs("div",{className:"mt-2 mb-3 p-3 rounded-lg bg-muted/50 border border-border text-sm",children:[e.jsx("p",{className:"font-medium text-foreground mb-2",children:"选择安装位置"}),e.jsxs("label",{className:"flex items-center gap-2 mb-1 cursor-pointer",children:[e.jsx("input",{type:"radio",name:`scope-${C.name}`,value:"user",checked:S==="user",onChange:()=>{I("user"),T("")},className:"accent-amber-600"}),e.jsx("span",{className:"text-foreground",children:"全局(所有项目可用)"})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"radio",name:`scope-${C.name}`,value:"local",checked:S==="local",onChange:()=>I("local"),className:"accent-amber-600"}),e.jsx("span",{className:"text-foreground",children:"安装到指定项目"})]}),S==="local"&&e.jsxs("select",{value:D,onChange:ne=>T(ne.target.value),className:"mt-2 w-full px-2 py-1.5 rounded-md border border-border bg-background text-foreground text-xs",children:[e.jsx("option",{value:"",children:"选择项目..."}),u.map(ne=>e.jsx("option",{value:ne.path||ne.fullPath,children:ne.displayName||ne.name},ne.name))]}),e.jsxs("div",{className:"flex gap-2 mt-3",children:[e.jsx(B,{size:"sm",variant:"outline",onClick:E,className:"flex-1",children:"取消"}),e.jsx(B,{size:"sm",className:"bg-amber-600 hover:bg-amber-700 text-white flex-1",onClick:W,children:"确认安装"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-auto pt-2",children:[e.jsxs(B,{variant:"ghost",size:"sm",onClick:()=>window.open(`https://github.com/${C.repository}`,"_blank"),children:[e.jsx(Vo,{className:"w-4 h-4 mr-1"}),"查看"]}),C.installed?e.jsx(B,{size:"sm",disabled:!0,variant:"outline",className:"ml-auto",children:"已安装"}):!te&&e.jsxs(B,{size:"sm",className:"bg-amber-600 hover:bg-amber-700 text-white ml-auto",onClick:()=>M(C),disabled:$||!!f,children:[e.jsx(It,{className:"w-4 h-4 mr-1"}),$?"安装中...":"安装"]})]})]})},`${C.repository}-${C.name}`)})})]})]})})}function Jc({onClose:r,onChanged:o}){const{showAlert:c,showConfirm:u}=it(),[l,m]=n.useState([]),[d,s]=n.useState(!0),[p,t]=n.useState(null),[x,h]=n.useState(""),[a,i]=n.useState("main"),[y,j]=n.useState(!1),[w,b]=n.useState(null);n.useEffect(()=>{k()},[]);const k=async()=>{try{s(!0),t(null);const S=await Y("/api/skills/repos");if(S.ok){const I=await S.json();m(I.repos||[])}else{const I=await S.json();t(I.error||"Failed to fetch repos")}}catch(S){t(S.message)}finally{s(!1)}},f=async S=>{if(S.preventDefault(),!x.trim()){t("请输入仓库 URL");return}try{j(!0),t(null);const I=await Y("/api/skills/repos",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:x.trim(),branch:a.trim()||"main"})});if(I.ok)h(""),i("main"),k(),o?.();else{const D=await I.json();t(D.error||"Failed to add repo")}}catch(I){t(I.message)}finally{j(!1)}},N=async(S,I)=>{if(await u(`确定要移除仓库 "${S}/${I}" 吗?`,{title:"移除仓库",variant:"danger",confirmText:"确认移除"}))try{b(`${S}/${I}`);const D=await Y(`/api/skills/repos/${S}/${I}`,{method:"DELETE"});if(D.ok)k(),o?.();else{const T=await D.json();c(T.error||"移除仓库失败",{variant:"error"})}}catch(D){c(D.message,{variant:"error"})}finally{b(null)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-background rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center gap-3 p-4 border-b border-border",children:[e.jsx(B,{variant:"ghost",size:"icon",onClick:r,children:e.jsx(er,{className:"w-5 h-5"})}),e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:"管理技能仓库"})]}),e.jsxs("div",{className:"flex-1 overflow-auto p-4 space-y-6",children:[e.jsxs("div",{className:"bg-gray-50 dark:bg-gray-900/50 rounded-lg p-4 space-y-4",children:[e.jsx("h3",{className:"font-medium text-foreground",children:"添加技能仓库"}),e.jsxs("form",{onSubmit:f,className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm text-muted-foreground mb-1",children:"仓库 URL"}),e.jsx(at,{type:"text",placeholder:"owner/name 或 https://github.com/owner/name",value:x,onChange:S=>h(S.target.value),disabled:y})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm text-muted-foreground mb-1",children:"分支"}),e.jsx(at,{type:"text",placeholder:"main",value:a,onChange:S=>i(S.target.value),disabled:y})]}),e.jsxs(B,{type:"submit",disabled:y||!x.trim(),className:"bg-amber-600 hover:bg-amber-700 text-white",children:[e.jsx(_t,{className:"w-4 h-4 mr-2"}),y?"添加中...":"添加仓库"]})]})]}),p&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 text-red-800 dark:text-red-200 text-sm",children:p}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h3",{className:"font-medium text-foreground",children:"已添加的仓库"}),d?e.jsx("div",{className:"text-center py-4 text-muted-foreground",children:"加载中..."}):l.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Zo,{className:"w-12 h-12 mx-auto mb-4 opacity-50"}),e.jsx("p",{children:"还没有添加任何仓库"})]}):l.map(S=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"font-medium text-foreground",children:[S.owner,"/",S.repo]}),S.isSystem&&e.jsx(tt,{variant:"outline",className:"text-xs bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-300",children:"内置"})]}),e.jsxs("div",{className:"flex items-center gap-3 mt-1 text-sm text-muted-foreground",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(tn,{className:"w-3 h-3"}),"分支: main"]}),e.jsxs(tt,{variant:"outline",className:"text-xs",children:["识别到 ",S.skillCount," 个技能"]})]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-4",children:[!S.isSystem&&S.url&&e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>window.open(S.url,"_blank"),children:e.jsx(Vo,{className:"w-4 h-4"})}),!S.isSystem&&e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>N(S.owner,S.repo),disabled:w===`${S.owner}/${S.repo}`,className:"text-red-500 hover:text-red-600",children:e.jsx(xt,{className:"w-4 h-4"})})]})]})},`${S.owner}/${S.repo}`))]})]})]})})}function qc({projects:r=[]}){const{showAlert:o,showConfirm:c}=it(),[u,l]=n.useState([]),[m,d]=n.useState(!0),[s,p]=n.useState(null),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),[j,w]=n.useState(null),b=n.useRef(null);n.useEffect(()=>{k()},[]);const k=async()=>{try{d(!0),p(null);const M=await Y("/api/skills");if(M.ok){const E=await M.json();l(E.skills||[])}else{const E=await M.json();p(E.error||"Failed to fetch skills")}}catch(M){p(M.message)}finally{d(!1)}},f=async()=>{try{const M=await Y("/api/skills");if(M.ok){const E=await M.json();l(E.skills||[])}}catch{}},N=async M=>{try{const E=await Y(`/api/skills/${M}/download`);if(!E.ok){const $=await E.json();o($.error||"下载技能失败",{variant:"error"});return}const W=await E.blob(),X=URL.createObjectURL(W),C=document.createElement("a");C.href=X,C.download=`${M}.zip`,C.click(),URL.revokeObjectURL(X)}catch(E){o(E.message,{variant:"error"})}},S=async M=>{if(await c(`确定要删除技能 "${M.name}" 吗?`,{title:"删除技能",variant:"danger",confirmText:"确认删除"}))try{const E=M.projectPath?`/api/skills/${M.name}?projectPath=${encodeURIComponent(M.projectPath)}`:`/api/skills/${M.name}`,W=await Y(E,{method:"DELETE"});if(W.ok)k();else{const X=await W.json();o(X.error||"删除技能失败",{variant:"error"})}}catch(E){o(E.message,{variant:"error"})}},I=async M=>{let E,W;if(M.syncType==="builtin"?(W="同步修改到云端",E=`确定要将技能 "${M.name}" 的本地修改推送到共享仓库吗?
|
|
154
|
+
`;if(typeof document<"u"){const r=document.createElement("style");r.type="text/css",r.innerText=Nc,document.head.appendChild(r)}function Tc({selectedProject:r,selectedSession:o,initialCommand:c,isPlainShell:u=!1,onProcessComplete:l,minimal:m=!1,autoConnect:d=!1}){const s=n.useRef(null),p=n.useRef(null),t=n.useRef(null),x=n.useRef(null),[h,a]=n.useState(!1),[i,y]=n.useState(!1),[j,w]=n.useState(!1),[b,k]=n.useState(null),[f,N]=n.useState(!1),S=n.useRef(r),I=n.useRef(o),D=n.useRef(c),T=n.useRef(u),R=n.useRef(l);n.useEffect(()=>{S.current=r,I.current=o,D.current=c,T.current=u,R.current=l});const M=n.useCallback(async()=>{if(!(f||h))try{const ne=localStorage.getItem("auth-token");if(!ne){console.error("No authentication token found for Shell WebSocket connection");return}const ie=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/shell?token=${encodeURIComponent(ne)}`;x.current=new WebSocket(ie),x.current.onopen=()=>{a(!0),N(!1),setTimeout(()=>{t.current&&p.current&&(t.current.fit(),x.current.send(JSON.stringify({type:"init",projectPath:S.current.fullPath||S.current.path,sessionId:T.current?null:I.current?.id,hasSession:T.current?!1:!!I.current,provider:T.current?"plain-shell":I.current?.__provider||"claude",cols:p.current.cols,rows:p.current.rows,initialCommand:D.current,isPlainShell:T.current})))},100)},x.current.onmessage=le=>{try{const xe=JSON.parse(le.data);if(xe.type==="output"){let Ce=xe.data;if(T.current&&R.current){const be=Ce.replace(/\x1b\[[0-9;]*m/g,"");if(be.includes("Process exited with code 0"))R.current(0);else if(be.match(/Process exited with code (\d+)/)){const Se=parseInt(be.match(/Process exited with code (\d+)/)[1]);Se!==0&&R.current(Se)}}p.current&&p.current.write(Ce)}else xe.type==="url_open"&&window.open(xe.url,"_blank")}catch(xe){console.error("[Shell] Error handling WebSocket message:",xe,le.data)}},x.current.onclose=le=>{a(!1),N(!1),p.current&&(p.current.clear(),p.current.write("\x1B[2J\x1B[H"))},x.current.onerror=le=>{a(!1),N(!1)}}catch{a(!1),N(!1)}},[f,h]),E=n.useCallback(()=>{!i||h||f||(N(!0),M())},[i,h,f,M]),W=n.useCallback(()=>{x.current&&(x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"terminate"})),x.current.close(),x.current=null),p.current&&(p.current.clear(),p.current.write("\x1B[2J\x1B[H")),a(!1),N(!1)},[]),X=n.useMemo(()=>o?o.summary||"New Session":null,[o]),C=n.useMemo(()=>X?X.slice(0,30):null,[X]),$=n.useMemo(()=>X?X.slice(0,50):null,[X]),te=()=>{w(!0),x.current&&(x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"terminate"})),x.current.close(),x.current=null),p.current&&(p.current.dispose(),p.current=null,t.current=null),a(!1),y(!1),setTimeout(()=>{w(!1)},200)};return n.useEffect(()=>{const ne=o?.id||null;b!==null&&b!==ne&&i&&W(),k(ne)},[o?.id,i,W]),n.useEffect(()=>{if(!s.current||!r||j||p.current)return;p.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff",extendedAnsi:["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"]}}),t.current=new Vn.FitAddon;const ne=new Zn.WebglAddon,G=new Qn.WebLinksAddon;p.current.loadAddon(t.current),p.current.loadAddon(G);try{p.current.loadAddon(ne)}catch{console.warn("[Shell] WebGL renderer unavailable, using Canvas fallback")}p.current.open(s.current),p.current.attachCustomKeyEventHandler(le=>(le.ctrlKey||le.metaKey)&&le.key==="c"&&p.current.hasSelection()?(document.execCommand("copy"),!1):(le.ctrlKey||le.metaKey)&&le.key==="v"?(navigator.clipboard.readText().then(xe=>{x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"input",data:xe}))}).catch(()=>{}),!1):!0),setTimeout(()=>{t.current&&(t.current.fit(),p.current&&x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"resize",cols:p.current.cols,rows:p.current.rows})))},100),y(!0),p.current.onData(le=>{x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"input",data:le}))});const ie=new ResizeObserver(()=>{t.current&&p.current&&setTimeout(()=>{t.current.fit(),x.current&&x.current.readyState===WebSocket.OPEN&&x.current.send(JSON.stringify({type:"resize",cols:p.current.cols,rows:p.current.rows}))},50)});return s.current&&ie.observe(s.current),()=>{ie.disconnect(),x.current&&(x.current.readyState===WebSocket.OPEN||x.current.readyState===WebSocket.CONNECTING)&&x.current.close(),x.current=null,p.current&&(p.current.dispose(),p.current=null)}},[r?.path||r?.fullPath,j]),n.useEffect(()=>{!d||!i||f||h||E()},[d,i,f,h,E]),r?m?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:s,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${h?"bg-green-500":"bg-red-500"}`}),o&&e.jsxs("span",{className:"text-xs text-blue-300",children:["(",C,"...)"]}),!o&&e.jsx("span",{className:"text-xs text-gray-400",children:"(新会话)"}),!i&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),j&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[h&&e.jsxs("button",{onClick:W,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Shell 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:te,disabled:j||h,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Shell(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:s,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),i&&!h&&!f&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:E,className:"px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",title:"Connect to shell",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"在 Shell 中继续"})]}),e.jsx("p",{className:"text-gray-400 text-sm mt-3 px-2",children:u?`Run ${c||"command"} in ${r.displayName}`:o?`Resume session: ${$}...`:"Start a new Claude session"})]})}),f&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Shell..."})]}),e.jsx("p",{className:"text-gray-400 text-sm mt-3 px-2",children:u?`Running ${c||"command"} in ${r.displayName}`:`Starting Claude CLI in ${r.displayName}`})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开交互式 Shell"})]})})}function Sc({project:r,session:o=null,command:c=null,isPlainShell:u=null,autoConnect:l=!0,onComplete:m=null,onClose:d=null,title:s=null,className:p="",showHeader:t=!0,compact:x=!1,minimal:h=!1}){const[a,i]=n.useState(!1),y=u!==null?u:c!==null,j=n.useCallback(w=>{i(!0),m&&m(w)},[m]);return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${p}`,children:[!h&&t&&s&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:s}),a&&e.jsx("span",{className:"text-xs text-green-400",children:"(已完成)"})]}),d&&e.jsx("button",{onClick:d,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Tc,{selectedProject:r,selectedSession:o,initialCommand:c,isPlainShell:y,onProcessComplete:j,minimal:h,autoConnect:h?!0:l})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${p}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Shell 需要一个项目"})]})})}function Xc({selectedProject:r,minimal:o=!1,autoConnect:c=!1}){const u=n.useRef(null),l=n.useRef(null),m=n.useRef(null),d=n.useRef(null),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),j=n.useRef(r);n.useEffect(()=>{j.current=r});const w=n.useCallback(async()=>{if(!(i||s))try{const N=localStorage.getItem("auth-token");if(!N){console.error("No authentication token found for Codex WebSocket connection");return}const I=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/codex?token=${encodeURIComponent(N)}`;d.current=new WebSocket(I),d.current.onopen=()=>{p(!0),y(!1),setTimeout(()=>{m.current&&l.current&&(m.current.fit(),d.current.send(JSON.stringify({type:"init",projectPath:j.current.fullPath||j.current.path,cols:l.current.cols,rows:l.current.rows})))},100)},d.current.onmessage=D=>{try{const T=JSON.parse(D.data);T.type==="output"?l.current&&l.current.write(T.data):T.type==="url_open"&&window.open(T.url,"_blank")}catch(T){console.error("[CodexShell] Error handling WebSocket message:",T)}},d.current.onclose=()=>{p(!1),y(!1),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H"))},d.current.onerror=()=>{p(!1),y(!1)}}catch{p(!1),y(!1)}},[i,s]),b=n.useCallback(()=>{!t||s||i||(y(!0),w())},[t,s,i,w]),k=n.useCallback(()=>{d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H")),p(!1),y(!1)},[]),f=()=>{a(!0),d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.dispose(),l.current=null,m.current=null),p(!1),x(!1),setTimeout(()=>a(!1),200)};return n.useEffect(()=>{if(!u.current||!r||h||l.current)return;l.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff"}}),m.current=new Vn.FitAddon;const N=new Zn.WebglAddon,S=new Qn.WebLinksAddon;l.current.loadAddon(m.current),l.current.loadAddon(S);try{l.current.loadAddon(N)}catch{console.warn("[CodexShell] WebGL renderer unavailable, using Canvas fallback")}l.current.open(u.current),l.current.attachCustomKeyEventHandler(D=>(D.ctrlKey||D.metaKey)&&D.key==="c"&&l.current.hasSelection()?(document.execCommand("copy"),!1):(D.ctrlKey||D.metaKey)&&D.key==="v"?(navigator.clipboard.readText().then(T=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:T}))}).catch(()=>{}),!1):!0),setTimeout(()=>{m.current&&(m.current.fit(),l.current&&d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows})))},100),x(!0),l.current.onData(D=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:D}))});const I=new ResizeObserver(()=>{m.current&&l.current&&setTimeout(()=>{m.current.fit(),d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows}))},50)});return u.current&&I.observe(u.current),()=>{I.disconnect(),d.current&&(d.current.readyState===WebSocket.OPEN||d.current.readyState===WebSocket.CONNECTING)&&d.current.close(),d.current=null,l.current&&(l.current.dispose(),l.current=null)}},[r?.path||r?.fullPath,h]),n.useEffect(()=>{!c||!t||i||s||b()},[c,t,i,s,b]),r?o?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${s?"bg-green-500":"bg-red-500"}`}),e.jsx("span",{className:"text-xs text-gray-300 font-medium",children:"Codex"}),!t&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),h&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[s&&e.jsxs("button",{onClick:k,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Codex 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:f,disabled:h||s,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Codex(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!t&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),t&&!s&&!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:b,className:"px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"启动 Codex"})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["在 ",r.displayName," 中启动 Codex CLI"]})]})}),i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Codex..."})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["正在 ",r.displayName," 中启动 Codex CLI"]})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开 Codex"})]})})}function Mc({project:r,autoConnect:o=!0,onClose:c=null,className:u="",showHeader:l=!0,minimal:m=!1}){return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${u}`,children:[!m&&l&&c&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:"Codex"}),e.jsx("button",{onClick:c,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Xc,{selectedProject:r,minimal:m,autoConnect:m?!0:o})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${u}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Codex 需要一个项目"})]})})}function Oc({selectedProject:r,minimal:o=!1,autoConnect:c=!1}){const u=n.useRef(null),l=n.useRef(null),m=n.useRef(null),d=n.useRef(null),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),j=n.useRef(r);n.useEffect(()=>{j.current=r});const w=n.useCallback(async()=>{if(!(i||s))try{const N=localStorage.getItem("auth-token");if(!N){console.error("No authentication token found for Gemini WebSocket connection");return}const I=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/gemini?token=${encodeURIComponent(N)}`;d.current=new WebSocket(I),d.current.onopen=()=>{p(!0),y(!1),setTimeout(()=>{m.current&&l.current&&(m.current.fit(),d.current.send(JSON.stringify({type:"init",projectPath:j.current.fullPath||j.current.path,cols:l.current.cols,rows:l.current.rows})))},100)},d.current.onmessage=D=>{try{const T=JSON.parse(D.data);T.type==="output"?l.current&&l.current.write(T.data):T.type==="url_open"&&window.open(T.url,"_blank")}catch(T){console.error("[GeminiShell] Error handling WebSocket message:",T)}},d.current.onclose=()=>{p(!1),y(!1),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H"))},d.current.onerror=()=>{p(!1),y(!1)}}catch{p(!1),y(!1)}},[i,s]),b=n.useCallback(()=>{!t||s||i||(y(!0),w())},[t,s,i,w]),k=n.useCallback(()=>{d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.clear(),l.current.write("\x1B[2J\x1B[H")),p(!1),y(!1)},[]),f=()=>{a(!0),d.current&&(d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"terminate"})),d.current.close(),d.current=null),l.current&&(l.current.dispose(),l.current=null,m.current=null),p(!1),x(!1),setTimeout(()=>a(!1),200)};return n.useEffect(()=>{if(!u.current||!r||h||l.current)return;l.current=new Kn.Terminal({cursorBlink:!0,fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',allowProposedApi:!0,allowTransparency:!1,convertEol:!0,scrollback:1e4,tabStopWidth:4,windowsMode:!1,macOptionIsMeta:!0,macOptionClickForcesSelection:!1,theme:{background:"#1e1e1e",foreground:"#d4d4d4",cursor:"#ffffff",cursorAccent:"#1e1e1e",selection:"#264f78",selectionForeground:"#ffffff",black:"#000000",red:"#cd3131",green:"#0dbc79",yellow:"#e5e510",blue:"#2472c8",magenta:"#bc3fbc",cyan:"#11a8cd",white:"#e5e5e5",brightBlack:"#666666",brightRed:"#f14c4c",brightGreen:"#23d18b",brightYellow:"#f5f543",brightBlue:"#3b8eea",brightMagenta:"#d670d6",brightCyan:"#29b8db",brightWhite:"#ffffff"}}),m.current=new Vn.FitAddon;const N=new Zn.WebglAddon,S=new Qn.WebLinksAddon;l.current.loadAddon(m.current),l.current.loadAddon(S);try{l.current.loadAddon(N)}catch{console.warn("[GeminiShell] WebGL renderer unavailable, using Canvas fallback")}l.current.open(u.current),l.current.attachCustomKeyEventHandler(D=>(D.ctrlKey||D.metaKey)&&D.key==="c"&&l.current.hasSelection()?(document.execCommand("copy"),!1):(D.ctrlKey||D.metaKey)&&D.key==="v"?(navigator.clipboard.readText().then(T=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:T}))}).catch(()=>{}),!1):!0),setTimeout(()=>{m.current&&(m.current.fit(),l.current&&d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows})))},100),x(!0),l.current.onData(D=>{d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"input",data:D}))});const I=new ResizeObserver(()=>{m.current&&l.current&&setTimeout(()=>{m.current.fit(),d.current&&d.current.readyState===WebSocket.OPEN&&d.current.send(JSON.stringify({type:"resize",cols:l.current.cols,rows:l.current.rows}))},50)});return u.current&&I.observe(u.current),()=>{I.disconnect(),d.current&&(d.current.readyState===WebSocket.OPEN||d.current.readyState===WebSocket.CONNECTING)&&d.current.close(),d.current=null,l.current&&(l.current.dispose(),l.current=null)}},[r?.path||r?.fullPath,h]),n.useEffect(()=>{!c||!t||i||s||b()},[c,t,i,s,b]),r?o?e.jsx("div",{className:"h-full w-full bg-gray-900",children:e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}})}):e.jsxs("div",{className:"h-full flex flex-col bg-gray-900 w-full",children:[e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${s?"bg-green-500":"bg-red-500"}`}),e.jsx("span",{className:"text-xs text-gray-300 font-medium",children:"Gemini"}),!t&&e.jsx("span",{className:"text-xs text-yellow-400",children:"(正在初始化...)"}),h&&e.jsx("span",{className:"text-xs text-blue-400",children:"(正在重启...)"})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[s&&e.jsxs("button",{onClick:k,className:"px-3 py-1 text-xs bg-red-600 text-white rounded hover:bg-red-700 flex items-center space-x-1",title:"断开 Gemini 连接",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{children:"断开连接"})]}),e.jsxs("button",{onClick:f,disabled:h||s,className:"text-xs text-gray-400 hover:text-white disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1",title:"重启 Gemini(先断开连接)",children:[e.jsx("svg",{className:"w-3 h-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),e.jsx("span",{children:"重启"})]})]})]})}),e.jsxs("div",{className:"flex-1 p-2 overflow-hidden relative",children:[e.jsx("div",{ref:u,className:"h-full w-full focus:outline-none",style:{outline:"none"}}),!t&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90",children:e.jsx("div",{className:"text-white",children:"加载终端中..."})}),t&&!s&&!i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("button",{onClick:b,className:"px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center justify-center space-x-2 text-base font-medium w-full sm:w-auto",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 10V3L4 14h7v7l9-11h-7z"})}),e.jsx("span",{children:"启动 Gemini"})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["在 ",r.displayName," 中启动 Gemini CLI"]})]})}),i&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-90 p-4",children:e.jsxs("div",{className:"text-center max-w-sm w-full",children:[e.jsxs("div",{className:"flex items-center justify-center space-x-3 text-yellow-400",children:[e.jsx("div",{className:"w-6 h-6 animate-spin rounded-full border-2 border-yellow-400 border-t-transparent"}),e.jsx("span",{className:"text-base font-medium",children:"连接到 Gemini..."})]}),e.jsxs("p",{className:"text-gray-400 text-sm mt-3 px-2",children:["正在 ",r.displayName," 中启动 Gemini CLI"]})]})})]})]}):e.jsx("div",{className:"h-full flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"选择项目"}),e.jsx("p",{children:"选择一个项目以在该目录中打开 Gemini"})]})})}function Cc({project:r,autoConnect:o=!0,onClose:c=null,className:u="",showHeader:l=!0,minimal:m=!1}){return r?e.jsxs("div",{className:`h-full w-full flex flex-col ${u}`,children:[!m&&l&&c&&e.jsx("div",{className:"flex-shrink-0 bg-gray-800 border-b border-gray-700 px-4 py-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-medium text-gray-200",children:"Gemini"}),e.jsx("button",{onClick:c,className:"text-gray-400 hover:text-white",title:"关闭",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})}),e.jsx("div",{className:"flex-1 w-full min-h-0",children:e.jsx(Oc,{selectedProject:r,minimal:m,autoConnect:m?!0:o})})]}):e.jsx("div",{className:`h-full flex items-center justify-center ${u}`,children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2z"})})}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"未选择项目"}),e.jsx("p",{children:"打开 Gemini 需要一个项目"})]})})}class Ec extends lt.Component{constructor(o){super(o),this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(o){return{hasError:!0}}componentDidCatch(o,c){console.error("ErrorBoundary caught an error:",o,c),this.setState({error:o,errorInfo:c})}render(){return this.state.hasError?e.jsx("div",{className:"flex flex-col items-center justify-center p-8 text-center",children:e.jsxs("div",{className:"bg-red-50 border border-red-200 rounded-lg p-6 max-w-md",children:[e.jsxs("div",{className:"flex items-center mb-4",children:[e.jsx("div",{className:"flex-shrink-0",children:e.jsx("svg",{className:"h-5 w-5 text-red-400",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z",clipRule:"evenodd"})})}),e.jsx("h3",{className:"ml-3 text-sm font-medium text-red-800",children:"出现问题"})]}),e.jsxs("div",{className:"text-sm text-red-700",children:[e.jsx("p",{className:"mb-2",children:"加载聊天界面时出现错误。"}),this.props.showDetails&&this.state.error&&e.jsxs("details",{className:"mt-4",children:[e.jsx("summary",{className:"cursor-pointer text-xs font-mono",children:"错误详情"}),e.jsxs("pre",{className:"mt-2 text-xs bg-red-100 p-2 rounded overflow-auto max-h-40",children:[this.state.error.toString(),this.state.errorInfo&&this.state.errorInfo.componentStack]})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx("button",{onClick:()=>{this.setState({hasError:!1,error:null,errorInfo:null}),this.props.onRetry&&this.props.onRetry()},className:"bg-red-600 text-white px-4 py-2 rounded text-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500",children:"重试"})})]})}):this.props.children}}const jr=({children:r,content:o,position:c="top",className:u="",delay:l=500})=>{const[m,d]=n.useState(!1),[s,p]=n.useState(null),t=()=>{const i=setTimeout(()=>{d(!0)},l);p(i)},x=()=>{s&&(clearTimeout(s),p(null)),d(!1)},h=()=>{switch(c){case"top":return"bottom-full left-1/2 transform -translate-x-1/2 mb-2";case"bottom":return"top-full left-1/2 transform -translate-x-1/2 mt-2";case"left":return"right-full top-1/2 transform -translate-y-1/2 mr-2";case"right":return"left-full top-1/2 transform -translate-y-1/2 ml-2";default:return"bottom-full left-1/2 transform -translate-x-1/2 mb-2"}},a=()=>{switch(c){case"top":return"top-full left-1/2 transform -translate-x-1/2 border-t-gray-900 dark:border-t-gray-100";case"bottom":return"bottom-full left-1/2 transform -translate-x-1/2 border-b-gray-900 dark:border-b-gray-100";case"left":return"left-full top-1/2 transform -translate-y-1/2 border-l-gray-900 dark:border-l-gray-100";case"right":return"right-full top-1/2 transform -translate-y-1/2 border-r-gray-900 dark:border-r-gray-100";default:return"top-full left-1/2 transform -translate-x-1/2 border-t-gray-900 dark:border-t-gray-100"}};return o?e.jsxs("div",{className:"relative inline-block",onMouseEnter:t,onMouseLeave:x,children:[r,m&&e.jsxs("div",{className:nt("absolute z-50 px-2 py-1 text-xs font-medium text-white bg-gray-900 dark:bg-gray-100 dark:text-gray-900 rounded shadow-lg whitespace-nowrap pointer-events-none","animate-in fade-in-0 zoom-in-95 duration-200",h(),u),children:[o,e.jsx("div",{className:nt("absolute w-0 h-0 border-4 border-transparent",a())})]})]}):r};function Dc(){const[r,o]=n.useState(null),[c,u]=n.useState([]),[l,m]=n.useState(!1),d=n.useRef(null),s=n.useRef(null),p=n.useRef(0),{token:t}=Xt();n.useEffect(()=>{d.current&&(clearTimeout(d.current),d.current=null),s.current&&(s.current.close(),s.current=null),t?(p.current=0,x()):(m(!1),o(null));const a=()=>{if(document.visibilityState==="visible"){const i=s.current?.readyState;(i===void 0||i===3||i===2)&&(d.current&&(clearTimeout(d.current),d.current=null),p.current=0,x())}};return document.addEventListener("visibilitychange",a),()=>{document.removeEventListener("visibilitychange",a),d.current&&clearTimeout(d.current),s.current&&s.current.close()}},[t]);const x=()=>{try{const a=t||localStorage.getItem("auth-token");if(!a){console.warn("No authentication token found for WebSocket connection");return}const y=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws?token=${encodeURIComponent(a)}`,j=new WebSocket(y);s.current=j,j.onopen=()=>{p.current=0,m(!0),o(j)},j.onmessage=w=>{try{const b=JSON.parse(w.data);u(k=>[...k,b])}catch(b){console.error("Error parsing WebSocket message:",b)}},j.onclose=()=>{if(m(!1),o(null),s.current=null,localStorage.getItem("auth-token")){const b=Math.min(1e3*Math.pow(2,p.current),15e3);p.current+=1,d.current=setTimeout(()=>{x()},b)}},j.onerror=w=>{console.error("WebSocket error:",w)}}catch(a){console.error("Error creating WebSocket connection:",a)}};return{ws:r,sendMessage:a=>{r&&l?r.send(JSON.stringify(a)):console.warn("WebSocket not connected")},messages:c,isConnected:l}}const ws=n.createContext({ws:null,sendMessage:()=>{},messages:[],isConnected:!1}),Ns=()=>{const r=n.useContext(ws);if(!r)throw new Error("useWebSocketContext must be used within a WebSocketProvider");return r},Pc=({children:r})=>{const o=Dc();return e.jsx(ws.Provider,{value:o,children:r})};function Ac({selectedProject:r,selectedSession:o,activeTab:c,setActiveTab:u,ws:l,sendMessage:m,messages:d,isMobile:s,isPWA:p,onMenuClick:t,isLoading:x,onInputFocusChange:h,onSessionActive:a,onSessionInactive:i,onSessionProcessing:y,onSessionNotProcessing:j,processingSessions:w,onReplaceTemporarySession:b,onNavigateToSession:k,onShowSettings:f,autoScrollToBottom:N,sendByCtrlEnter:S,externalMessageUpdate:I,limitStatus:D,onLimitBlocked:T,checkLimitStatus:R}){const{showConfirm:M}=it(),{hasPermission:E}=Xt(),{isConnected:W}=Ns(),[X,C]=n.useState(null),[$,te]=n.useState(null),[ne,G]=n.useState(600),[ie,le]=n.useState(!1),[xe,Ce]=n.useState(!1),be=n.useRef(null),Se=async ye=>{const Xe="previewTabAcknowledged";if(!localStorage.getItem(Xe)){const Ee=await M("此功能的对话记录不会显示在当前网页的会话列表中,与 Chat 是两套独立的系统,请注意区分。",{title:"预览功能提示",subtitle:ye==="codex"?"Codex":"Gemini CLI",variant:"warning",confirmText:"我知道了,继续",cancelText:"取消",checkboxLabel:"不再提醒"});if(!Ee?.confirmed)return;Ee.checked&&localStorage.setItem(Xe,"1")}u(ye)};n.useEffect(()=>{c==="shell"&&R&&R()},[c,R]);const Re=["png","jpg","jpeg","gif","svg","webp","ico","bmp"],se=(ye,Xe=null)=>{const Ee=ye.split(".").pop()?.toLowerCase();if(Re.includes(Ee)){te({name:ye.split("/").pop(),path:ye,projectName:r?.name,projectPath:r?.path});return}const Fe={name:ye.split("/").pop(),path:ye,projectName:r?.name,diffInfo:Xe};C(Fe)},we=()=>{C(null),Ce(!1)},$e=()=>{Ce(!xe)},We=ye=>{s||(le(!0),ye.preventDefault())};return n.useEffect(()=>{const ye=Ee=>{if(!ie)return;const Fe=be.current?.parentElement;if(!Fe)return;const Ne=Fe.getBoundingClientRect(),Be=Ne.right-Ee.clientX,Pe=300,Ae=Ne.width*.8;Be>=Pe&&Be<=Ae&&G(Be)},Xe=()=>{le(!1)};return ie&&(document.addEventListener("mousemove",ye),document.addEventListener("mouseup",Xe),document.body.style.cursor="col-resize",document.body.style.userSelect="none"),()=>{document.removeEventListener("mousemove",ye),document.removeEventListener("mouseup",Xe),document.body.style.cursor="",document.body.style.userSelect=""}},[ie]),x?e.jsxs("div",{className:"h-full flex flex-col",children:[s&&e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsx("button",{onClick:t,className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 pwa-menu-button",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-4",children:e.jsx("div",{className:"w-full h-full rounded-full border-4 border-gray-200 border-t-blue-500",style:{animation:"spin 1s linear infinite",WebkitAnimation:"spin 1s linear infinite",MozAnimation:"spin 1s linear infinite"}})}),e.jsxs("h2",{className:"text-xl font-semibold mb-2",children:["正在加载 ",et]}),e.jsx("p",{children:"正在设置您的工作区..."})]})})]}):r?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsxs("div",{className:"flex items-center justify-between relative",children:[e.jsxs("div",{className:"flex items-center space-x-2 min-w-0 flex-1",children:[s&&e.jsx("button",{onClick:t,onTouchStart:ye=>{ye.preventDefault(),t()},className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 touch-manipulation active:scale-95 pwa-menu-button flex-shrink-0",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})}),e.jsx("div",{className:"min-w-0 flex items-center gap-2 flex-1 overflow-x-auto scrollbar-hide",children:e.jsx("div",{className:"min-w-0 flex-1",children:c==="chat"&&o?e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white whitespace-nowrap overflow-x-auto scrollbar-hide",children:o.summary||"新会话"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName}),e.jsxs("span",{className:`inline-flex items-center gap-1 text-xs ${W?"text-green-600 dark:text-green-400":"text-red-500 dark:text-red-400 animate-pulse"}`,children:[W?e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.288 15.038a5.25 5.25 0 017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z"})}):e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.412 15.655L9.75 21.75l3.745-4.012M9.257 13.5H3.75l2.659-2.849m2.048-2.194L14.25 2.25 12 10.5h8.25l-4.707 5.043M6.53 9.345A3.778 3.778 0 0112 8.25c1.372 0 2.585.59 3.43 1.53M3 3l18 18"})}),e.jsx("span",{className:"hidden sm:inline",children:W?"连接正常":"连接异常"})]})]})]}):c==="chat"&&!o?e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white",children:"新会话"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName}),e.jsxs("span",{className:`inline-flex items-center gap-1 text-xs ${W?"text-green-600 dark:text-green-400":"text-red-500 dark:text-red-400 animate-pulse"}`,children:[W?e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.288 15.038a5.25 5.25 0 017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z"})}):e.jsx("svg",{className:"w-2.5 h-2.5",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.412 15.655L9.75 21.75l3.745-4.012M9.257 13.5H3.75l2.659-2.849m2.048-2.194L14.25 2.25 12 10.5h8.25l-4.707 5.043M6.53 9.345A3.778 3.778 0 0112 8.25c1.372 0 2.585.59 3.43 1.53M3 3l18 18"})}),e.jsx("span",{className:"hidden sm:inline",children:W?"连接正常":"连接异常"})]})]})]}):e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-sm sm:text-base font-semibold text-gray-900 dark:text-white",children:c==="files"?"项目文件":"项目"}),e.jsx("div",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:r.displayName})]})})})]}),e.jsx("div",{className:"flex-shrink-0 hidden sm:block",children:e.jsxs("div",{className:"relative flex bg-gray-100 dark:bg-gray-800 rounded-lg p-1",children:[e.jsx(jr,{content:"Chat",position:"bottom",children:e.jsx("button",{onClick:()=>u("chat"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md ${c==="chat"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Chat"})]})})}),e.jsx(jr,{content:"Files",position:"bottom",children:e.jsx("button",{onClick:()=>u("files"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="files"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-5l-2-2H5a2 2 0 00-2 2z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Files"})]})})}),E("claude_shell")&&e.jsx(jr,{content:D&&!D.allowed?"使用已达上限":"Claude Code",position:"bottom",children:e.jsx("button",{onClick:()=>{if(D&&!D.allowed){T?.(D.reason);return}u("shell")},className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${D&&!D.allowed?"opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-500":c==="shell"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z",fill:"#D97757",fillRule:"nonzero"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Claude Code"})]})})}),E("codex_shell")&&e.jsx(jr,{content:"Codex",position:"bottom",children:e.jsx("button",{onClick:()=>Se("codex"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="codex"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsx("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",fill:"currentColor",fillRule:"evenodd",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"})}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Codex"})]})})}),E("gemini_shell")&&e.jsx(jr,{content:"Gemini CLI",position:"bottom",children:e.jsx("button",{onClick:()=>Se("gemini"),className:`relative px-2 sm:px-3 py-1.5 text-xs sm:text-sm font-medium rounded-md transition-all duration-200 ${c==="gemini"?"bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-700"}`,children:e.jsxs("span",{className:"flex items-center gap-1 sm:gap-1.5",children:[e.jsxs("svg",{className:"w-3 sm:w-3.5 h-3 sm:h-3.5",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"#3186FF"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-0)"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-1)"}),e.jsx("path",{d:"M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z",fill:"url(#gemini-tab-fill-2)"}),e.jsxs("defs",{children:[e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-0",x1:"7",x2:"11",y1:"15.5",y2:"12",children:[e.jsx("stop",{stopColor:"#08B962"}),e.jsx("stop",{offset:"1",stopColor:"#08B962",stopOpacity:"0"})]}),e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-1",x1:"8",x2:"11.5",y1:"5.5",y2:"11",children:[e.jsx("stop",{stopColor:"#F94543"}),e.jsx("stop",{offset:"1",stopColor:"#F94543",stopOpacity:"0"})]}),e.jsxs("linearGradient",{gradientUnits:"userSpaceOnUse",id:"gemini-tab-fill-2",x1:"3.5",x2:"17.5",y1:"13.5",y2:"12",children:[e.jsx("stop",{stopColor:"#FABC12"}),e.jsx("stop",{offset:".46",stopColor:"#FABC12",stopOpacity:"0"})]})]})]}),e.jsx("span",{className:"hidden md:hidden lg:inline",children:"Gemini CLI"})]})})})]})})]})}),e.jsxs("div",{className:"flex-1 flex min-h-0 overflow-hidden",children:[e.jsxs("div",{className:`flex-1 flex flex-col min-h-0 overflow-hidden ${X?"mr-0":""} ${xe?"hidden":""}`,children:[e.jsx("div",{className:`h-full ${c==="chat"?"block":"hidden"}`,children:e.jsx(Ec,{showDetails:!0,children:e.jsx(kc,{selectedProject:r,selectedSession:o,ws:l,sendMessage:m,messages:d,onFileOpen:se,onInputFocusChange:h,onSessionActive:a,onSessionInactive:i,onSessionProcessing:y,onSessionNotProcessing:j,processingSessions:w,onReplaceTemporarySession:b,onNavigateToSession:k,onShowSettings:f,autoScrollToBottom:N,sendByCtrlEnter:S,externalMessageUpdate:I,limitStatus:D,onLimitExceeded:T,checkLimitStatus:R})})}),c==="files"&&e.jsx("div",{className:"h-full overflow-hidden",children:e.jsx(wc,{selectedProject:r})}),c==="shell"&&e.jsxs("div",{className:"h-full w-full overflow-hidden relative",children:[e.jsx(Sc,{project:r,session:o,showHeader:!1}),D&&!D.allowed&&e.jsx("div",{className:"absolute inset-0 bg-black/60 z-50 flex items-center justify-center",children:e.jsxs("div",{className:"bg-card border border-border rounded-lg shadow-xl p-6 mx-4 max-w-md text-center",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-4 bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-6 h-6 text-red-600 dark:text-red-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})}),e.jsx("h3",{className:"text-lg font-semibold text-foreground mb-2",children:D.reason==="total_limit_exceeded"?"使用上限已达到":"今日使用上限已达到"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:D.reason==="total_limit_exceeded"?"您已达到使用上限,请联系管理员提升额度。":"您已达到今日使用上限,请明日再来或联系管理员提升额度。"}),e.jsx("button",{onClick:()=>u("chat"),className:"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",children:"返回 Chat"})]})})]}),c==="codex"&&e.jsx("div",{className:"h-full w-full overflow-hidden relative",children:e.jsx(Mc,{project:r,showHeader:!1})}),c==="gemini"&&e.jsx("div",{className:"h-full w-full overflow-hidden relative",children:e.jsx(Cc,{project:r,showHeader:!1})}),e.jsx("div",{className:`h-full overflow-hidden ${c==="preview"?"block":"hidden"}`})]}),X&&!s&&e.jsxs(e.Fragment,{children:[!xe&&e.jsx("div",{ref:be,onMouseDown:We,className:"flex-shrink-0 w-1 bg-gray-200 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 cursor-col-resize transition-colors relative group",title:"Drag to resize",children:e.jsx("div",{className:"absolute inset-y-0 left-1/2 -translate-x-1/2 w-1 bg-blue-500 dark:bg-blue-600 opacity-0 group-hover:opacity-100 transition-opacity"})}),e.jsx("div",{className:`flex-shrink-0 border-l border-gray-200 dark:border-gray-700 h-full overflow-hidden ${xe?"flex-1":""}`,style:xe?{}:{width:`${ne}px`},children:e.jsx($n,{file:X,onClose:we,projectPath:r?.path,isSidebar:!0,isExpanded:xe,onToggleExpand:$e})})]})]}),X&&s&&e.jsx($n,{file:X,onClose:we,projectPath:r?.path,isSidebar:!1}),$&&e.jsx(ks,{file:$,onClose:()=>te(null)})]}):e.jsxs("div",{className:"h-full flex flex-col",children:[s&&e.jsx("div",{className:"bg-background border-b border-border p-2 sm:p-3 pwa-header-safe flex-shrink-0",children:e.jsx("button",{onClick:t,className:"p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 pwa-menu-button",children:e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"})})})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsxs("div",{className:"text-center text-gray-500 dark:text-gray-400 max-w-md mx-auto px-6",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-6 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-5l-2-2H5a2 2 0 00-2 2z"})})}),e.jsx("h2",{className:"text-2xl font-semibold mb-3 text-gray-900 dark:text-white",children:"选择您的项目"}),e.jsxs("p",{className:"text-gray-600 dark:text-gray-300 mb-6 leading-relaxed",children:["从侧边栏选择一个项目,开始与 ",et," 进行交流。每个项目包含您的聊天会话和文件历史。"]}),e.jsx("div",{className:"bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4 border border-blue-200 dark:border-blue-800",children:e.jsxs("p",{className:"text-sm text-blue-700 dark:text-blue-300",children:["💡 ",e.jsx("strong",{children:"提示:"})," ",s?"点击上方菜单按钮访问项目":E("create_project")?"点击侧边栏中的文件夹图标创建新项目":"点击侧边栏中的「使用项目模板」按钮来创建项目"]})})]})})]})}const Lc=lt.memo(Ac);function Ic({activeTab:r,setActiveTab:o,isInputFocused:c}){const u=[{id:"chat",icon:Cr,onClick:()=>o("chat")},{id:"shell",icon:Fn,onClick:()=>o("shell")},{id:"files",icon:Qt,onClick:()=>o("files")}];return e.jsx("div",{className:`fixed bottom-0 left-0 right-0 bg-background border-t border-border z-50 ios-bottom-safe transform transition-transform duration-300 ease-in-out shadow-lg ${c?"translate-y-full":"translate-y-0"}`,children:e.jsx("div",{className:"flex items-center justify-around py-1",children:u.map(l=>{const m=l.icon,d=r===l.id;return e.jsxs("button",{onClick:l.onClick,onTouchStart:s=>{s.preventDefault(),l.onClick()},className:`flex items-center justify-center p-2 rounded-lg min-h-[40px] min-w-[40px] relative touch-manipulation ${d?"text-blue-600 dark:text-blue-400":"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white"}`,"aria-label":l.id,children:[e.jsx(m,{className:"w-5 h-5"}),d&&e.jsx("div",{className:"absolute top-0 left-1/2 transform -translate-x-1/2 w-6 h-0.5 bg-blue-600 dark:bg-blue-400 rounded-full"})]},l.id)})})})}const Ts=n.createContext(),eo=()=>{const r=n.useContext(Ts);if(!r)throw new Error("useTheme must be used within a ThemeProvider");return r},_c=({children:r})=>{const[o,c]=n.useState(()=>{const m=localStorage.getItem("theme");return m?m==="dark":window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)").matches:!1});n.useEffect(()=>{if(o){document.documentElement.classList.add("dark"),localStorage.setItem("theme","dark");const m=document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');m&&m.setAttribute("content","black-translucent");const d=document.querySelector('meta[name="theme-color"]');d&&d.setAttribute("content","#0c1117")}else{document.documentElement.classList.remove("dark"),localStorage.setItem("theme","light");const m=document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');m&&m.setAttribute("content","default");const d=document.querySelector('meta[name="theme-color"]');d&&d.setAttribute("content","#ffffff")}},[o]),n.useEffect(()=>{if(!window.matchMedia)return;const m=window.matchMedia("(prefers-color-scheme: dark)"),d=s=>{localStorage.getItem("theme")||c(s.matches)};return m.addEventListener("change",d),()=>m.removeEventListener("change",d)},[]);const l={isDarkMode:o,toggleDarkMode:()=>{c(m=>!m)}};return e.jsx(Ts.Provider,{value:l,children:r})},zc=["Bash(git log:*)","Bash(git diff:*)","Bash(git status:*)","Write","Read","Edit","Glob","Grep","MultiEdit","Task","TodoWrite","TodoRead","WebFetch","WebSearch"];function Rc({skipPermissions:r,setSkipPermissions:o,allowedTools:c,setAllowedTools:u,disallowedTools:l,setDisallowedTools:m,newAllowedTool:d,setNewAllowedTool:s,newDisallowedTool:p,setNewDisallowedTool:t}){const x=y=>{y&&!c.includes(y)&&(u([...c,y]),s(""))},h=y=>{u(c.filter(j=>j!==y))},a=y=>{y&&!l.includes(y)&&(m([...l,y]),t(""))},i=y=>{m(l.filter(j=>j!==y))};return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"bg-sky-50 dark:bg-sky-900/20 border border-sky-200 dark:border-sky-800 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Qr,{className:"w-5 h-5 text-sky-500 flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"text-sm text-sky-800 dark:text-sky-200",children:[e.jsx("span",{className:"font-medium",children:"提示:"}),"此权限设置仅对 ",e.jsx("span",{className:"font-medium",children:"Chat(聊天)"})," 生效,对 ",e.jsx("span",{className:"font-medium",children:"Shell(终端)"})," 无效。Shell 是直接的系统终端,不受此权限控制。"]})]})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Wt,{className:"w-5 h-5 text-orange-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"权限设置"})]}),e.jsx("div",{className:"bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 rounded-lg p-4",children:e.jsxs("label",{className:"flex items-center gap-3",children:[e.jsx("input",{type:"checkbox",checked:r,onChange:y=>o(y.target.checked),className:"w-4 h-4 text-blue-600 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 rounded focus:ring-blue-500 focus:ring-2"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-orange-900 dark:text-orange-100",children:"跳过权限提示(请谨慎使用)"}),e.jsx("div",{className:"text-sm text-orange-700 dark:text-orange-300",children:"等同于 --dangerously-skip-permissions 标志"})]})]})})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Ft,{className:"w-5 h-5 text-green-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"允许的工具"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"自动允许而不提示权限的工具"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(at,{value:d,onChange:y=>s(y.target.value),placeholder:'e.g., "Bash(git log:*)" or "Write"',onKeyPress:y=>{y.key==="Enter"&&(y.preventDefault(),x(d))},className:"flex-1 h-10"}),e.jsxs(B,{onClick:()=>x(d),disabled:!d,size:"sm",className:"h-10 px-4",children:[e.jsx(_t,{className:"w-4 h-4 mr-2 sm:mr-0"}),e.jsx("span",{className:"sm:hidden",children:"添加"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:"快速添加常用工具:"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:zc.map(y=>e.jsx(B,{variant:"outline",size:"sm",onClick:()=>x(y),disabled:c.includes(y),className:"text-xs h-8",children:y},y))})]}),e.jsxs("div",{className:"space-y-2",children:[c.map(y=>e.jsxs("div",{className:"flex items-center justify-between bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3",children:[e.jsx("span",{className:"font-mono text-sm text-green-800 dark:text-green-200",children:y}),e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>h(y),className:"text-green-600 hover:text-green-700",children:e.jsx(Ue,{className:"w-4 h-4"})})]},y)),c.length===0&&e.jsx("div",{className:"text-center py-6 text-gray-500 dark:text-gray-400",children:"未配置允许的工具"})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Wt,{className:"w-5 h-5 text-red-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"阻止的工具"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"自动阻止而不提示权限的工具"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(at,{value:p,onChange:y=>t(y.target.value),placeholder:'e.g., "Bash(rm:*)"',onKeyPress:y=>{y.key==="Enter"&&(y.preventDefault(),a(p))},className:"flex-1 h-10"}),e.jsxs(B,{onClick:()=>a(p),disabled:!p,size:"sm",className:"h-10 px-4",children:[e.jsx(_t,{className:"w-4 h-4 mr-2 sm:mr-0"}),e.jsx("span",{className:"sm:hidden",children:"添加"})]})]}),e.jsxs("div",{className:"space-y-2",children:[l.map(y=>e.jsxs("div",{className:"flex items-center justify-between bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3",children:[e.jsx("span",{className:"font-mono text-sm text-red-800 dark:text-red-200",children:y}),e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>i(y),className:"text-red-600 hover:text-red-700",children:e.jsx(Ue,{className:"w-4 h-4"})})]},y)),l.length===0&&e.jsx("div",{className:"text-center py-6 text-gray-500 dark:text-gray-400",children:"未配置阻止的工具"})]})]}),e.jsxs("div",{className:"bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4",children:[e.jsx("h4",{className:"font-medium text-blue-900 dark:text-blue-100 mb-2",children:"工具模式示例:"}),e.jsxs("ul",{className:"text-sm text-blue-800 dark:text-blue-200 space-y-1",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(git log:*)"'})," - 允许所有 git log 命令"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(git diff:*)"'})," - 允许所有 git diff 命令"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Write"'})," - 允许所有 Write 工具使用"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:'"Bash(rm:*)"'})," - 阻止所有 rm 命令(危险)"]})]})]})]})}function $c({permissionMode:r,setPermissionMode:o}){return e.jsx("div",{className:"space-y-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Ft,{className:"w-5 h-5 text-green-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"权限模式"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"控制 Codex 如何处理文件修改和命令执行"}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="default"?"bg-gray-100 dark:bg-gray-800 border-gray-400 dark:border-gray-500":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("default"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="default",onChange:()=>o("default"),className:"mt-1 w-4 h-4 text-green-600"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-foreground",children:"默认"}),e.jsx("div",{className:"text-sm text-muted-foreground",children:"仅受信任的命令(ls、cat、grep、git status 等)会自动运行。其他命令将被跳过。可以写入工作区。"})]})]})}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="acceptEdits"?"bg-green-50 dark:bg-green-900/20 border-green-400 dark:border-green-600":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("acceptEdits"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="acceptEdits",onChange:()=>o("acceptEdits"),className:"mt-1 w-4 h-4 text-green-600"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-green-900 dark:text-green-100",children:"接受编辑"}),e.jsx("div",{className:"text-sm text-green-700 dark:text-green-300",children:"所有命令在工作区内自动运行。沙盒执行的完全自动模式。"})]})]})}),e.jsx("div",{className:`border rounded-lg p-4 cursor-pointer transition-all ${r==="bypassPermissions"?"bg-orange-50 dark:bg-orange-900/20 border-orange-400 dark:border-orange-600":"bg-gray-50 dark:bg-gray-900/50 border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600"}`,onClick:()=>o("bypassPermissions"),children:e.jsxs("label",{className:"flex items-start gap-3 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"codexPermissionMode",checked:r==="bypassPermissions",onChange:()=>o("bypassPermissions"),className:"mt-1 w-4 h-4 text-orange-600"}),e.jsxs("div",{children:[e.jsxs("div",{className:"font-medium text-orange-900 dark:text-orange-100 flex items-center gap-2",children:["跳过权限",e.jsx(Wt,{className:"w-4 h-4"})]}),e.jsx("div",{className:"text-sm text-orange-700 dark:text-orange-300",children:"无限制的完全系统访问。所有命令自动运行,具有完全的磁盘和网络访问权限。请谨慎使用。"})]})]})}),e.jsxs("details",{className:"text-sm",children:[e.jsx("summary",{className:"cursor-pointer text-muted-foreground hover:text-foreground",children:"技术详情"}),e.jsxs("div",{className:"mt-2 p-3 bg-gray-50 dark:bg-gray-900/50 rounded-lg text-xs text-muted-foreground space-y-2",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Default:"})," sandboxMode=workspace-write, approvalPolicy=untrusted. Trusted commands: cat, cd, grep, head, ls, pwd, tail, git status/log/diff/show, find (without -exec), etc."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Accept Edits:"})," sandboxMode=workspace-write, approvalPolicy=never. All commands auto-execute within project directory."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Bypass Permissions:"})," sandboxMode=danger-full-access, approvalPolicy=never. Full system access, use only in trusted environments."]}),e.jsx("p",{className:"text-xs opacity-75",children:"您可以在聊天界面中使用模式按钮为每个会话覆盖此设置。"})]})]})]})})}function Wc({agent:r,...o}){return r==="claude"?e.jsx(Rc,{...o}):r==="codex"?e.jsx($c,{...o}):null}const Hc=r=>{switch(r){case"stdio":return e.jsx(Fn,{className:"w-4 h-4"});case"sse":return e.jsx(Or,{className:"w-4 h-4"});case"http":return e.jsx(lr,{className:"w-4 h-4"});default:return e.jsx(en,{className:"w-4 h-4"})}};function Fc({servers:r,onAdd:o,onEdit:c,onDelete:u,testResults:l,serverTools:m,onDiscoverRepo:d}){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(en,{className:"w-5 h-5 text-purple-500"}),e.jsx("h3",{className:"text-lg font-medium text-foreground",children:"MCP 服务器"})]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Model Context Protocol 服务器为 ",et," 提供额外的工具和数据源"]}),e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs(B,{onClick:o,className:"bg-purple-600 hover:bg-purple-700 text-white",size:"sm",children:[e.jsx(_t,{className:"w-4 h-4 mr-2"}),"添加 MCP 服务器"]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs(B,{onClick:d,variant:"outline",size:"sm",children:[e.jsx(tn,{className:"w-4 h-4 mr-2"}),"MCP 商店"]})})]}),e.jsxs("div",{className:"space-y-2",children:[r.map(s=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[Hc(s.type),e.jsx("span",{className:"font-medium text-foreground",children:s.name}),e.jsx(tt,{variant:"outline",className:"text-xs",children:s.type}),e.jsx(tt,{variant:"outline",className:"text-xs",title:s.scope==="local"&&s.projectPath?s.projectPath:void 0,children:s.scope==="local"?`local${s.projectPath?` · ${s.projectPath.split("/").filter(Boolean).pop()}`:""}`:s.scope==="user"?"user":s.scope})]}),e.jsxs("div",{className:"text-sm text-muted-foreground space-y-1",children:[s.type==="stdio"&&s.config?.command&&e.jsxs("div",{children:["命令:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.command})]}),(s.type==="sse"||s.type==="http")&&s.config?.url&&e.jsxs("div",{children:["URL:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.url})]}),s.config?.args&&s.config.args.length>0&&e.jsxs("div",{children:["参数:",e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-1 rounded text-xs",children:s.config.args.join(" ")})]})]}),l?.[s.id]&&e.jsx("div",{className:`mt-2 p-2 rounded text-xs ${l[s.id].success?"bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200":"bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200"}`,children:e.jsx("div",{className:"font-medium",children:l[s.id].message})}),m?.[s.id]&&m[s.id].tools?.length>0&&e.jsxs("div",{className:"mt-2 p-2 rounded text-xs bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200",children:[e.jsxs("div",{className:"font-medium",children:["工具(",m[s.id].tools.length,"):"]}),e.jsxs("div",{className:"flex flex-wrap gap-1 mt-1",children:[m[s.id].tools.slice(0,5).map((p,t)=>e.jsx("code",{className:"bg-blue-100 dark:bg-blue-800 px-1 rounded",children:p.name},t)),m[s.id].tools.length>5&&e.jsxs("span",{className:"text-xs opacity-75",children:["+",m[s.id].tools.length-5," 更多"]})]})]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-4",children:[e.jsx(B,{onClick:()=>c(s),variant:"ghost",size:"sm",className:"text-gray-600 hover:text-gray-700",title:"编辑服务器",children:e.jsx(On,{className:"w-4 h-4"})}),e.jsx(B,{onClick:()=>u(s.id,s.scope,s.projectPath),variant:"ghost",size:"sm",className:"text-red-600 hover:text-red-700",title:"删除服务器",children:e.jsx(xt,{className:"w-4 h-4"})})]})]})},`${s.scope}:${s.projectPath||""}:${s.id}`)),r.length===0&&e.jsx("div",{className:"text-center py-8 text-gray-500 dark:text-gray-400",children:"未配置 MCP 服务器"})]})]})}function Bc(r){return e.jsx(Fc,{...r})}const Uc=[{key:"ANTHROPIC_DEFAULT_OPUS_MODEL",label:"Opus 模型",placeholder:"例如: claude-opus-4-6",description:"覆盖 opus 别名使用的模型,Plan Mode 激活时也用于 opusplan"},{key:"ANTHROPIC_DEFAULT_SONNET_MODEL",label:"Sonnet 模型",placeholder:"例如: claude-sonnet-4-5-20250929",description:"覆盖 sonnet 别名使用的模型,Plan Mode 未激活时也用于 opusplan"},{key:"ANTHROPIC_DEFAULT_HAIKU_MODEL",label:"Haiku 模型",placeholder:"例如: claude-haiku-4-5-20251001",description:"覆盖 haiku 别名使用的模型,也用于后台功能"},{key:"CLAUDE_CODE_SUBAGENT_MODEL",label:"Subagent 模型",placeholder:"例如: claude-haiku-4-5-20251001",description:"覆盖子代理(subagents)使用的模型"}],Gc=n.forwardRef(function({onStatusChange:o},c){const[u,l]=n.useState({}),[m,d]=n.useState({}),[s,p]=n.useState(!0),[t,x]=n.useState(!1),[h,a]=n.useState(null),[i,y]=n.useState(null),j=JSON.stringify(u)!==JSON.stringify(m);n.useEffect(()=>{o?.({saving:t,hasChanges:j})},[t,j,o]),n.useEffect(()=>{w()},[]),n.useEffect(()=>{if(h){const f=setTimeout(()=>a(null),3e3);return()=>clearTimeout(f)}},[h]);const w=async()=>{try{p(!0),y(null);const f=await Y("/api/settings/models");if(f.ok){const N=await f.json();l(N.models||{}),d(N.models||{})}else{const N=await f.json();y(N.error||"加载模型配置失败")}}catch(f){y(f.message)}finally{p(!1)}},b=async()=>{try{x(!0),a(null);const f=await Y("/api/settings/models",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({models:u})});if(f.ok)return a("success"),d({...u}),!0;{const N=await f.json();return a("error"),y(N.error||"保存失败"),!1}}catch(f){return a("error"),y(f.message),!1}finally{x(!1)}},k=()=>{l({...m}),a(null)};return n.useImperativeHandle(c,()=>({save:b,reset:k,get hasChanges(){return j},get saving(){return t}}),[j,t,u,m]),s?e.jsxs("div",{className:"flex items-center justify-center py-12",children:[e.jsx("div",{className:"animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500"}),e.jsx("span",{className:"ml-3 text-sm text-muted-foreground",children:"加载模型配置..."})]}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-start gap-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3",children:[e.jsx(Qr,{className:"w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0"}),e.jsxs("div",{className:"text-sm text-blue-700 dark:text-blue-300",children:[e.jsxs("p",{children:["自定义模型 ID 来覆盖 ",et," 和 Claude Code 使用的默认模型。留空表示使用默认模型。"]}),e.jsx("p",{className:"mt-1 text-blue-600 dark:text-blue-400",children:"非 Claude 模型将按 Sonnet 定价计费,但统计中会记录实际模型 ID。"})]})]}),i&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3 text-sm text-red-600 dark:text-red-400",children:i}),h==="success"&&e.jsx("div",{className:"bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3 text-sm text-green-600 dark:text-green-400",children:"模型配置已保存"}),Uc.map(f=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{children:[e.jsx("label",{className:"font-medium text-sm text-foreground",children:f.label}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:f.description})]}),e.jsx("input",{type:"text",value:u[f.key]||"",onChange:N=>l(S=>({...S,[f.key]:N.target.value})),placeholder:f.placeholder,className:"w-full text-sm bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-900 dark:text-gray-100 rounded-lg focus:ring-blue-500 focus:border-blue-500 px-3 py-2"}),e.jsx("p",{className:"text-xs text-muted-foreground font-mono",children:f.key})]})},f.key))]})});function Yc({onClose:r,onInstalled:o,onOpenRepoManager:c,projects:u=[]}){const{showAlert:l}=it(),[m,d]=n.useState([]),[s,p]=n.useState([]),[t,x]=n.useState(!0),[h,a]=n.useState(null),[i,y]=n.useState(""),[j,w]=n.useState("all"),[b,k]=n.useState(null),[f,N]=n.useState(null),[S,I]=n.useState("user"),[D,T]=n.useState("");n.useEffect(()=>{R()},[]);const R=async(C=!1)=>{try{x(!0),a(null),C&&await Y("/api/skills/repos/refresh",{method:"POST"});const[$,te]=await Promise.all([Y("/api/skills/available"),Y("/api/skills/repos")]);if($.ok){const ne=await $.json();d(ne.skills||[])}if(te.ok){const ne=await te.json();p(ne.repos||[])}}catch($){a($.message)}finally{x(!1)}},M=C=>{N(C),I("user"),T("")},E=()=>{N(null),I("user"),T("")},W=async()=>{const C=f;if(C){if(S==="local"&&!D){l("请选择要安装到的项目",{variant:"warning"});return}try{N(null),k(C.name);const $={skillPath:C.path};S==="local"&&D&&($.projectPath=D);const te=await Y(`/api/skills/install/${C.name}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify($)});if(te.ok)d(ne=>ne.map(G=>G.name===C.name?{...G,installed:!0}:G)),o?.();else{const ne=await te.json();l(ne.error||"安装技能失败",{variant:"error"})}}catch($){l($.message,{variant:"error"})}finally{k(null),I("user"),T("")}}},X=m.filter(C=>{if(i){const $=i.toLowerCase();if(!C.name.toLowerCase().includes($)&&!C.title?.toLowerCase().includes($)&&!C.description?.toLowerCase().includes($))return!1}return!(j!=="all"&&C.repository!==j)});return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-background rounded-xl shadow-xl w-full max-w-4xl max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-border",children:[e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:"Skills 管理"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(B,{variant:"ghost",size:"sm",onClick:()=>R(!0),disabled:t,children:[e.jsx(st,{className:`w-4 h-4 ${t?"animate-spin":""}`}),e.jsx("span",{className:"ml-1 hidden sm:inline",children:"刷新"})]}),e.jsxs(B,{variant:"ghost",size:"sm",onClick:c,children:[e.jsx(Ht,{className:"w-4 h-4"}),e.jsx("span",{className:"ml-1 hidden sm:inline",children:"仓库管理"})]}),e.jsx(B,{variant:"ghost",size:"icon",onClick:r,children:e.jsx(Ue,{className:"w-5 h-5"})})]})]}),e.jsx("div",{className:"px-4 pt-4 pb-2"}),e.jsxs("div",{className:"px-4 pb-4 flex flex-wrap gap-3",children:[e.jsx("div",{className:"flex-1 min-w-[200px]",children:e.jsxs("div",{className:"relative",children:[e.jsx(St,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(at,{type:"text",placeholder:"搜索技能名称或描述...",value:i,onChange:C=>y(C.target.value),className:"pl-10"})]})}),e.jsxs("select",{value:j,onChange:C=>w(C.target.value),className:"px-3 py-2 rounded-md border border-border bg-background text-foreground text-sm min-w-[120px]",children:[e.jsx("option",{value:"all",children:"全部"}),s.map(C=>e.jsxs("option",{value:`${C.owner}/${C.repo}`,children:[C.owner,"/",C.repo]},`${C.owner}/${C.repo}`))]})]}),e.jsxs("div",{className:"flex-1 overflow-auto px-4 pb-4",children:[h&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 text-red-800 dark:text-red-200 text-sm mb-4",children:h}),t?e.jsx("div",{className:"text-center py-8 text-muted-foreground",children:"加载中..."}):X.length===0?e.jsx("div",{className:"text-center py-8 text-muted-foreground",children:m.length===0?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"没有可用的技能"}),e.jsx("p",{className:"text-xs mt-2",children:"请先添加技能仓库"}),e.jsxs(B,{variant:"outline",size:"sm",className:"mt-4",onClick:c,children:[e.jsx(Ht,{className:"w-4 h-4 mr-2"}),"管理仓库"]})]}):e.jsx("p",{children:"没有找到匹配的技能"})}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:X.map(C=>{const $=b===C.name,te=f?.name===C.name;return e.jsx("div",{className:"border border-border rounded-lg p-4 hover:border-amber-500/50 transition-colors",children:e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"mb-2",children:[e.jsx("h4",{className:"font-medium text-foreground",children:C.title||C.name}),e.jsxs("div",{className:"flex items-center gap-1 mt-1",children:[e.jsxs("span",{className:"text-xs text-muted-foreground",children:["skills/",C.name]}),e.jsx(tt,{variant:"outline",className:"text-xs ml-2",children:C.repository})]})]}),C.description&&e.jsx("p",{className:"text-sm text-muted-foreground flex-1 line-clamp-3 mb-3",children:C.description}),te&&e.jsxs("div",{className:"mt-2 mb-3 p-3 rounded-lg bg-muted/50 border border-border text-sm",children:[e.jsx("p",{className:"font-medium text-foreground mb-2",children:"选择安装位置"}),e.jsxs("label",{className:"flex items-center gap-2 mb-1 cursor-pointer",children:[e.jsx("input",{type:"radio",name:`scope-${C.name}`,value:"user",checked:S==="user",onChange:()=>{I("user"),T("")},className:"accent-amber-600"}),e.jsx("span",{className:"text-foreground",children:"全局(所有项目可用)"})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"radio",name:`scope-${C.name}`,value:"local",checked:S==="local",onChange:()=>I("local"),className:"accent-amber-600"}),e.jsx("span",{className:"text-foreground",children:"安装到指定项目"})]}),S==="local"&&e.jsxs("select",{value:D,onChange:ne=>T(ne.target.value),className:"mt-2 w-full px-2 py-1.5 rounded-md border border-border bg-background text-foreground text-xs",children:[e.jsx("option",{value:"",children:"选择项目..."}),u.map(ne=>e.jsx("option",{value:ne.path||ne.fullPath,children:ne.displayName||ne.name},ne.name))]}),e.jsxs("div",{className:"flex gap-2 mt-3",children:[e.jsx(B,{size:"sm",variant:"outline",onClick:E,className:"flex-1",children:"取消"}),e.jsx(B,{size:"sm",className:"bg-amber-600 hover:bg-amber-700 text-white flex-1",onClick:W,children:"确认安装"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-auto pt-2",children:[e.jsxs(B,{variant:"ghost",size:"sm",onClick:()=>window.open(`https://github.com/${C.repository}`,"_blank"),children:[e.jsx(Vo,{className:"w-4 h-4 mr-1"}),"查看"]}),C.installed?e.jsx(B,{size:"sm",disabled:!0,variant:"outline",className:"ml-auto",children:"已安装"}):!te&&e.jsxs(B,{size:"sm",className:"bg-amber-600 hover:bg-amber-700 text-white ml-auto",onClick:()=>M(C),disabled:$||!!f,children:[e.jsx(It,{className:"w-4 h-4 mr-1"}),$?"安装中...":"安装"]})]})]})},`${C.repository}-${C.name}`)})})]})]})})}function Jc({onClose:r,onChanged:o}){const{showAlert:c,showConfirm:u}=it(),[l,m]=n.useState([]),[d,s]=n.useState(!0),[p,t]=n.useState(null),[x,h]=n.useState(""),[a,i]=n.useState("main"),[y,j]=n.useState(!1),[w,b]=n.useState(null);n.useEffect(()=>{k()},[]);const k=async()=>{try{s(!0),t(null);const S=await Y("/api/skills/repos");if(S.ok){const I=await S.json();m(I.repos||[])}else{const I=await S.json();t(I.error||"Failed to fetch repos")}}catch(S){t(S.message)}finally{s(!1)}},f=async S=>{if(S.preventDefault(),!x.trim()){t("请输入仓库 URL");return}try{j(!0),t(null);const I=await Y("/api/skills/repos",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:x.trim(),branch:a.trim()||"main"})});if(I.ok)h(""),i("main"),k(),o?.();else{const D=await I.json();t(D.error||"Failed to add repo")}}catch(I){t(I.message)}finally{j(!1)}},N=async(S,I)=>{if(await u(`确定要移除仓库 "${S}/${I}" 吗?`,{title:"移除仓库",variant:"danger",confirmText:"确认移除"}))try{b(`${S}/${I}`);const D=await Y(`/api/skills/repos/${S}/${I}`,{method:"DELETE"});if(D.ok)k(),o?.();else{const T=await D.json();c(T.error||"移除仓库失败",{variant:"error"})}}catch(D){c(D.message,{variant:"error"})}finally{b(null)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-background rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"flex items-center gap-3 p-4 border-b border-border",children:[e.jsx(B,{variant:"ghost",size:"icon",onClick:r,children:e.jsx(er,{className:"w-5 h-5"})}),e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:"管理技能仓库"})]}),e.jsxs("div",{className:"flex-1 overflow-auto p-4 space-y-6",children:[e.jsxs("div",{className:"bg-gray-50 dark:bg-gray-900/50 rounded-lg p-4 space-y-4",children:[e.jsx("h3",{className:"font-medium text-foreground",children:"添加技能仓库"}),e.jsxs("form",{onSubmit:f,className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm text-muted-foreground mb-1",children:"仓库 URL"}),e.jsx(at,{type:"text",placeholder:"owner/name 或 https://github.com/owner/name",value:x,onChange:S=>h(S.target.value),disabled:y})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm text-muted-foreground mb-1",children:"分支"}),e.jsx(at,{type:"text",placeholder:"main",value:a,onChange:S=>i(S.target.value),disabled:y})]}),e.jsxs(B,{type:"submit",disabled:y||!x.trim(),className:"bg-amber-600 hover:bg-amber-700 text-white",children:[e.jsx(_t,{className:"w-4 h-4 mr-2"}),y?"添加中...":"添加仓库"]})]})]}),p&&e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 text-red-800 dark:text-red-200 text-sm",children:p}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h3",{className:"font-medium text-foreground",children:"已添加的仓库"}),d?e.jsx("div",{className:"text-center py-4 text-muted-foreground",children:"加载中..."}):l.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Zo,{className:"w-12 h-12 mx-auto mb-4 opacity-50"}),e.jsx("p",{children:"还没有添加任何仓库"})]}):l.map(S=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"font-medium text-foreground",children:[S.owner,"/",S.repo]}),S.isSystem&&e.jsx(tt,{variant:"outline",className:"text-xs bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-300",children:"内置"})]}),e.jsxs("div",{className:"flex items-center gap-3 mt-1 text-sm text-muted-foreground",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(tn,{className:"w-3 h-3"}),"分支: main"]}),e.jsxs(tt,{variant:"outline",className:"text-xs",children:["识别到 ",S.skillCount," 个技能"]})]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-4",children:[!S.isSystem&&S.url&&e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>window.open(S.url,"_blank"),children:e.jsx(Vo,{className:"w-4 h-4"})}),!S.isSystem&&e.jsx(B,{variant:"ghost",size:"sm",onClick:()=>N(S.owner,S.repo),disabled:w===`${S.owner}/${S.repo}`,className:"text-red-500 hover:text-red-600",children:e.jsx(xt,{className:"w-4 h-4"})})]})]})},`${S.owner}/${S.repo}`))]})]})]})})}function qc({projects:r=[]}){const{showAlert:o,showConfirm:c}=it(),[u,l]=n.useState([]),[m,d]=n.useState(!0),[s,p]=n.useState(null),[t,x]=n.useState(!1),[h,a]=n.useState(!1),[i,y]=n.useState(!1),[j,w]=n.useState(null),b=n.useRef(null);n.useEffect(()=>{k()},[]);const k=async()=>{try{d(!0),p(null);const M=await Y("/api/skills");if(M.ok){const E=await M.json();l(E.skills||[])}else{const E=await M.json();p(E.error||"Failed to fetch skills")}}catch(M){p(M.message)}finally{d(!1)}},f=async()=>{try{const M=await Y("/api/skills");if(M.ok){const E=await M.json();l(E.skills||[])}}catch{}},N=async M=>{try{const E=await Y(`/api/skills/${M}/download`);if(!E.ok){const $=await E.json();o($.error||"下载技能失败",{variant:"error"});return}const W=await E.blob(),X=URL.createObjectURL(W),C=document.createElement("a");C.href=X,C.download=`${M}.zip`,C.click(),URL.revokeObjectURL(X)}catch(E){o(E.message,{variant:"error"})}},S=async M=>{if(await c(`确定要删除技能 "${M.name}" 吗?`,{title:"删除技能",variant:"danger",confirmText:"确认删除"}))try{const E=M.projectPath?`/api/skills/${M.name}?projectPath=${encodeURIComponent(M.projectPath)}`:`/api/skills/${M.name}`,W=await Y(E,{method:"DELETE"});if(W.ok)k();else{const X=await W.json();o(X.error||"删除技能失败",{variant:"error"})}}catch(E){o(E.message,{variant:"error"})}},I=async M=>{let E,W;if(M.syncType==="builtin"?(W="同步修改到云端",E=`确定要将技能 "${M.name}" 的本地修改推送到共享仓库吗?
|
|
155
155
|
|
|
156
156
|
这会把你在本地对该技能所做的修改同步到公司的共享 Git 仓库,其他用户拉取更新后即可获得最新版本。`):M.syncType==="external"?(W="迁移技能到共享仓库",E=`确定要将技能 "${M.name}" 迁移到公司共享仓库吗?
|
|
157
157
|
|
package/dist/index.html
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
<!-- Prevent zoom on iOS -->
|
|
27
27
|
<meta name="format-detection" content="telephone=no" />
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-C1nCVxE_.js"></script>
|
|
29
29
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-Bv0Nkan8.js">
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-sVRjxPVQ.js">
|
|
31
31
|
<link rel="modulepreload" crossorigin href="/assets/vendor-utils-00TdZexr.js">
|
package/package.json
CHANGED
package/server/routes/agents.js
CHANGED
|
@@ -654,7 +654,55 @@ async function installMcp(mcpName, repoUrl, userUuid, projectPath) {
|
|
|
654
654
|
}
|
|
655
655
|
|
|
656
656
|
await fs.writeFile(claudeJsonPath, JSON.stringify(claudeConfig, null, 2), 'utf-8');
|
|
657
|
-
|
|
657
|
+
// Return the server keys that were written, so callers can track them for later removal
|
|
658
|
+
return { success: true, keys: Object.keys(mcpJson) };
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Uninstall a single MCP server by removing its keys from .claude.json.
|
|
663
|
+
* `installedKeys` are the server key names that were written during install.
|
|
664
|
+
*/
|
|
665
|
+
async function uninstallMcp(installedKeys, userUuid, projectPath) {
|
|
666
|
+
if (!installedKeys?.length) return;
|
|
667
|
+
const userPaths = getUserPaths(userUuid);
|
|
668
|
+
const claudeJsonPath = path.join(userPaths.claudeDir, '.claude.json');
|
|
669
|
+
let claudeConfig = {};
|
|
670
|
+
try {
|
|
671
|
+
claudeConfig = JSON.parse(await fs.readFile(claudeJsonPath, 'utf-8'));
|
|
672
|
+
} catch {
|
|
673
|
+
return; // Nothing to remove
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
let changed = false;
|
|
677
|
+
if (projectPath) {
|
|
678
|
+
const mcpServers = claudeConfig.projects?.[projectPath]?.mcpServers;
|
|
679
|
+
if (mcpServers) {
|
|
680
|
+
for (const key of installedKeys) {
|
|
681
|
+
if (key in mcpServers) { delete mcpServers[key]; changed = true; }
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
if (claudeConfig.mcpServers) {
|
|
686
|
+
for (const key of installedKeys) {
|
|
687
|
+
if (key in claudeConfig.mcpServers) { delete claudeConfig.mcpServers[key]; changed = true; }
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (changed) {
|
|
693
|
+
await fs.writeFile(claudeJsonPath, JSON.stringify(claudeConfig, null, 2), 'utf-8');
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Uninstall a single skill by removing its symlink.
|
|
699
|
+
*/
|
|
700
|
+
async function uninstallSkill(skillName, userUuid, projectPath) {
|
|
701
|
+
const userPaths = getUserPaths(userUuid);
|
|
702
|
+
const linkPath = projectPath
|
|
703
|
+
? path.join(projectPath, '.claude', 'skills', skillName)
|
|
704
|
+
: path.join(userPaths.skillsDir, skillName);
|
|
705
|
+
try { await fs.unlink(linkPath); } catch {}
|
|
658
706
|
}
|
|
659
707
|
|
|
660
708
|
// ─── Routes ──────────────────────────────────────────────────────────────────
|
|
@@ -813,13 +861,80 @@ router.post('/install', async (req, res) => {
|
|
|
813
861
|
console.error('[AgentInstall] Failed to copy agent files:', err.message);
|
|
814
862
|
}
|
|
815
863
|
|
|
864
|
+
// Load existing agentInfo to perform diff-based uninstall of removed skills/MCPs
|
|
865
|
+
const prevConfig = await loadProjectConfig(userUuid);
|
|
866
|
+
const prevKey = projectDir.replace(/\//g, '-');
|
|
867
|
+
const prevAgentInfo = prevConfig[prevKey]?.agentInfo;
|
|
868
|
+
|
|
869
|
+
// Remove skills that existed in old version but are no longer in new version
|
|
870
|
+
const newSkillNames = new Set((agent.skills || []).filter(s => s.name).map(s => s.name));
|
|
871
|
+
if (prevAgentInfo?.installedSkills?.length > 0) {
|
|
872
|
+
// Precise diff using recorded data
|
|
873
|
+
for (const old of prevAgentInfo.installedSkills) {
|
|
874
|
+
if (!newSkillNames.has(old.name)) {
|
|
875
|
+
try {
|
|
876
|
+
await uninstallSkill(old.name, userUuid, projectDir);
|
|
877
|
+
console.log(`[AgentInstall] Removed old skill "${old.name}" (no longer in agent)`);
|
|
878
|
+
} catch (e) {
|
|
879
|
+
console.warn(`[AgentInstall] Could not remove old skill "${old.name}":`, e.message);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
} else if (prevAgentInfo) {
|
|
884
|
+
// No recorded data — fallback: scan actual skills dir and remove anything not in new agent
|
|
885
|
+
try {
|
|
886
|
+
const skillsDir = path.join(projectDir, '.claude', 'skills');
|
|
887
|
+
const entries = await fs.readdir(skillsDir).catch(() => []);
|
|
888
|
+
for (const name of entries) {
|
|
889
|
+
if (!newSkillNames.has(name)) {
|
|
890
|
+
try {
|
|
891
|
+
await fs.unlink(path.join(skillsDir, name));
|
|
892
|
+
console.log(`[AgentInstall] Removed residual skill "${name}" (fallback cleanup)`);
|
|
893
|
+
} catch (e) {
|
|
894
|
+
console.warn(`[AgentInstall] Could not remove residual skill "${name}":`, e.message);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
} catch {}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// Remove MCPs that existed in old version but are no longer in new version
|
|
902
|
+
const newMcpNames = new Set((agent.mcps || []).filter(m => m.name).map(m => m.name));
|
|
903
|
+
if (prevAgentInfo?.installedMcps?.length > 0) {
|
|
904
|
+
// Precise diff using recorded data (includes exact server keys)
|
|
905
|
+
for (const old of prevAgentInfo.installedMcps) {
|
|
906
|
+
if (!newMcpNames.has(old.name)) {
|
|
907
|
+
try {
|
|
908
|
+
await uninstallMcp(old.keys, userUuid, projectDir);
|
|
909
|
+
console.log(`[AgentInstall] Removed old MCP "${old.name}" (no longer in agent)`);
|
|
910
|
+
} catch (e) {
|
|
911
|
+
console.warn(`[AgentInstall] Could not remove old MCP "${old.name}":`, e.message);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
} else if (prevAgentInfo) {
|
|
916
|
+
// No recorded data — fallback: remove ALL project-scoped MCP keys (will be reinstalled)
|
|
917
|
+
try {
|
|
918
|
+
const userPaths = getUserPaths(userUuid);
|
|
919
|
+
const claudeJsonPath = path.join(userPaths.claudeDir, '.claude.json');
|
|
920
|
+
const claudeConfig = JSON.parse(await fs.readFile(claudeJsonPath, 'utf-8'));
|
|
921
|
+
const projectMcpKeys = Object.keys(claudeConfig.projects?.[projectDir]?.mcpServers || {});
|
|
922
|
+
if (projectMcpKeys.length > 0) {
|
|
923
|
+
await uninstallMcp(projectMcpKeys, userUuid, projectDir);
|
|
924
|
+
console.log(`[AgentInstall] Removed ${projectMcpKeys.length} residual project MCPs (fallback cleanup)`);
|
|
925
|
+
}
|
|
926
|
+
} catch {}
|
|
927
|
+
}
|
|
928
|
+
|
|
816
929
|
// Install skills
|
|
817
930
|
const skillResults = [];
|
|
931
|
+
const installedSkills = [];
|
|
818
932
|
for (const skill of agent.skills || []) {
|
|
819
933
|
if (!skill.name || !skill.repo) continue;
|
|
820
934
|
try {
|
|
821
935
|
const ok = await installSkill(skill.name, skill.repo, userUuid, projectDir);
|
|
822
936
|
skillResults.push({ name: skill.name, success: ok });
|
|
937
|
+
if (ok) installedSkills.push({ name: skill.name, repo: skill.repo });
|
|
823
938
|
} catch (err) {
|
|
824
939
|
console.error(`[AgentInstall] Failed to install skill "${skill.name}":`, err.message);
|
|
825
940
|
skillResults.push({ name: skill.name, success: false, error: err.message });
|
|
@@ -828,11 +943,13 @@ router.post('/install', async (req, res) => {
|
|
|
828
943
|
|
|
829
944
|
// Install MCPs (project-scoped to the newly created project directory)
|
|
830
945
|
const mcpResults = [];
|
|
946
|
+
const installedMcps = [];
|
|
831
947
|
for (const mcp of agent.mcps || []) {
|
|
832
948
|
if (!mcp.name || !mcp.repo) continue;
|
|
833
949
|
try {
|
|
834
|
-
const
|
|
835
|
-
mcpResults.push({ name: mcp.name, success:
|
|
950
|
+
const result = await installMcp(mcp.name, mcp.repo, userUuid, projectDir);
|
|
951
|
+
mcpResults.push({ name: mcp.name, success: result.success });
|
|
952
|
+
if (result.success) installedMcps.push({ name: mcp.name, repo: mcp.repo, keys: result.keys });
|
|
836
953
|
} catch (err) {
|
|
837
954
|
console.error(`[AgentInstall] Failed to install MCP "${mcp.name}":`, err.message);
|
|
838
955
|
mcpResults.push({ name: mcp.name, success: false, error: err.message });
|
|
@@ -865,6 +982,8 @@ router.post('/install', async (req, res) => {
|
|
|
865
982
|
isAgent: true,
|
|
866
983
|
claudeMdHash,
|
|
867
984
|
installedFiles,
|
|
985
|
+
installedSkills,
|
|
986
|
+
installedMcps,
|
|
868
987
|
gitRepos: (agent.git_repos || []).filter(g => g.name && g.repo).map(g => ({
|
|
869
988
|
name: g.name, repo: g.repo, branch: g.branch || 'main'
|
|
870
989
|
}))
|
|
@@ -1727,18 +1846,15 @@ router.post('/submissions/:id/approve', async (req, res) => {
|
|
|
1727
1846
|
entry.agentInfo.claudeMdHash = newClaudeMdHash;
|
|
1728
1847
|
entry.agentInfo.installedFiles = newInstalledFiles;
|
|
1729
1848
|
|
|
1730
|
-
// Update git repo dependencies
|
|
1731
1849
|
if (publishedAgent) {
|
|
1850
|
+
// Update git repo dependencies
|
|
1732
1851
|
const newGitRepos = (publishedAgent.git_repos || []).filter(g => g.name && g.repo);
|
|
1733
1852
|
const oldGitRepos = entry.agentInfo.gitRepos || [];
|
|
1853
|
+
const oldGitByName = new Map(oldGitRepos.map(g => [g.name, g]));
|
|
1854
|
+
const newGitByName = new Map(newGitRepos.map(g => [g.name, g]));
|
|
1734
1855
|
|
|
1735
|
-
// Build lookup maps
|
|
1736
|
-
const oldByName = new Map(oldGitRepos.map(g => [g.name, g]));
|
|
1737
|
-
const newByName = new Map(newGitRepos.map(g => [g.name, g]));
|
|
1738
|
-
|
|
1739
|
-
// Remove symlinks for deleted git repos
|
|
1740
1856
|
for (const old of oldGitRepos) {
|
|
1741
|
-
if (!
|
|
1857
|
+
if (!newGitByName.has(old.name)) {
|
|
1742
1858
|
try {
|
|
1743
1859
|
const linkPath = path.join(projectDir, old.name);
|
|
1744
1860
|
await fs.unlink(linkPath).catch(() => {});
|
|
@@ -1747,9 +1863,8 @@ router.post('/submissions/:id/approve', async (req, res) => {
|
|
|
1747
1863
|
}
|
|
1748
1864
|
}
|
|
1749
1865
|
|
|
1750
|
-
// Add/update git repos
|
|
1751
1866
|
for (const gitRepo of newGitRepos) {
|
|
1752
|
-
const old =
|
|
1867
|
+
const old = oldGitByName.get(gitRepo.name);
|
|
1753
1868
|
const branchChanged = !old || old.branch !== gitRepo.branch;
|
|
1754
1869
|
const repoChanged = !old || old.repo !== gitRepo.repo;
|
|
1755
1870
|
|
|
@@ -1762,16 +1877,101 @@ router.post('/submissions/:id/approve', async (req, res) => {
|
|
|
1762
1877
|
console.warn(`[AgentApprove] Failed to update git repo "${gitRepo.name}" for user ${user.uuid}:`, e.message);
|
|
1763
1878
|
}
|
|
1764
1879
|
} else {
|
|
1765
|
-
|
|
1766
|
-
try {
|
|
1767
|
-
await ensureSharedGitRepo(gitRepo.repo, gitRepo.branch || 'main');
|
|
1768
|
-
} catch {}
|
|
1880
|
+
try { await ensureSharedGitRepo(gitRepo.repo, gitRepo.branch || 'main'); } catch {}
|
|
1769
1881
|
}
|
|
1770
1882
|
}
|
|
1771
1883
|
|
|
1772
1884
|
entry.agentInfo.gitRepos = newGitRepos.map(g => ({
|
|
1773
1885
|
name: g.name, repo: g.repo, branch: g.branch || 'main'
|
|
1774
1886
|
}));
|
|
1887
|
+
|
|
1888
|
+
// Update skill dependencies
|
|
1889
|
+
const newSkills = (publishedAgent.skills || []).filter(s => s.name && s.repo);
|
|
1890
|
+
const oldSkills = entry.agentInfo.installedSkills;
|
|
1891
|
+
const newSkillNames = new Set(newSkills.map(s => s.name));
|
|
1892
|
+
|
|
1893
|
+
if (oldSkills?.length > 0) {
|
|
1894
|
+
// Precise diff using recorded data
|
|
1895
|
+
for (const old of oldSkills) {
|
|
1896
|
+
if (!newSkillNames.has(old.name)) {
|
|
1897
|
+
try {
|
|
1898
|
+
await uninstallSkill(old.name, user.uuid, projectDir);
|
|
1899
|
+
console.log(`[AgentApprove] Removed old skill "${old.name}" for user ${user.uuid}`);
|
|
1900
|
+
} catch (e) {
|
|
1901
|
+
console.warn(`[AgentApprove] Could not remove old skill "${old.name}" for user ${user.uuid}:`, e.message);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
} else {
|
|
1906
|
+
// No recorded data — fallback: scan actual skills dir
|
|
1907
|
+
try {
|
|
1908
|
+
const skillsDir = path.join(projectDir, '.claude', 'skills');
|
|
1909
|
+
const entries = await fs.readdir(skillsDir).catch(() => []);
|
|
1910
|
+
for (const name of entries) {
|
|
1911
|
+
if (!newSkillNames.has(name)) {
|
|
1912
|
+
try {
|
|
1913
|
+
await fs.unlink(path.join(skillsDir, name));
|
|
1914
|
+
console.log(`[AgentApprove] Removed residual skill "${name}" for user ${user.uuid} (fallback cleanup)`);
|
|
1915
|
+
} catch (e) {
|
|
1916
|
+
console.warn(`[AgentApprove] Could not remove residual skill "${name}" for user ${user.uuid}:`, e.message);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
} catch {}
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
const newInstalledSkills = [];
|
|
1924
|
+
for (const skill of newSkills) {
|
|
1925
|
+
try {
|
|
1926
|
+
const ok = await installSkill(skill.name, skill.repo, user.uuid, projectDir);
|
|
1927
|
+
if (ok) newInstalledSkills.push({ name: skill.name, repo: skill.repo });
|
|
1928
|
+
} catch (e) {
|
|
1929
|
+
console.warn(`[AgentApprove] Could not install skill "${skill.name}" for user ${user.uuid}:`, e.message);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
entry.agentInfo.installedSkills = newInstalledSkills;
|
|
1933
|
+
|
|
1934
|
+
// Update MCP dependencies
|
|
1935
|
+
const newMcps = (publishedAgent.mcps || []).filter(m => m.name && m.repo);
|
|
1936
|
+
const oldMcps = entry.agentInfo.installedMcps;
|
|
1937
|
+
const newMcpNames = new Set(newMcps.map(m => m.name));
|
|
1938
|
+
|
|
1939
|
+
if (oldMcps?.length > 0) {
|
|
1940
|
+
// Precise diff using recorded data (includes exact server keys)
|
|
1941
|
+
for (const old of oldMcps) {
|
|
1942
|
+
if (!newMcpNames.has(old.name)) {
|
|
1943
|
+
try {
|
|
1944
|
+
await uninstallMcp(old.keys, user.uuid, projectDir);
|
|
1945
|
+
console.log(`[AgentApprove] Removed old MCP "${old.name}" for user ${user.uuid}`);
|
|
1946
|
+
} catch (e) {
|
|
1947
|
+
console.warn(`[AgentApprove] Could not remove old MCP "${old.name}" for user ${user.uuid}:`, e.message);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
} else {
|
|
1952
|
+
// No recorded data — fallback: remove ALL project-scoped MCP keys (will be reinstalled)
|
|
1953
|
+
try {
|
|
1954
|
+
const userPaths = getUserPaths(user.uuid);
|
|
1955
|
+
const claudeJsonPath = path.join(userPaths.claudeDir, '.claude.json');
|
|
1956
|
+
const claudeConfig = JSON.parse(await fs.readFile(claudeJsonPath, 'utf-8'));
|
|
1957
|
+
const projectMcpKeys = Object.keys(claudeConfig.projects?.[projectDir]?.mcpServers || {});
|
|
1958
|
+
if (projectMcpKeys.length > 0) {
|
|
1959
|
+
await uninstallMcp(projectMcpKeys, user.uuid, projectDir);
|
|
1960
|
+
console.log(`[AgentApprove] Removed ${projectMcpKeys.length} residual project MCPs for user ${user.uuid} (fallback cleanup)`);
|
|
1961
|
+
}
|
|
1962
|
+
} catch {}
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
const newInstalledMcps = [];
|
|
1966
|
+
for (const mcp of newMcps) {
|
|
1967
|
+
try {
|
|
1968
|
+
const result = await installMcp(mcp.name, mcp.repo, user.uuid, projectDir);
|
|
1969
|
+
if (result.success) newInstalledMcps.push({ name: mcp.name, repo: mcp.repo, keys: result.keys });
|
|
1970
|
+
} catch (e) {
|
|
1971
|
+
console.warn(`[AgentApprove] Could not install MCP "${mcp.name}" for user ${user.uuid}:`, e.message);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
entry.agentInfo.installedMcps = newInstalledMcps;
|
|
1775
1975
|
}
|
|
1776
1976
|
|
|
1777
1977
|
userUpdated = true;
|