@ian2018cs/agenthub 0.1.88 → 0.1.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{j as e,s as ua,R as pa,o as ma,E as fa,m as ha,b as xa,c as ga,h as ya,p as ba,d as va}from"./vendor-codemirror-B2saKA4-.js";import{b as ja,g as Zr,a as n,d as Hr,R as mt,u as Qr,L as qt,e as Vo,B as ka,f as Zo,h as dr}from"./vendor-react-C_uEg43g.js";import{t as wa,c as Na,a as Qo,F as Sa}from"./vendor-utils-00TdZexr.js";import{T as Bt,C as es,I as en,F as Tr,X as Ge,L as bt,B as _t,S as Mt,R as st,D as It,a as On,b as ur,Z as Cr,c as tn,G as rn,d as Vt,e as Br,U as Ht,f as Cn,g as pr,h as Bn,i as Ta,j as Zt,k as Xr,l as yo,m as vt,P as En,n as Mr,o as Xa,p as zt,q as Ut,r as Gt,M as hn,s as Ma,t as Un,u as Oa,v as Ca,E as ts,w as Ea,x as bo,y as xn,z as Da,A as Er,H as Gn,J as mr,K as rs,N as Qt,O as ns,Q as Pa,V as Dn,W as os,Y as ss,_ as Aa,$ as La,a0 as _a,a1 as Ur,a2 as Gr,a3 as Ia,a4 as za,a5 as Pn,a6 as Ra,a7 as as,a8 as $a,a9 as Wa,aa as Fa,ab as Yn,ac as Ha,ad as Ba,ae as Ua,af as Ga,ag as Ya,ah as An,ai as Ja,aj as Yr,ak as is,al as ls,am as qa,an as Ka}from"./vendor-icons-BLTKkQIn.js";import{r as cs,a as Va,b as Za,M as ds}from"./vendor-markdown-Ok8-Lurq.js";import{h as us}from"./vendor-syntax-CEC-Nb_2.js";import{r as Qa,a as ei,b as ti,c as ri}from"./vendor-xterm-CvdiG4-n.js";import"./vendor-katex-DK8hFnhL.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const c of document.querySelectorAll('link[rel="modulepreload"]'))u(c);new MutationObserver(c=>{for(const m of c)if(m.type==="childList")for(const d of m.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&u(d)}).observe(document,{childList:!0,subtree:!0});function l(c){const m={};return c.integrity&&(m.integrity=c.integrity),c.referrerPolicy&&(m.referrerPolicy=c.referrerPolicy),c.crossOrigin==="use-credentials"?m.credentials="include":c.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function u(c){if(c.ep)return;c.ep=!0;const m=l(c);fetch(c.href,m)}})();var Rr={},vo;function ni(){if(vo)return Rr;vo=1;var r=ja();return Rr.createRoot=r.createRoot,Rr.hydrateRoot=r.hydrateRoot,Rr}var oi=ni();const si=Zr(oi);function ot(...r){return wa(Na(r))}function ai(r){if(!r||typeof r!="string")return null;try{return JSON.parse(r)}catch{return null}}const Jn=n.forwardRef(({className:r,children:o,...l},u)=>e.jsx("div",{ref:u,className:ot("relative overflow-hidden",r),...l,children:e.jsx("div",{className:"h-full w-full rounded-[inherit] overflow-auto",style:{WebkitOverflowScrolling:"touch",touchAction:"pan-y"},children:o})}));Jn.displayName="ScrollArea";const ii=Qo("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground shadow hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",outline:"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2",sm:"h-8 rounded-md px-3 text-xs",lg:"h-10 rounded-md px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),U=n.forwardRef(({className:r,variant:o,size:l,...u},c)=>e.jsx("button",{className:ot(ii({variant:o,size:l,className:r})),ref:c,...u}));U.displayName="Button";const li=Qo("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",success:"border-transparent bg-green-500 text-white shadow hover:bg-green-500/80",outline:"text-foreground"}},defaultVariants:{variant:"default"}});function nt({className:r,variant:o,...l}){return e.jsx("div",{className:ot(li({variant:o}),r),...l})}const ct=n.forwardRef(({className:r,type:o,...l},u)=>e.jsx("input",{type:o,className:ot("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",r),ref:u,...l}));ct.displayName="Input";const ps="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",ms="[a-zA-Z0-9._/~:+@%=\\\\-]",ci=new RegExp(`${ms}*\\/user-data\\/${ps}\\/`,"gi"),di=new RegExp(`${ms}*\\/user-projects\\/${ps}\\/`,"gi");function Ue(r){return!r||typeof r!="string"?r||"":r.replace(ci,"./").replace(di,"./")}var ui={};const Ve="AgentHub",fs="你的 AI 助手",jo=typeof process<"u"&&ui?.PRODUCT_WEB_URL||"http://localhost:6175",ko=[{icon:"📋",text:"帮我整理今天的工作计划"},{icon:"📊",text:"分析这段数据并给出洞察"},{icon:"✍️",text:"帮我润色这段文字"},{icon:"💡",text:"给我一些解决问题的思路"}],wo="default",hs=n.createContext(null);function lt(){const r=n.useContext(hs);if(!r)throw new Error("useDialog must be used within DialogProvider");return r}function pi({children:r}){const[o,l]=n.useState(null),u=n.useRef(null),c=n.useCallback(s=>{u.current?.(s),u.current=null,l(null)},[]),m=n.useCallback((s,p={})=>new Promise(t=>{u.current=t,l({type:"alert",message:s,title:p.title||"提示",variant:p.variant||"info"})}),[]),d=n.useCallback((s,p={})=>new Promise(t=>{u.current=t,l({type:"confirm",message:s,title:p.title||"确认操作",subtitle:p.subtitle,detail:p.detail,confirmText:p.confirmText||"确认",cancelText:p.cancelText||"取消",variant:p.variant||"warning",checkboxLabel:p.checkboxLabel})}),[]);return e.jsxs(hs.Provider,{value:{showAlert:m,showConfirm:d},children:[r,o&&Hr.createPortal(e.jsx(mi,{dialog:o,onClose:c}),document.body)]})}function mi({dialog:r,onClose:o}){const l=n.useRef(null),u=n.useRef(null),[c,m]=n.useState(!1),d=n.useCallback(a=>{r.checkboxLabel!==void 0?o({confirmed:a,checked:a?c:!1}):o(a)},[r.checkboxLabel,c,o]);n.useEffect(()=>{r.type==="confirm"?l.current?.focus():u.current?.focus()},[r.type]),n.useEffect(()=>{const a=i=>{i.key==="Escape"&&(r.type==="confirm"?d(!1):o(void 0))};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[r.type,o,d]);const s={info:e.jsx(en,{className:"w-5 h-5 text-blue-600 dark:text-blue-400"}),warning:e.jsx(Bt,{className:"w-5 h-5 text-amber-600 dark:text-amber-400"}),error:e.jsx(es,{className:"w-5 h-5 text-red-600 dark:text-red-400"}),danger:e.jsx(Bt,{className:"w-5 h-5 text-red-600 dark:text-red-400"})},p={info:"bg-blue-100 dark:bg-blue-900/30",warning:"bg-amber-100 dark:bg-amber-900/30",error:"bg-red-100 dark:bg-red-900/30",danger:"bg-red-100 dark:bg-red-900/30"},t={warning:"bg-amber-600 hover:bg-amber-700 text-white",danger:"bg-red-600 hover:bg-red-700 text-white",info:"bg-primary hover:bg-primary/90 text-primary-foreground"},x=s[r.variant]||s.info,h=p[r.variant]||p.info;return r.type==="alert"?e.jsx("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:()=>o(),children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-sm p-6 space-y-4",onClick:a=>a.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:`w-10 h-10 rounded-full ${h} flex items-center justify-center flex-shrink-0`,children:x}),e.jsx("h3",{className:"font-semibold text-foreground",children:r.title})]}),e.jsx("p",{className:"text-sm text-foreground whitespace-pre-wrap",children:r.message}),e.jsx("div",{className:"flex justify-end pt-1",children:e.jsx("button",{ref:u,className:"px-4 py-2 rounded-lg bg-primary hover:bg-primary/90 text-primary-foreground text-sm font-medium transition-colors",onClick:()=>o(),children:"确定"})})]})}):e.jsx("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:()=>d(!1),children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-sm p-6 space-y-4",onClick:a=>a.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:`w-10 h-10 rounded-full ${h} flex items-center justify-center flex-shrink-0`,children:x}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-foreground",children:r.title}),r.subtitle&&e.jsx("p",{className:"text-sm text-muted-foreground",children:r.subtitle})]})]}),e.jsx("p",{className:"text-sm text-foreground whitespace-pre-wrap",children:r.message}),r.detail&&e.jsx("p",{className:"text-xs text-muted-foreground bg-muted/50 rounded-lg p-3",children:r.detail}),r.checkboxLabel&&e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:c,onChange:a=>m(a.target.checked),className:"w-4 h-4 rounded border-border accent-primary cursor-pointer"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:r.checkboxLabel})]}),e.jsxs("div",{className:"flex gap-3 pt-1",children:[e.jsx("button",{className:"flex-1 px-4 py-2 rounded-lg border border-border text-sm font-medium hover:bg-accent transition-colors",onClick:()=>d(!1),children:r.cancelText}),e.jsx("button",{ref:l,className:`flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${t[r.variant]||t.info}`,onClick:()=>d(!0),children:r.confirmText})]})]})})}const J=(r,o={})=>{const l=localStorage.getItem("auth-token"),u={};return o.body instanceof FormData||(u["Content-Type"]="application/json"),l&&(u.Authorization=`Bearer ${l}`),fetch(r,{...o,headers:{...u,...o.headers}})},me={auth:{status:()=>fetch("/api/auth/status"),login:(r,o)=>fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:r,password:o})}),sendCode:r=>fetch("/api/auth/send-code",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:r})}),verifyCode:(r,o)=>fetch("/api/auth/verify-code",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:r,code:o})}),user:()=>J("/api/auth/user"),logout:()=>J("/api/auth/logout",{method:"POST"}),limitStatus:()=>J("/api/auth/limit-status"),changePassword:(r,o)=>J("/api/auth/change-password",{method:"PATCH",body:JSON.stringify({current_password:r,new_password:o})}),feishuBindToken:()=>J("/api/auth/feishu-bind-token",{method:"POST"}),feishuStatus:()=>J("/api/auth/feishu-status"),featurePermissions:()=>J("/api/auth/feature-permissions")},admin:{getUsers:()=>J("/api/admin/users"),createUser:(r,o)=>J("/api/admin/users",{method:"POST",body:JSON.stringify({username:r,password:o})}),updateUserStatus:(r,o)=>J(`/api/admin/users/${r}`,{method:"PATCH",body:JSON.stringify({status:o})}),deleteUser:r=>J(`/api/admin/users/${r}`,{method:"DELETE"}),getEmailDomains:()=>J("/api/admin/email-domains"),addEmailDomain:r=>J("/api/admin/email-domains",{method:"POST",body:JSON.stringify({domain:r})}),removeEmailDomain:r=>J(`/api/admin/email-domains/${r}`,{method:"DELETE"}),getUserLimits:r=>J(`/api/admin/users/${r}/limits`),updateUserLimits:(r,o)=>J(`/api/admin/users/${r}/limits`,{method:"PATCH",body:JSON.stringify(o)}),resetUserPassword:(r,o)=>J(`/api/admin/users/${r}/password`,{method:"PATCH",body:JSON.stringify({new_password:o})}),updateUserRole:(r,o)=>J(`/api/admin/users/${r}/role`,{method:"PATCH",body:JSON.stringify({role:o})}),getDefaultLimits:()=>J("/api/admin/settings/default-limits"),updateDefaultLimits:r=>J("/api/admin/settings/default-limits",{method:"PUT",body:JSON.stringify(r)}),getUserPermissions:r=>J(`/api/admin/users/${r}/permissions`),updateUserPermissions:(r,o)=>J(`/api/admin/users/${r}/permissions`,{method:"PATCH",body:JSON.stringify({permissions:o})}),getDefaultPermissions:()=>J("/api/admin/settings/default-permissions"),updateDefaultPermissions:r=>J("/api/admin/settings/default-permissions",{method:"PUT",body:JSON.stringify({permissions:r})}),getUserVisibleAgents:r=>J(`/api/admin/users/${r}/visible-agents`),updateUserVisibleAgents:(r,o)=>J(`/api/admin/users/${r}/visible-agents`,{method:"PATCH",body:JSON.stringify({agents:o})})},projects:()=>J("/api/projects"),sessions:(r,o=5,l=0)=>J(`/api/projects/${r}/sessions?limit=${o}&offset=${l}`),sessionMessages:(r,o,l=null,u=0)=>{const c=new URLSearchParams;l!==null&&(c.append("limit",l),c.append("offset",u));const m=c.toString(),d=`/api/projects/${r}/sessions/${o}/messages${m?`?${m}`:""}`;return J(d)},renameProject:(r,o)=>J(`/api/projects/${r}/rename`,{method:"PUT",body:JSON.stringify({displayName:o})}),deleteSession:(r,o)=>J(`/api/projects/${r}/sessions/${o}`,{method:"DELETE"}),renameSession:(r,o,l)=>J(`/api/projects/${r}/sessions/${o}/rename`,{method:"PUT",body:JSON.stringify({title:l})}),forkSession:(r,o,l)=>J(`/api/projects/${r}/sessions/${o}/fork`,{method:"POST",body:JSON.stringify({upToMessageId:l})}),deleteProject:(r,o=!0)=>J(`/api/projects/${r}?deleteFolder=${o}`,{method:"DELETE"}),createProject:r=>J("/api/projects/create",{method:"POST",body:JSON.stringify({path:r})}),createWorkspace:r=>J("/api/projects/create-workspace",{method:"POST",body:JSON.stringify(r)}),readFile:(r,o)=>J(`/api/projects/${r}/file?filePath=${encodeURIComponent(o)}`),saveFile:(r,o,l)=>J(`/api/projects/${r}/file`,{method:"PUT",body:JSON.stringify({filePath:o,content:l})}),getFiles:(r,o={})=>{const l=new URLSearchParams;o.dirPath&&l.set("dirPath",o.dirPath),o.depth&&l.set("depth",o.depth.toString()),o.showHidden&&l.set("showHidden","true");const u=l.toString();return J(`/api/projects/${r}/files${u?"?"+u:""}`)},uploadFiles:(r,o)=>J(`/api/projects/${r}/upload-files`,{method:"POST",body:o,headers:{}}),deleteFile:(r,o)=>J(`/api/projects/${r}/files?filePath=${encodeURIComponent(o)}`,{method:"DELETE"}),createDir:(r,o)=>J(`/api/projects/${r}/create-dir`,{method:"POST",body:JSON.stringify({dirPath:o})}),getFileContent:(r,o)=>J(`/api/projects/${r}/files/content?path=${encodeURIComponent(o)}`),transcribe:r=>J("/api/transcribe",{method:"POST",body:r,headers:{}}),settings:{getAgentPermissions:()=>J("/api/settings/agent-permissions"),saveAgentPermissions:r=>J("/api/settings/agent-permissions",{method:"PUT",body:JSON.stringify({agentPermissions:r})})},get:r=>J(`/api${r}`)},Sr={claude_shell:!0,codex_shell:!0,gemini_shell:!0,submit_agent:!0,tab_models:!0,tab_skills:!0,tab_mcp:!0,tab_permissions:!0,feishu_binding:!0,create_project:!0},xs=n.createContext({user:null,token:null,login:()=>{},sendCode:()=>{},verifyCode:()=>{},logout:()=>{},isLoading:!0,needsSetup:!1,smtpConfigured:!1,error:null,isAdmin:!1,isSuperAdmin:!1,limitStatus:{allowed:!0},checkLimitStatus:()=>{},setLimitStatus:()=>{},featurePermissions:Sr,hasPermission:()=>!0,refreshFeaturePermissions:()=>{}}),Ot=()=>{const r=n.useContext(xs);if(!r)throw new Error("useAuth must be used within an AuthProvider");return r};async function gn(){try{const r=await me.settings.getAgentPermissions();if(r.ok){const o=await r.json();o.agentPermissions&&localStorage.setItem("claude-settings",JSON.stringify(o.agentPermissions))}}catch{}}const fi=({children:r})=>{const[o,l]=n.useState(null),[u,c]=n.useState(localStorage.getItem("auth-token")),[m,d]=n.useState(!0),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(null),[i,g]=n.useState({allowed:!0}),[v,k]=n.useState(Sr);n.useEffect(()=>{b()},[]);const b=async()=>{try{d(!0),a(null);const E=await(await me.auth.status()).json();if(x(E.smtpConfigured||!1),E.needsSetup){p(!0),d(!1);return}if(u)try{const $=await me.auth.user();if($.ok){const T=await $.json();l(T.user),p(!1),T.featurePermissions&&k({...Sr,...T.featurePermissions}),await gn()}else localStorage.removeItem("auth-token"),c(null),l(null)}catch($){console.error("Token verification failed:",$),localStorage.removeItem("auth-token"),c(null),l(null)}}catch(M){console.error("[AuthContext] Auth status check failed:",M),a("Failed to check authentication status")}finally{d(!1)}},j=async M=>{try{a(null);const E=await me.auth.sendCode(M),$=await E.json();return E.ok?{success:!0,type:$.type}:{success:!1,error:$.error||"发送验证码失败",waitSeconds:$.waitSeconds}}catch(E){return console.error("Send code error:",E),{success:!1,error:"网络错误,请稍后再试"}}},f=async(M,E)=>{try{a(null);const $=await me.auth.verifyCode(M,E),T=await $.json();return $.ok?(c(T.token),l(T.user),p(!1),localStorage.setItem("auth-token",T.token),await gn(),await D(),{success:!0}):(a(T.error||"验证失败"),{success:!1,error:T.error||"验证失败"})}catch($){return console.error("Verify code error:",$),{success:!1,error:"网络错误,请稍后再试"}}},w=async(M,E)=>{try{a(null);const $=await me.auth.login(M,E),T=await $.json();return $.ok?(c(T.token),l(T.user),localStorage.setItem("auth-token",T.token),await gn(),await D(),{success:!0}):(a(T.error||"登录失败"),{success:!1,error:T.error||"登录失败"})}catch($){console.error("Login error:",$);const T="网络错误,请稍后再试";return a(T),{success:!1,error:T}}},S=()=>{c(null),l(null),g({allowed:!0}),k(Sr),localStorage.removeItem("auth-token"),u&&me.auth.logout().catch(M=>{console.error("Logout endpoint error:",M)})},z=async()=>{if(!o)return{allowed:!0};try{const M=await me.auth.limitStatus();if(M.ok){const E=await M.json();return g(E),E}}catch(M){console.error("Error checking limit status:",M)}return{allowed:!0}},D=n.useCallback(async()=>{try{const M=await me.auth.featurePermissions();if(M.ok){const E=await M.json();E.featurePermissions&&k({...Sr,...E.featurePermissions})}}catch(M){console.error("Error refreshing feature permissions:",M)}},[]),N=n.useCallback(M=>v[M]!==!1,[v]);n.useEffect(()=>{o&&!m&&z()},[o,m]);const R={user:o,token:u,login:w,sendCode:j,verifyCode:f,logout:S,isLoading:m,needsSetup:s,smtpConfigured:t,error:h,isAdmin:o?.role==="admin"||o?.role==="super_admin",isSuperAdmin:o?.role==="super_admin",limitStatus:i,checkLimitStatus:z,setLimitStatus:g,featurePermissions:v,hasPermission:N,refreshFeaturePermissions:D};return e.jsx(xs.Provider,{value:R,children:r})},hi=/^[a-zA-Z0-9_-]+$/,xi=({onClose:r,onProjectCreated:o})=>{const[l,u]=n.useState(""),[c,m]=n.useState(""),[d,s]=n.useState(!1),[p,t]=n.useState(null),x=i=>i.trim()?hi.test(i.trim())?null:"项目名称只能包含字母、数字、连字符和下划线":"项目名称为必填项",h=async()=>{t(null);const i=x(l);if(i){t(i);return}s(!0);try{const g={name:l.trim()};c.trim()&&(g.githubUrl=c.trim());const v=await me.createWorkspace(g),k=await v.json();if(!v.ok)throw new Error(k.error||"Failed to create project");o&&o(k.project),r()}catch(g){console.error("Error creating project:",g),t(g.message||"Failed to create project")}finally{s(!1)}},a=i=>{i.key==="Enter"&&!d&&h()};return e.jsx("div",{className:"fixed top-0 left-0 right-0 bottom-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[60] p-0 sm:p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-none sm:rounded-lg shadow-xl w-full h-full sm:h-auto sm:max-w-md border-0 sm:border border-gray-200 dark:border-gray-700 overflow-y-auto",children:[e.jsxs("div",{className:"flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 bg-blue-100 dark:bg-blue-900/50 rounded-lg flex items-center justify-center",children:e.jsx(Tr,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:"创建新项目"})]}),e.jsx("button",{onClick:r,className:"p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700",disabled:d,children:e.jsx(Ge,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"p-6 space-y-5",children:[p&&e.jsxs("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-start gap-3",children:[e.jsx(es,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm text-red-800 dark:text-red-200",children:p})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:["项目名称 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx(ct,{type:"text",value:l,onChange:i=>u(i.target.value),onKeyDown:a,placeholder:"my-awesome-project",className:"w-full",autoFocus:!0}),e.jsx("p",{className:"mt-1 text-xs text-gray-500 dark:text-gray-400",children:"仅允许字母、数字、连字符和下划线"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:"GitHub 链接(可选)"}),e.jsx(ct,{type:"text",value:c,onChange:i=>m(i.target.value),onKeyDown:a,placeholder:"https://github.com/user/repo",className:"w-full"}),e.jsx("p",{className:"mt-1 text-xs text-gray-500 dark:text-gray-400",children:"留空以创建空项目,或输入公共仓库链接以克隆"})]})]}),e.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-700",children:[e.jsx(U,{variant:"outline",onClick:r,disabled:d,children:"取消"}),e.jsx(U,{onClick:h,disabled:d||!l.trim(),children:d?e.jsxs(e.Fragment,{children:[e.jsx(bt,{className:"w-4 h-4 mr-2 animate-spin"}),"创建中..."]}):"创建项目"})]})]})})};function gi({projects:r=[],onClose:o}){const{showAlert:l,showConfirm:u}=lt(),[c,m]=n.useState([]),[d,s]=n.useState(!0),[p,t]=n.useState(null),[x,h]=n.useState(""),a={};for(const b of r)b.agentInfo?.isAgent&&(a[b.agentInfo.agentName]=b.agentInfo.installedVersion);n.useEffect(()=>{i()},[]),n.useEffect(()=>{const b=j=>{j.key==="Escape"&&o()};return window.addEventListener("keydown",b),()=>window.removeEventListener("keydown",b)},[o]);const i=async()=>{try{s(!0);const b=await J("/api/agents");if(b.ok){const j=await b.json();m(j.agents||[])}else{const j=await b.json();l(j.error||"获取 Agent 列表失败",{variant:"error"})}}catch(b){l(b.message,{variant:"error"})}finally{s(!1)}},g=async(b,j=!1)=>{const f=b.dirName||b.name;t(f);try{const w=await J("/api/agents/install",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentName:f,force:j})}),S=await w.json();if(w.status===409&&S.conflict){t(null),await u("检测到本地 CLAUDE.md 已被修改,更新将覆盖本地改动,是否继续?",{title:"本地文件冲突",confirmText:"强制更新",variant:"warning"})&&await g(b,!0);return}w.ok?(l(`Agent "${b.display_name||b.name}" ${j?"更新":"使用"}成功!项目已创建,Skills 和 MCP 服务已安装。`,{title:j?"更新成功":"使用成功"}),window.refreshProjects?.(),window.refreshMcpServers?.(),i()):l(S.error||"使用失败",{variant:"error"})}catch(w){l(w.message,{variant:"error"})}finally{t(null)}},v=b=>{const j=b.dirName||b.name,f=a[j];return f?f===b.version?{state:"up_to_date",installedVersion:f}:{state:"update_available",installedVersion:f,latestVersion:b.version}:{state:"not_installed"}},k=n.useMemo(()=>{if(!x.trim())return c;const b=x.toLowerCase();return c.filter(j=>(j.display_name||j.name||"").toLowerCase().includes(b)||(j.description||"").toLowerCase().includes(b))},[c,x]);return e.jsx("div",{className:"fixed inset-0 z-[60] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:o,children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-lg flex flex-col max-h-[80vh]",onClick:b=>b.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-border",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center",children:e.jsx(_t,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-sm font-semibold text-foreground",children:"使用共享项目模板"}),!d&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:[c.length," 个可用"]})]})]}),e.jsx("button",{onClick:o,className:"w-7 h-7 rounded-md flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-accent transition-colors",children:e.jsx(Ge,{className:"w-4 h-4"})})]}),e.jsx("div",{className:"px-4 py-3 border-b border-border",children:e.jsxs("div",{className:"relative",children:[e.jsx(Mt,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground"}),e.jsx("input",{type:"text",placeholder:"搜索共享项目模板...",value:x,onChange:b=>h(b.target.value),className:"w-full h-8 pl-9 pr-3 text-sm bg-muted/50 border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary/30 focus:bg-background text-foreground placeholder:text-muted-foreground",autoFocus:!0})]})}),e.jsx("div",{className:"flex-1 overflow-y-auto px-4 py-3 space-y-2",children:d?e.jsxs("div",{className:"flex items-center justify-center py-12 text-muted-foreground",children:[e.jsx(st,{className:"w-5 h-5 animate-spin mr-2"}),"加载中..."]}):c.length===0?e.jsxs("div",{className:"text-center py-12 text-muted-foreground",children:[e.jsx(_t,{className:"w-8 h-8 mx-auto mb-2 opacity-40"}),e.jsx("p",{className:"text-sm",children:"暂无可用共享项目模板"})]}):k.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Mt,{className:"w-6 h-6 mx-auto mb-2 opacity-40"}),e.jsx("p",{className:"text-sm",children:"未找到匹配的共享项目模板"})]}):k.map(b=>{const j=b.dirName||b.name,f=v(b),w=p===j;return e.jsxs("div",{className:"flex items-center gap-3 p-3 border border-border rounded-lg hover:bg-accent/50 transition-colors",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center flex-shrink-0",children:e.jsx(_t,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"font-medium text-sm text-foreground truncate",children:b.display_name||b.name}),e.jsxs("span",{className:"text-xs text-muted-foreground flex-shrink-0",children:["v",b.version]}),f.state==="update_available"&&e.jsxs(nt,{className:"text-xs bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 border-amber-200 dark:border-amber-700 hover:bg-amber-200 dark:hover:bg-amber-900/50 flex-shrink-0",children:["有更新 v",f.latestVersion]}),f.state==="up_to_date"&&e.jsx(nt,{className:"text-xs bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 border-green-200 dark:border-green-700 hover:bg-green-200 dark:hover:bg-green-900/50 flex-shrink-0",children:"已使用"})]}),b.description&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:b.description}),e.jsxs("div",{className:"flex items-center gap-3 mt-1",children:[b.skills?.length>0&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:[b.skills.length," 个 Skill"]}),b.mcps?.length>0&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:[b.mcps.length," 个 MCP"]})]})]}),e.jsx(U,{size:"sm",variant:f.state==="not_installed"?"default":"outline",onClick:()=>g(b),disabled:w||f.state==="up_to_date",className:"text-xs h-7 px-2.5 flex-shrink-0",children:w?e.jsx(st,{className:"w-3 h-3 animate-spin"}):f.state==="up_to_date"?"已是最新":f.state==="update_available"?e.jsxs(e.Fragment,{children:[e.jsx(It,{className:"w-3 h-3 mr-1"}),"更新"]}):e.jsxs(e.Fragment,{children:[e.jsx(It,{className:"w-3 h-3 mr-1"}),"使用"]})})]},j)})}),e.jsxs("div",{className:"flex items-center justify-between px-5 py-3 border-t border-border",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:!d&&x.trim()?`${k.length} / ${c.length} 个 共享项目模板`:d?"":`共 ${c.length} 个 共享项目模板`}),e.jsx(U,{variant:"outline",size:"sm",onClick:o,className:"text-xs h-7",children:"关闭"})]})]})})}function qn({projects:r=[],onClose:o,onSubmitted:l,initialProjectKey:u="",prefillData:c=null}){const{showAlert:m}=lt(),[d,s]=n.useState(u),[p,t]=n.useState(""),[x,h]=n.useState(""),[a,i]=n.useState(""),[g,v]=n.useState(!1),[k,b]=n.useState({hasClaudeMd:!1,skills:[],mcps:[],refFiles:[],gitRepos:[]}),[j,f]=n.useState(new Set),[w,S]=n.useState(new Set),[z,D]=n.useState(new Set),[N,R]=n.useState(new Set),[M,E]=n.useState(!1),[$,T]=n.useState(""),[X,_]=n.useState({files:[],truncated:!1}),[te,ne]=n.useState(!1),[G,le]=n.useState(new Set),[de,fe]=n.useState(""),[Ee,ge]=n.useState(!1),[Me,Fe]=n.useState(null),[ae,Ne]=n.useState(null),[He,Be]=n.useState(""),[he,Oe]=n.useState(!1),De=n.useRef(null),Ye=n.useRef(null),Te=r.filter(K=>K.fullPath);n.useEffect(()=>{if(d){Je(d),Ce(d);const K=Te.find(B=>B.name===d);if(K){const B=K.fullPath.split("/").filter(Boolean).pop()||"";t(B),h(K.displayName||K.name)}else if(c?.projectPath){const B=c.projectPath.split("/").filter(Boolean).pop()||"";t(B)}}else _({files:[],truncated:!1}),le(new Set),fe(""),ge(!1)},[d]),n.useEffect(()=>{c?.projectKey&&(s(c.projectKey),Ye.current={displayName:c.displayName||"",description:c.description||"",updateNotes:c.updateNotes||"",skills:c.skills||[],mcps:c.mcps||[],files:c.files||[],gitRepos:c.gitRepos||[]})},[c]),n.useEffect(()=>{if(De.current&&clearTimeout(De.current),!p||!/^[a-zA-Z0-9_-]{1,100}$/.test(p)){Fe(null),Ne(null),Oe(!1);return}return Oe(!0),De.current=setTimeout(async()=>{try{const K=await J(`/api/agents/check-name/${encodeURIComponent(p)}`);if(K.ok){const B=await K.json();Fe(B.existing),Ne(B.pendingConflict);const C=Ye.current;C?(B.existing?(x||h(B.existing.display_name||""),C.updateNotes&&Be(C.updateNotes),!a&&B.existing.description&&i(B.existing.description)):(C.displayName&&!x&&h(C.displayName),C.description&&!a&&i(C.description)),Ye.current=null):B.existing&&!a&&i(B.existing.description||"")}}catch{Fe(null),Ne(null)}finally{Oe(!1)}},400),()=>{De.current&&clearTimeout(De.current)}},[p]);const Je=async K=>{if(K)try{const B=await J(`/api/agents/preview?projectKey=${encodeURIComponent(K)}`);if(B.ok){const C=await B.json();b(C);const V=Ye.current;V?(V.skills?.length>0?f(new Set(V.skills)):f(new Set((C.skills||[]).map(I=>I.name))),V.mcps?.length>0?S(new Set(V.mcps)):S(new Set((C.mcps||[]).map(I=>I.name))),D(new Set((C.refFiles||[]).filter(I=>I.exists).map(I=>I.path))),V.gitRepos?.length>0?R(new Set(V.gitRepos.map(I=>I.name))):R(new Set((C.gitRepos||[]).map(I=>I.name))),V.files?.length>0&&(le(new Set(V.files)),ge(!0))):(f(new Set((C.skills||[]).map(I=>I.name))),S(new Set((C.mcps||[]).map(I=>I.name))),D(new Set((C.refFiles||[]).filter(I=>I.exists).map(I=>I.path))),R(new Set((C.gitRepos||[]).map(I=>I.name))))}}catch{b({hasClaudeMd:!1,skills:[],mcps:[],refFiles:[],gitRepos:[]}),f(new Set),S(new Set),D(new Set),R(new Set)}},Ce=async K=>{ne(!0),le(new Set),fe(""),ge(!1);try{const B=await J(`/api/agents/project-files?projectKey=${encodeURIComponent(K)}`);if(B.ok){const C=await B.json();_(C)}else _({files:[],truncated:!1})}catch{_({files:[],truncated:!1})}finally{ne(!1)}},Re=K=>K<1024?`${K} B`:K<1024*1024?`${(K/1024).toFixed(1)} KB`:`${(K/(1024*1024)).toFixed(1)} MB`,$e=n.useMemo(()=>{const K=new Set((k.refFiles||[]).map(C=>C.path));let B=(X.files||[]).filter(C=>!K.has(C.path));if(de.trim()){const C=de.toLowerCase();B=B.filter(V=>V.path.toLowerCase().includes(C))}return B},[X.files,k.refFiles,de]),Ie=async()=>{if(d){v(!0);try{const K=await J("/api/agents/generate-description",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectKey:d,skills:[...j],mcps:[...w]})}),B=await K.json();K.ok?i(B.description||""):m(B.error||"生成失败",{variant:"error"})}catch(K){m(K.message,{variant:"error"})}finally{v(!1)}}},ze=K=>/^[a-zA-Z0-9_-]{1,100}$/.test(K)?(T(""),!0):(T("只能包含字母、数字、连字符和下划线,1-100 字符"),!1),Ze=async()=>{if(!d){m("请选择一个项目",{variant:"warning"});return}if(!ze(p))return;if(!x.trim()){m("请填写显示名称",{variant:"warning"});return}if(!(!Te.find(B=>B.name===d)&&!c)){E(!0);try{const B=new Date().toISOString(),C=(k.skills||[]).filter(ye=>j.has(ye.name)),V=(k.mcps||[]).filter(ye=>w.has(ye.name)),I=(k.gitRepos||[]).filter(ye=>N.has(ye.name)),re=C.map(ye=>` - name: "${ye.name}"
1
+ import{j as e,s as ua,R as pa,o as ma,E as fa,m as ha,b as xa,c as ga,h as ya,p as ba,d as va}from"./vendor-codemirror-B2saKA4-.js";import{b as ja,g as Zr,a as n,d as Hr,R as mt,u as Qr,L as qt,e as Vo,B as ka,f as Zo,h as dr}from"./vendor-react-C_uEg43g.js";import{t as wa,c as Na,a as Qo,F as Sa}from"./vendor-utils-00TdZexr.js";import{T as Bt,C as es,I as en,F as Tr,X as Ge,L as bt,B as _t,S as Mt,R as st,D as It,a as On,b as ur,Z as Cr,c as tn,G as rn,d as Vt,e as Br,U as Ht,f as Cn,g as pr,h as Bn,i as Ta,j as Zt,k as Xr,l as yo,m as vt,P as En,n as Mr,o as Xa,p as zt,q as Ut,r as Gt,M as hn,s as Ma,t as Un,u as Oa,v as Ca,E as ts,w as Ea,x as bo,y as xn,z as Da,A as Er,H as Gn,J as mr,K as rs,N as Qt,O as ns,Q as Pa,V as Dn,W as os,Y as ss,_ as Aa,$ as La,a0 as _a,a1 as Ur,a2 as Gr,a3 as Ia,a4 as za,a5 as Pn,a6 as Ra,a7 as as,a8 as $a,a9 as Wa,aa as Fa,ab as Yn,ac as Ha,ad as Ba,ae as Ua,af as Ga,ag as Ya,ah as An,ai as Ja,aj as Yr,ak as is,al as ls,am as qa,an as Ka}from"./vendor-icons-BLTKkQIn.js";import{r as cs,a as Va,b as Za,M as ds}from"./vendor-markdown-Ok8-Lurq.js";import{h as us}from"./vendor-syntax-CEC-Nb_2.js";import{r as Qa,a as ei,b as ti,c as ri}from"./vendor-xterm-CvdiG4-n.js";import"./vendor-katex-DK8hFnhL.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const c of document.querySelectorAll('link[rel="modulepreload"]'))u(c);new MutationObserver(c=>{for(const m of c)if(m.type==="childList")for(const d of m.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&u(d)}).observe(document,{childList:!0,subtree:!0});function l(c){const m={};return c.integrity&&(m.integrity=c.integrity),c.referrerPolicy&&(m.referrerPolicy=c.referrerPolicy),c.crossOrigin==="use-credentials"?m.credentials="include":c.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function u(c){if(c.ep)return;c.ep=!0;const m=l(c);fetch(c.href,m)}})();var Rr={},vo;function ni(){if(vo)return Rr;vo=1;var r=ja();return Rr.createRoot=r.createRoot,Rr.hydrateRoot=r.hydrateRoot,Rr}var oi=ni();const si=Zr(oi);function ot(...r){return wa(Na(r))}function ai(r){if(!r||typeof r!="string")return null;try{return JSON.parse(r)}catch{return null}}const Jn=n.forwardRef(({className:r,children:o,...l},u)=>e.jsx("div",{ref:u,className:ot("relative overflow-hidden",r),...l,children:e.jsx("div",{className:"h-full w-full rounded-[inherit] overflow-auto",style:{WebkitOverflowScrolling:"touch",touchAction:"pan-y"},children:o})}));Jn.displayName="ScrollArea";const ii=Qo("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground shadow hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",outline:"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2",sm:"h-8 rounded-md px-3 text-xs",lg:"h-10 rounded-md px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),U=n.forwardRef(({className:r,variant:o,size:l,...u},c)=>e.jsx("button",{className:ot(ii({variant:o,size:l,className:r})),ref:c,...u}));U.displayName="Button";const li=Qo("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",success:"border-transparent bg-green-500 text-white shadow hover:bg-green-500/80",outline:"text-foreground"}},defaultVariants:{variant:"default"}});function nt({className:r,variant:o,...l}){return e.jsx("div",{className:ot(li({variant:o}),r),...l})}const ct=n.forwardRef(({className:r,type:o,...l},u)=>e.jsx("input",{type:o,className:ot("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",r),ref:u,...l}));ct.displayName="Input";const ps="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",ms="[a-zA-Z0-9._/~:+@%=\\\\-]",ci=new RegExp(`${ms}*\\/user-data\\/${ps}\\/`,"gi"),di=new RegExp(`${ms}*\\/user-projects\\/${ps}\\/`,"gi");function Ue(r){return!r||typeof r!="string"?r||"":r.replace(ci,"./").replace(di,"./")}var ui={};const Ve="AgentHub",fs="你的 AI 助手",jo=typeof process<"u"&&ui?.PRODUCT_WEB_URL||"http://10.0.1.133:6175",ko=[{icon:"📋",text:"帮我整理今天的工作计划"},{icon:"📊",text:"分析这段数据并给出洞察"},{icon:"✍️",text:"帮我润色这段文字"},{icon:"💡",text:"给我一些解决问题的思路"}],wo="default",hs=n.createContext(null);function lt(){const r=n.useContext(hs);if(!r)throw new Error("useDialog must be used within DialogProvider");return r}function pi({children:r}){const[o,l]=n.useState(null),u=n.useRef(null),c=n.useCallback(s=>{u.current?.(s),u.current=null,l(null)},[]),m=n.useCallback((s,p={})=>new Promise(t=>{u.current=t,l({type:"alert",message:s,title:p.title||"提示",variant:p.variant||"info"})}),[]),d=n.useCallback((s,p={})=>new Promise(t=>{u.current=t,l({type:"confirm",message:s,title:p.title||"确认操作",subtitle:p.subtitle,detail:p.detail,confirmText:p.confirmText||"确认",cancelText:p.cancelText||"取消",variant:p.variant||"warning",checkboxLabel:p.checkboxLabel})}),[]);return e.jsxs(hs.Provider,{value:{showAlert:m,showConfirm:d},children:[r,o&&Hr.createPortal(e.jsx(mi,{dialog:o,onClose:c}),document.body)]})}function mi({dialog:r,onClose:o}){const l=n.useRef(null),u=n.useRef(null),[c,m]=n.useState(!1),d=n.useCallback(a=>{r.checkboxLabel!==void 0?o({confirmed:a,checked:a?c:!1}):o(a)},[r.checkboxLabel,c,o]);n.useEffect(()=>{r.type==="confirm"?l.current?.focus():u.current?.focus()},[r.type]),n.useEffect(()=>{const a=i=>{i.key==="Escape"&&(r.type==="confirm"?d(!1):o(void 0))};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[r.type,o,d]);const s={info:e.jsx(en,{className:"w-5 h-5 text-blue-600 dark:text-blue-400"}),warning:e.jsx(Bt,{className:"w-5 h-5 text-amber-600 dark:text-amber-400"}),error:e.jsx(es,{className:"w-5 h-5 text-red-600 dark:text-red-400"}),danger:e.jsx(Bt,{className:"w-5 h-5 text-red-600 dark:text-red-400"})},p={info:"bg-blue-100 dark:bg-blue-900/30",warning:"bg-amber-100 dark:bg-amber-900/30",error:"bg-red-100 dark:bg-red-900/30",danger:"bg-red-100 dark:bg-red-900/30"},t={warning:"bg-amber-600 hover:bg-amber-700 text-white",danger:"bg-red-600 hover:bg-red-700 text-white",info:"bg-primary hover:bg-primary/90 text-primary-foreground"},x=s[r.variant]||s.info,h=p[r.variant]||p.info;return r.type==="alert"?e.jsx("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:()=>o(),children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-sm p-6 space-y-4",onClick:a=>a.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:`w-10 h-10 rounded-full ${h} flex items-center justify-center flex-shrink-0`,children:x}),e.jsx("h3",{className:"font-semibold text-foreground",children:r.title})]}),e.jsx("p",{className:"text-sm text-foreground whitespace-pre-wrap",children:r.message}),e.jsx("div",{className:"flex justify-end pt-1",children:e.jsx("button",{ref:u,className:"px-4 py-2 rounded-lg bg-primary hover:bg-primary/90 text-primary-foreground text-sm font-medium transition-colors",onClick:()=>o(),children:"确定"})})]})}):e.jsx("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:()=>d(!1),children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-sm p-6 space-y-4",onClick:a=>a.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:`w-10 h-10 rounded-full ${h} flex items-center justify-center flex-shrink-0`,children:x}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-foreground",children:r.title}),r.subtitle&&e.jsx("p",{className:"text-sm text-muted-foreground",children:r.subtitle})]})]}),e.jsx("p",{className:"text-sm text-foreground whitespace-pre-wrap",children:r.message}),r.detail&&e.jsx("p",{className:"text-xs text-muted-foreground bg-muted/50 rounded-lg p-3",children:r.detail}),r.checkboxLabel&&e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:c,onChange:a=>m(a.target.checked),className:"w-4 h-4 rounded border-border accent-primary cursor-pointer"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:r.checkboxLabel})]}),e.jsxs("div",{className:"flex gap-3 pt-1",children:[e.jsx("button",{className:"flex-1 px-4 py-2 rounded-lg border border-border text-sm font-medium hover:bg-accent transition-colors",onClick:()=>d(!1),children:r.cancelText}),e.jsx("button",{ref:l,className:`flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${t[r.variant]||t.info}`,onClick:()=>d(!0),children:r.confirmText})]})]})})}const J=(r,o={})=>{const l=localStorage.getItem("auth-token"),u={};return o.body instanceof FormData||(u["Content-Type"]="application/json"),l&&(u.Authorization=`Bearer ${l}`),fetch(r,{...o,headers:{...u,...o.headers}})},me={auth:{status:()=>fetch("/api/auth/status"),login:(r,o)=>fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:r,password:o})}),sendCode:r=>fetch("/api/auth/send-code",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:r})}),verifyCode:(r,o)=>fetch("/api/auth/verify-code",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:r,code:o})}),user:()=>J("/api/auth/user"),logout:()=>J("/api/auth/logout",{method:"POST"}),limitStatus:()=>J("/api/auth/limit-status"),changePassword:(r,o)=>J("/api/auth/change-password",{method:"PATCH",body:JSON.stringify({current_password:r,new_password:o})}),feishuBindToken:()=>J("/api/auth/feishu-bind-token",{method:"POST"}),feishuStatus:()=>J("/api/auth/feishu-status"),featurePermissions:()=>J("/api/auth/feature-permissions")},admin:{getUsers:()=>J("/api/admin/users"),createUser:(r,o)=>J("/api/admin/users",{method:"POST",body:JSON.stringify({username:r,password:o})}),updateUserStatus:(r,o)=>J(`/api/admin/users/${r}`,{method:"PATCH",body:JSON.stringify({status:o})}),deleteUser:r=>J(`/api/admin/users/${r}`,{method:"DELETE"}),getEmailDomains:()=>J("/api/admin/email-domains"),addEmailDomain:r=>J("/api/admin/email-domains",{method:"POST",body:JSON.stringify({domain:r})}),removeEmailDomain:r=>J(`/api/admin/email-domains/${r}`,{method:"DELETE"}),getUserLimits:r=>J(`/api/admin/users/${r}/limits`),updateUserLimits:(r,o)=>J(`/api/admin/users/${r}/limits`,{method:"PATCH",body:JSON.stringify(o)}),resetUserPassword:(r,o)=>J(`/api/admin/users/${r}/password`,{method:"PATCH",body:JSON.stringify({new_password:o})}),updateUserRole:(r,o)=>J(`/api/admin/users/${r}/role`,{method:"PATCH",body:JSON.stringify({role:o})}),getDefaultLimits:()=>J("/api/admin/settings/default-limits"),updateDefaultLimits:r=>J("/api/admin/settings/default-limits",{method:"PUT",body:JSON.stringify(r)}),getUserPermissions:r=>J(`/api/admin/users/${r}/permissions`),updateUserPermissions:(r,o)=>J(`/api/admin/users/${r}/permissions`,{method:"PATCH",body:JSON.stringify({permissions:o})}),getDefaultPermissions:()=>J("/api/admin/settings/default-permissions"),updateDefaultPermissions:r=>J("/api/admin/settings/default-permissions",{method:"PUT",body:JSON.stringify({permissions:r})}),getUserVisibleAgents:r=>J(`/api/admin/users/${r}/visible-agents`),updateUserVisibleAgents:(r,o)=>J(`/api/admin/users/${r}/visible-agents`,{method:"PATCH",body:JSON.stringify({agents:o})})},projects:()=>J("/api/projects"),sessions:(r,o=5,l=0)=>J(`/api/projects/${r}/sessions?limit=${o}&offset=${l}`),sessionMessages:(r,o,l=null,u=0)=>{const c=new URLSearchParams;l!==null&&(c.append("limit",l),c.append("offset",u));const m=c.toString(),d=`/api/projects/${r}/sessions/${o}/messages${m?`?${m}`:""}`;return J(d)},renameProject:(r,o)=>J(`/api/projects/${r}/rename`,{method:"PUT",body:JSON.stringify({displayName:o})}),deleteSession:(r,o)=>J(`/api/projects/${r}/sessions/${o}`,{method:"DELETE"}),renameSession:(r,o,l)=>J(`/api/projects/${r}/sessions/${o}/rename`,{method:"PUT",body:JSON.stringify({title:l})}),forkSession:(r,o,l)=>J(`/api/projects/${r}/sessions/${o}/fork`,{method:"POST",body:JSON.stringify({upToMessageId:l})}),deleteProject:(r,o=!0)=>J(`/api/projects/${r}?deleteFolder=${o}`,{method:"DELETE"}),createProject:r=>J("/api/projects/create",{method:"POST",body:JSON.stringify({path:r})}),createWorkspace:r=>J("/api/projects/create-workspace",{method:"POST",body:JSON.stringify(r)}),readFile:(r,o)=>J(`/api/projects/${r}/file?filePath=${encodeURIComponent(o)}`),saveFile:(r,o,l)=>J(`/api/projects/${r}/file`,{method:"PUT",body:JSON.stringify({filePath:o,content:l})}),getFiles:(r,o={})=>{const l=new URLSearchParams;o.dirPath&&l.set("dirPath",o.dirPath),o.depth&&l.set("depth",o.depth.toString()),o.showHidden&&l.set("showHidden","true");const u=l.toString();return J(`/api/projects/${r}/files${u?"?"+u:""}`)},uploadFiles:(r,o)=>J(`/api/projects/${r}/upload-files`,{method:"POST",body:o,headers:{}}),deleteFile:(r,o)=>J(`/api/projects/${r}/files?filePath=${encodeURIComponent(o)}`,{method:"DELETE"}),createDir:(r,o)=>J(`/api/projects/${r}/create-dir`,{method:"POST",body:JSON.stringify({dirPath:o})}),getFileContent:(r,o)=>J(`/api/projects/${r}/files/content?path=${encodeURIComponent(o)}`),transcribe:r=>J("/api/transcribe",{method:"POST",body:r,headers:{}}),settings:{getAgentPermissions:()=>J("/api/settings/agent-permissions"),saveAgentPermissions:r=>J("/api/settings/agent-permissions",{method:"PUT",body:JSON.stringify({agentPermissions:r})})},get:r=>J(`/api${r}`)},Sr={claude_shell:!0,codex_shell:!0,gemini_shell:!0,submit_agent:!0,tab_models:!0,tab_skills:!0,tab_mcp:!0,tab_permissions:!0,feishu_binding:!0,create_project:!0},xs=n.createContext({user:null,token:null,login:()=>{},sendCode:()=>{},verifyCode:()=>{},logout:()=>{},isLoading:!0,needsSetup:!1,smtpConfigured:!1,error:null,isAdmin:!1,isSuperAdmin:!1,limitStatus:{allowed:!0},checkLimitStatus:()=>{},setLimitStatus:()=>{},featurePermissions:Sr,hasPermission:()=>!0,refreshFeaturePermissions:()=>{}}),Ot=()=>{const r=n.useContext(xs);if(!r)throw new Error("useAuth must be used within an AuthProvider");return r};async function gn(){try{const r=await me.settings.getAgentPermissions();if(r.ok){const o=await r.json();o.agentPermissions&&localStorage.setItem("claude-settings",JSON.stringify(o.agentPermissions))}}catch{}}const fi=({children:r})=>{const[o,l]=n.useState(null),[u,c]=n.useState(localStorage.getItem("auth-token")),[m,d]=n.useState(!0),[s,p]=n.useState(!1),[t,x]=n.useState(!1),[h,a]=n.useState(null),[i,g]=n.useState({allowed:!0}),[v,k]=n.useState(Sr);n.useEffect(()=>{b()},[]);const b=async()=>{try{d(!0),a(null);const E=await(await me.auth.status()).json();if(x(E.smtpConfigured||!1),E.needsSetup){p(!0),d(!1);return}if(u)try{const $=await me.auth.user();if($.ok){const T=await $.json();l(T.user),p(!1),T.featurePermissions&&k({...Sr,...T.featurePermissions}),await gn()}else localStorage.removeItem("auth-token"),c(null),l(null)}catch($){console.error("Token verification failed:",$),localStorage.removeItem("auth-token"),c(null),l(null)}}catch(M){console.error("[AuthContext] Auth status check failed:",M),a("Failed to check authentication status")}finally{d(!1)}},j=async M=>{try{a(null);const E=await me.auth.sendCode(M),$=await E.json();return E.ok?{success:!0,type:$.type}:{success:!1,error:$.error||"发送验证码失败",waitSeconds:$.waitSeconds}}catch(E){return console.error("Send code error:",E),{success:!1,error:"网络错误,请稍后再试"}}},f=async(M,E)=>{try{a(null);const $=await me.auth.verifyCode(M,E),T=await $.json();return $.ok?(c(T.token),l(T.user),p(!1),localStorage.setItem("auth-token",T.token),await gn(),await D(),{success:!0}):(a(T.error||"验证失败"),{success:!1,error:T.error||"验证失败"})}catch($){return console.error("Verify code error:",$),{success:!1,error:"网络错误,请稍后再试"}}},w=async(M,E)=>{try{a(null);const $=await me.auth.login(M,E),T=await $.json();return $.ok?(c(T.token),l(T.user),localStorage.setItem("auth-token",T.token),await gn(),await D(),{success:!0}):(a(T.error||"登录失败"),{success:!1,error:T.error||"登录失败"})}catch($){console.error("Login error:",$);const T="网络错误,请稍后再试";return a(T),{success:!1,error:T}}},S=()=>{c(null),l(null),g({allowed:!0}),k(Sr),localStorage.removeItem("auth-token"),u&&me.auth.logout().catch(M=>{console.error("Logout endpoint error:",M)})},z=async()=>{if(!o)return{allowed:!0};try{const M=await me.auth.limitStatus();if(M.ok){const E=await M.json();return g(E),E}}catch(M){console.error("Error checking limit status:",M)}return{allowed:!0}},D=n.useCallback(async()=>{try{const M=await me.auth.featurePermissions();if(M.ok){const E=await M.json();E.featurePermissions&&k({...Sr,...E.featurePermissions})}}catch(M){console.error("Error refreshing feature permissions:",M)}},[]),N=n.useCallback(M=>v[M]!==!1,[v]);n.useEffect(()=>{o&&!m&&z()},[o,m]);const R={user:o,token:u,login:w,sendCode:j,verifyCode:f,logout:S,isLoading:m,needsSetup:s,smtpConfigured:t,error:h,isAdmin:o?.role==="admin"||o?.role==="super_admin",isSuperAdmin:o?.role==="super_admin",limitStatus:i,checkLimitStatus:z,setLimitStatus:g,featurePermissions:v,hasPermission:N,refreshFeaturePermissions:D};return e.jsx(xs.Provider,{value:R,children:r})},hi=/^[a-zA-Z0-9_-]+$/,xi=({onClose:r,onProjectCreated:o})=>{const[l,u]=n.useState(""),[c,m]=n.useState(""),[d,s]=n.useState(!1),[p,t]=n.useState(null),x=i=>i.trim()?hi.test(i.trim())?null:"项目名称只能包含字母、数字、连字符和下划线":"项目名称为必填项",h=async()=>{t(null);const i=x(l);if(i){t(i);return}s(!0);try{const g={name:l.trim()};c.trim()&&(g.githubUrl=c.trim());const v=await me.createWorkspace(g),k=await v.json();if(!v.ok)throw new Error(k.error||"Failed to create project");o&&o(k.project),r()}catch(g){console.error("Error creating project:",g),t(g.message||"Failed to create project")}finally{s(!1)}},a=i=>{i.key==="Enter"&&!d&&h()};return e.jsx("div",{className:"fixed top-0 left-0 right-0 bottom-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[60] p-0 sm:p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-none sm:rounded-lg shadow-xl w-full h-full sm:h-auto sm:max-w-md border-0 sm:border border-gray-200 dark:border-gray-700 overflow-y-auto",children:[e.jsxs("div",{className:"flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 bg-blue-100 dark:bg-blue-900/50 rounded-lg flex items-center justify-center",children:e.jsx(Tr,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:"创建新项目"})]}),e.jsx("button",{onClick:r,className:"p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700",disabled:d,children:e.jsx(Ge,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"p-6 space-y-5",children:[p&&e.jsxs("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-start gap-3",children:[e.jsx(es,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm text-red-800 dark:text-red-200",children:p})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:["项目名称 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx(ct,{type:"text",value:l,onChange:i=>u(i.target.value),onKeyDown:a,placeholder:"my-awesome-project",className:"w-full",autoFocus:!0}),e.jsx("p",{className:"mt-1 text-xs text-gray-500 dark:text-gray-400",children:"仅允许字母、数字、连字符和下划线"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:"GitHub 链接(可选)"}),e.jsx(ct,{type:"text",value:c,onChange:i=>m(i.target.value),onKeyDown:a,placeholder:"https://github.com/user/repo",className:"w-full"}),e.jsx("p",{className:"mt-1 text-xs text-gray-500 dark:text-gray-400",children:"留空以创建空项目,或输入公共仓库链接以克隆"})]})]}),e.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-700",children:[e.jsx(U,{variant:"outline",onClick:r,disabled:d,children:"取消"}),e.jsx(U,{onClick:h,disabled:d||!l.trim(),children:d?e.jsxs(e.Fragment,{children:[e.jsx(bt,{className:"w-4 h-4 mr-2 animate-spin"}),"创建中..."]}):"创建项目"})]})]})})};function gi({projects:r=[],onClose:o}){const{showAlert:l,showConfirm:u}=lt(),[c,m]=n.useState([]),[d,s]=n.useState(!0),[p,t]=n.useState(null),[x,h]=n.useState(""),a={};for(const b of r)b.agentInfo?.isAgent&&(a[b.agentInfo.agentName]=b.agentInfo.installedVersion);n.useEffect(()=>{i()},[]),n.useEffect(()=>{const b=j=>{j.key==="Escape"&&o()};return window.addEventListener("keydown",b),()=>window.removeEventListener("keydown",b)},[o]);const i=async()=>{try{s(!0);const b=await J("/api/agents");if(b.ok){const j=await b.json();m(j.agents||[])}else{const j=await b.json();l(j.error||"获取 Agent 列表失败",{variant:"error"})}}catch(b){l(b.message,{variant:"error"})}finally{s(!1)}},g=async(b,j=!1)=>{const f=b.dirName||b.name;t(f);try{const w=await J("/api/agents/install",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentName:f,force:j})}),S=await w.json();if(w.status===409&&S.conflict){t(null),await u("检测到本地 CLAUDE.md 已被修改,更新将覆盖本地改动,是否继续?",{title:"本地文件冲突",confirmText:"强制更新",variant:"warning"})&&await g(b,!0);return}w.ok?(l(`Agent "${b.display_name||b.name}" ${j?"更新":"使用"}成功!项目已创建,Skills 和 MCP 服务已安装。`,{title:j?"更新成功":"使用成功"}),window.refreshProjects?.(),window.refreshMcpServers?.(),i()):l(S.error||"使用失败",{variant:"error"})}catch(w){l(w.message,{variant:"error"})}finally{t(null)}},v=b=>{const j=b.dirName||b.name,f=a[j];return f?f===b.version?{state:"up_to_date",installedVersion:f}:{state:"update_available",installedVersion:f,latestVersion:b.version}:{state:"not_installed"}},k=n.useMemo(()=>{if(!x.trim())return c;const b=x.toLowerCase();return c.filter(j=>(j.display_name||j.name||"").toLowerCase().includes(b)||(j.description||"").toLowerCase().includes(b))},[c,x]);return e.jsx("div",{className:"fixed inset-0 z-[60] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4",onClick:o,children:e.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-2xl w-full max-w-lg flex flex-col max-h-[80vh]",onClick:b=>b.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-border",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center",children:e.jsx(_t,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-sm font-semibold text-foreground",children:"使用共享项目模板"}),!d&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:[c.length," 个可用"]})]})]}),e.jsx("button",{onClick:o,className:"w-7 h-7 rounded-md flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-accent transition-colors",children:e.jsx(Ge,{className:"w-4 h-4"})})]}),e.jsx("div",{className:"px-4 py-3 border-b border-border",children:e.jsxs("div",{className:"relative",children:[e.jsx(Mt,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground"}),e.jsx("input",{type:"text",placeholder:"搜索共享项目模板...",value:x,onChange:b=>h(b.target.value),className:"w-full h-8 pl-9 pr-3 text-sm bg-muted/50 border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary/30 focus:bg-background text-foreground placeholder:text-muted-foreground",autoFocus:!0})]})}),e.jsx("div",{className:"flex-1 overflow-y-auto px-4 py-3 space-y-2",children:d?e.jsxs("div",{className:"flex items-center justify-center py-12 text-muted-foreground",children:[e.jsx(st,{className:"w-5 h-5 animate-spin mr-2"}),"加载中..."]}):c.length===0?e.jsxs("div",{className:"text-center py-12 text-muted-foreground",children:[e.jsx(_t,{className:"w-8 h-8 mx-auto mb-2 opacity-40"}),e.jsx("p",{className:"text-sm",children:"暂无可用共享项目模板"})]}):k.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Mt,{className:"w-6 h-6 mx-auto mb-2 opacity-40"}),e.jsx("p",{className:"text-sm",children:"未找到匹配的共享项目模板"})]}):k.map(b=>{const j=b.dirName||b.name,f=v(b),w=p===j;return e.jsxs("div",{className:"flex items-center gap-3 p-3 border border-border rounded-lg hover:bg-accent/50 transition-colors",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center flex-shrink-0",children:e.jsx(_t,{className:"w-4 h-4 text-blue-600 dark:text-blue-400"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"font-medium text-sm text-foreground truncate",children:b.display_name||b.name}),e.jsxs("span",{className:"text-xs text-muted-foreground flex-shrink-0",children:["v",b.version]}),f.state==="update_available"&&e.jsxs(nt,{className:"text-xs bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400 border-amber-200 dark:border-amber-700 hover:bg-amber-200 dark:hover:bg-amber-900/50 flex-shrink-0",children:["有更新 v",f.latestVersion]}),f.state==="up_to_date"&&e.jsx(nt,{className:"text-xs bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 border-green-200 dark:border-green-700 hover:bg-green-200 dark:hover:bg-green-900/50 flex-shrink-0",children:"已使用"})]}),b.description&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:b.description}),e.jsxs("div",{className:"flex items-center gap-3 mt-1",children:[b.skills?.length>0&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:[b.skills.length," 个 Skill"]}),b.mcps?.length>0&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:[b.mcps.length," 个 MCP"]})]})]}),e.jsx(U,{size:"sm",variant:f.state==="not_installed"?"default":"outline",onClick:()=>g(b),disabled:w||f.state==="up_to_date",className:"text-xs h-7 px-2.5 flex-shrink-0",children:w?e.jsx(st,{className:"w-3 h-3 animate-spin"}):f.state==="up_to_date"?"已是最新":f.state==="update_available"?e.jsxs(e.Fragment,{children:[e.jsx(It,{className:"w-3 h-3 mr-1"}),"更新"]}):e.jsxs(e.Fragment,{children:[e.jsx(It,{className:"w-3 h-3 mr-1"}),"使用"]})})]},j)})}),e.jsxs("div",{className:"flex items-center justify-between px-5 py-3 border-t border-border",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:!d&&x.trim()?`${k.length} / ${c.length} 个 共享项目模板`:d?"":`共 ${c.length} 个 共享项目模板`}),e.jsx(U,{variant:"outline",size:"sm",onClick:o,className:"text-xs h-7",children:"关闭"})]})]})})}function qn({projects:r=[],onClose:o,onSubmitted:l,initialProjectKey:u="",prefillData:c=null}){const{showAlert:m}=lt(),[d,s]=n.useState(u),[p,t]=n.useState(""),[x,h]=n.useState(""),[a,i]=n.useState(""),[g,v]=n.useState(!1),[k,b]=n.useState({hasClaudeMd:!1,skills:[],mcps:[],refFiles:[],gitRepos:[]}),[j,f]=n.useState(new Set),[w,S]=n.useState(new Set),[z,D]=n.useState(new Set),[N,R]=n.useState(new Set),[M,E]=n.useState(!1),[$,T]=n.useState(""),[X,_]=n.useState({files:[],truncated:!1}),[te,ne]=n.useState(!1),[G,le]=n.useState(new Set),[de,fe]=n.useState(""),[Ee,ge]=n.useState(!1),[Me,Fe]=n.useState(null),[ae,Ne]=n.useState(null),[He,Be]=n.useState(""),[he,Oe]=n.useState(!1),De=n.useRef(null),Ye=n.useRef(null),Te=r.filter(K=>K.fullPath);n.useEffect(()=>{if(d){Je(d),Ce(d);const K=Te.find(B=>B.name===d);if(K){const B=K.fullPath.split("/").filter(Boolean).pop()||"";t(B),h(K.displayName||K.name)}else if(c?.projectPath){const B=c.projectPath.split("/").filter(Boolean).pop()||"";t(B)}}else _({files:[],truncated:!1}),le(new Set),fe(""),ge(!1)},[d]),n.useEffect(()=>{c?.projectKey&&(s(c.projectKey),Ye.current={displayName:c.displayName||"",description:c.description||"",updateNotes:c.updateNotes||"",skills:c.skills||[],mcps:c.mcps||[],files:c.files||[],gitRepos:c.gitRepos||[]})},[c]),n.useEffect(()=>{if(De.current&&clearTimeout(De.current),!p||!/^[a-zA-Z0-9_-]{1,100}$/.test(p)){Fe(null),Ne(null),Oe(!1);return}return Oe(!0),De.current=setTimeout(async()=>{try{const K=await J(`/api/agents/check-name/${encodeURIComponent(p)}`);if(K.ok){const B=await K.json();Fe(B.existing),Ne(B.pendingConflict);const C=Ye.current;C?(B.existing?(x||h(B.existing.display_name||""),C.updateNotes&&Be(C.updateNotes),!a&&B.existing.description&&i(B.existing.description)):(C.displayName&&!x&&h(C.displayName),C.description&&!a&&i(C.description)),Ye.current=null):B.existing&&!a&&i(B.existing.description||"")}}catch{Fe(null),Ne(null)}finally{Oe(!1)}},400),()=>{De.current&&clearTimeout(De.current)}},[p]);const Je=async K=>{if(K)try{const B=await J(`/api/agents/preview?projectKey=${encodeURIComponent(K)}`);if(B.ok){const C=await B.json();b(C);const V=Ye.current;V?(V.skills?.length>0?f(new Set(V.skills)):f(new Set((C.skills||[]).map(I=>I.name))),V.mcps?.length>0?S(new Set(V.mcps)):S(new Set((C.mcps||[]).map(I=>I.name))),D(new Set((C.refFiles||[]).filter(I=>I.exists).map(I=>I.path))),V.gitRepos?.length>0?R(new Set(V.gitRepos.map(I=>I.name))):R(new Set((C.gitRepos||[]).map(I=>I.name))),V.files?.length>0&&(le(new Set(V.files)),ge(!0))):(f(new Set((C.skills||[]).map(I=>I.name))),S(new Set((C.mcps||[]).map(I=>I.name))),D(new Set((C.refFiles||[]).filter(I=>I.exists).map(I=>I.path))),R(new Set((C.gitRepos||[]).map(I=>I.name))))}}catch{b({hasClaudeMd:!1,skills:[],mcps:[],refFiles:[],gitRepos:[]}),f(new Set),S(new Set),D(new Set),R(new Set)}},Ce=async K=>{ne(!0),le(new Set),fe(""),ge(!1);try{const B=await J(`/api/agents/project-files?projectKey=${encodeURIComponent(K)}`);if(B.ok){const C=await B.json();_(C)}else _({files:[],truncated:!1})}catch{_({files:[],truncated:!1})}finally{ne(!1)}},Re=K=>K<1024?`${K} B`:K<1024*1024?`${(K/1024).toFixed(1)} KB`:`${(K/(1024*1024)).toFixed(1)} MB`,$e=n.useMemo(()=>{const K=new Set((k.refFiles||[]).map(C=>C.path));let B=(X.files||[]).filter(C=>!K.has(C.path));if(de.trim()){const C=de.toLowerCase();B=B.filter(V=>V.path.toLowerCase().includes(C))}return B},[X.files,k.refFiles,de]),Ie=async()=>{if(d){v(!0);try{const K=await J("/api/agents/generate-description",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectKey:d,skills:[...j],mcps:[...w]})}),B=await K.json();K.ok?i(B.description||""):m(B.error||"生成失败",{variant:"error"})}catch(K){m(K.message,{variant:"error"})}finally{v(!1)}}},ze=K=>/^[a-zA-Z0-9_-]{1,100}$/.test(K)?(T(""),!0):(T("只能包含字母、数字、连字符和下划线,1-100 字符"),!1),Ze=async()=>{if(!d){m("请选择一个项目",{variant:"warning"});return}if(!ze(p))return;if(!x.trim()){m("请填写显示名称",{variant:"warning"});return}if(!(!Te.find(B=>B.name===d)&&!c)){E(!0);try{const B=new Date().toISOString(),C=(k.skills||[]).filter(ye=>j.has(ye.name)),V=(k.mcps||[]).filter(ye=>w.has(ye.name)),I=(k.gitRepos||[]).filter(ye=>N.has(ye.name)),re=C.map(ye=>` - name: "${ye.name}"
2
2
  repo: "${ye.localPath||ye.repo||""}"`).join(`
3
3
  `),Y=V.map(ye=>` - name: "${ye.name}"
4
4
  repo: "${ye.repo||""}"`).join(`
@@ -196,5 +196,5 @@ X-API-Key=your-key`})]}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",c
196
196
  1. 数据库查询未使用索引(耗时占 45%)
197
197
  2. JSON 序列化存在冗余字段(内存多占 30%)
198
198
  3. 日志写入为同步 I/O(P99 延迟 +200ms)`}]}];function Uc({messages:r}){return e.jsxs("div",{className:"demo-chat-mockup glass-panel",children:[e.jsxs("div",{className:"lp-chat-header",children:[e.jsxs("div",{className:"lp-window-controls",children:[e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{})]}),e.jsx("div",{className:"lp-chat-title",children:"AgentHub"})]}),e.jsx("div",{className:"lp-chat-body",children:r.map((o,l)=>e.jsxs("div",{className:`lp-message ${o.type==="user"?"lp-user-msg":"lp-system-msg"}`,children:[e.jsx("div",{className:"lp-avatar",children:o.type==="user"?"U":e.jsx("img",{src:"/logo.svg",alt:"AgentHub"})}),e.jsx("div",{className:"lp-msg-content",children:o.content.split(`
199
- `).map((u,c)=>e.jsxs(mt.Fragment,{children:[c>0&&e.jsx("br",{}),u]},c))})]},l))})]})}function Gc(){const r=Qr(),{isDarkMode:o,toggleDarkMode:l}=no(),[u,c]=n.useState(!1);return n.useEffect(()=>{const m=()=>c(window.scrollY>50);return window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]),n.useEffect(()=>{window.scrollTo(0,0)},[]),n.useEffect(()=>{const m=new IntersectionObserver(d=>{d.forEach(s=>{s.isIntersecting&&(s.target.classList.add("visible"),m.unobserve(s.target))})},{threshold:.1});return document.querySelectorAll(".lp-fade-up").forEach(d=>m.observe(d)),()=>m.disconnect()},[]),e.jsxs("div",{className:"landing-page",children:[e.jsx("div",{className:"bg-orb orb-1"}),e.jsx("div",{className:"bg-orb orb-2"}),e.jsx("div",{className:"bg-grid"}),e.jsxs("nav",{className:`lp-navbar${u?" scrolled":""}`,children:[e.jsxs(qt,{to:"/",className:"lp-logo",children:[e.jsx("img",{className:"lp-logo-icon",src:"/logo.svg",alt:"AgentHub"}),e.jsx("span",{children:"AgentHub"})]}),e.jsx("ul",{className:"lp-nav-links",children:e.jsx("li",{children:e.jsxs(qt,{to:"/",style:{display:"inline-flex",alignItems:"center",gap:"0.4rem"},children:[e.jsx(Qt,{size:16})," 返回首页"]})})}),e.jsxs("div",{className:"lp-nav-right",children:[e.jsx("button",{className:"lp-theme-toggle",onClick:l,title:o?"切换到亮色":"切换到暗色",children:o?e.jsx(Gr,{size:18}):e.jsx(Ur,{size:18})}),e.jsx("button",{className:"lp-btn lp-btn-primary",onClick:()=>r("/app"),children:"开始使用"})]})]}),e.jsxs("main",{children:[e.jsxs("section",{className:"demo-hero",children:[e.jsxs("h1",{children:["看看 ",e.jsx("span",{className:"gradient-text",children:"AgentHub"})," 能做什么"]}),e.jsx("p",{children:"以下是几个真实的使用场景,展示 AI Agent 如何帮你解决工作中的实际问题。"})]}),e.jsx("section",{className:"demo-scenarios",children:Bc.map((m,d)=>e.jsxs("div",{className:"demo-scenario lp-fade-up",children:[e.jsxs("div",{className:"demo-scenario-info",children:[e.jsx("span",{className:`demo-scenario-tag ${m.tagClass}`,children:m.tag}),e.jsx("h2",{children:m.title}),e.jsx("p",{children:m.description}),e.jsx("ul",{className:"demo-highlights",children:m.highlights.map((s,p)=>e.jsx("li",{children:s},p))})]}),e.jsx(Uc,{messages:m.messages})]},d))}),e.jsxs("section",{className:"demo-cta",children:[e.jsx("h2",{children:"准备好开始了吗?"}),e.jsx("p",{children:"立即体验 AgentHub,让 AI 成为你的超级助手。"}),e.jsx("button",{className:"lp-btn lp-btn-primary lp-btn-large",onClick:()=>r("/app"),children:"开始使用"})]})]}),e.jsx("footer",{className:"lp-footer",children:e.jsxs("div",{className:"lp-footer-content",children:[e.jsxs(qt,{to:"/",className:"lp-logo",children:[e.jsx("img",{className:"lp-logo-icon",src:"/logo.svg",alt:"AgentHub"}),e.jsx("span",{children:"AgentHub"})]}),e.jsxs("p",{className:"lp-copyright",children:["© ",new Date().getFullYear()," AgentHub. All rights reserved."]})]})})]})}function Yc(){const{userUuid:r,sessionId:o}=Vo(),[l,u]=n.useState(null),[c,m]=n.useState(null),[d,s]=n.useState(!0);if(n.useEffect(()=>{fetch(`/api/share/${r}/${o}`).then(g=>g.ok?g.json():Promise.reject(g.status)).then(g=>{u(g),document.title=`${g.title||"对话分享"} - ${Ve}`}).catch(g=>{m(g===404?"not_found":"error")}).finally(()=>s(!1))},[r,o]),d)return e.jsx("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-3"}),e.jsx("p",{className:"text-gray-500 text-sm",children:"加载中..."})]})});if(c)return e.jsx("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center",children:e.jsxs("div",{className:"text-center px-6 max-w-sm",children:[e.jsx("div",{className:"w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4",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:1.5,d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"})})}),e.jsx("h1",{className:"text-lg font-semibold text-gray-900 mb-2",children:c==="not_found"?"分享已关闭或不存在":"加载失败"}),e.jsx("p",{className:"text-sm text-gray-500",children:c==="not_found"?"该对话分享链接已失效或被关闭。":"加载分享内容时发生错误,请稍后重试。"}),e.jsxs("a",{href:jo,className:"mt-6 inline-block text-sm text-blue-600 hover:underline",children:["前往 ",Ve]})]})});const{mode:p,title:t,projectName:x,messages:h=[],sharerName:a,generatedAt:i}=l;return e.jsxs("div",{className:"min-h-screen bg-gray-50 font-sans",children:[e.jsx("div",{className:"bg-white border-b border-gray-200 sticky top-0 z-10",children:e.jsxs("div",{className:"max-w-3xl mx-auto px-4 py-3 flex items-center justify-between",children:[e.jsxs("div",{className:"min-w-0",children:[x&&e.jsx("p",{className:"text-xs text-gray-400 mb-0.5 truncate",children:x}),e.jsx("h1",{className:"text-base font-semibold text-gray-900 truncate",children:t||"对话分享"}),p==="static"&&i&&e.jsxs("p",{className:"text-xs text-gray-400 mt-0.5",children:["静态快照 · ",new Date(i).toLocaleString("zh-CN")]})]}),e.jsxs("span",{className:`ml-3 flex-shrink-0 inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium ${p==="realtime"?"bg-green-100 text-green-700":"bg-blue-100 text-blue-700"}`,children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-current"}),p==="realtime"?"实时":"快照"]})]})}),e.jsx("div",{className:"max-w-3xl mx-auto px-4 py-6 space-y-4",children:h.length===0?e.jsx("div",{className:"text-center text-gray-400 py-16 text-sm",children:"暂无消息"}):h.map((g,v)=>e.jsx(Jc,{message:g},g.uuid||v))}),e.jsx("div",{className:"text-center pb-10 pt-4",children:e.jsxs("p",{className:"text-xs text-gray-400",children:[a?`由 ${a} 分享 · `:"","Powered by"," ",e.jsx("a",{href:jo,target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",children:Ve})]})})]})}function Jc({message:r}){const o=r.role==="user",l=r.timestamp?new Date(r.timestamp).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"}):null;return e.jsx("div",{className:`flex ${o?"justify-end":"justify-start"}`,children:e.jsxs("div",{className:`max-w-[96%] ${o?"order-2":"order-1"}`,children:[e.jsxs("div",{className:`flex items-center gap-2 mb-1 ${o?"justify-end":"justify-start"}`,children:[e.jsx("span",{className:`text-xs font-medium ${o?"text-gray-500":"text-blue-600"}`,children:o?"用户":Ve}),l&&e.jsx("span",{className:"text-xs text-gray-400",children:l})]}),e.jsx("div",{className:`rounded-2xl px-4 py-3 ${o?"bg-blue-600 text-white rounded-tr-sm":"bg-white border border-gray-200 text-gray-900 rounded-tl-sm shadow-sm"}`,children:o?e.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:r.content}):e.jsx("div",{className:"prose prose-sm max-w-none prose-p:my-1 prose-headings:my-2 prose-pre:my-2 prose-ul:my-1 prose-ol:my-1 prose-li:my-0 prose-table:my-2",children:e.jsx(ds,{remarkPlugins:[cs],components:{code({node:u,className:c,children:m,...d}){if(u?.position?.start?.line!==u?.position?.end?.line||String(m).includes(`
200
- `)){const p=c?.replace("language-","")||"";return e.jsxs("div",{className:"relative group my-2",children:[p&&p!=="text"&&e.jsx("div",{className:"absolute top-2 left-3 z-10 text-xs text-gray-400 font-medium uppercase",children:p}),e.jsx(us,{language:p||"text",style:ys,customStyle:{margin:0,borderRadius:"0.5rem",fontSize:"0.8125rem",padding:p&&p!=="text"?"2rem 1rem 1rem 1rem":"1rem"},codeTagProps:{style:{fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"}},children:String(m).replace(/\n$/,"")})]})}return e.jsx("code",{className:"bg-gray-100 text-gray-800 rounded px-1 py-0.5 text-xs font-mono",...d,children:m})},a({children:u,href:c,...m}){return e.jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",...m,children:u})},table({children:u}){return e.jsx("div",{className:"overflow-x-auto",children:e.jsx("table",{className:"min-w-full border-collapse text-xs",children:u})})},th({children:u}){return e.jsx("th",{className:"border border-gray-300 px-2 py-1 bg-gray-50 font-semibold text-left",children:u})},td({children:u}){return e.jsx("td",{className:"border border-gray-300 px-2 py-1",children:u})}},children:r.content})})})]})})}const qc=()=>{const[r,o]=n.useState("email"),[l,u]=n.useState(""),[c,m]=n.useState(""),[d,s]=n.useState(!1),[p,t]=n.useState(""),[x,h]=n.useState(0),{sendCode:a,verifyCode:i,smtpConfigured:g}=Ot();n.useEffect(()=>{if(x>0){const f=setTimeout(()=>h(x-1),1e3);return()=>clearTimeout(f)}},[x]);const v=async f=>{if(f.preventDefault(),t(""),!l||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(l)){t("请输入有效的邮箱地址");return}s(!0);const S=await a(l);S.success?(o("code"),h(60)):(t(S.error),S.waitSeconds&&h(S.waitSeconds)),s(!1)},k=async f=>{if(f.preventDefault(),t(""),!c||c.length!==6){t("请输入6位验证码");return}s(!0);const w=await i(l,c);w.success||t(w.error),s(!1)},b=async()=>{if(x>0)return;t(""),s(!0);const f=await a(l);f.success?h(60):t(f.error),s(!1)},j=()=>{o("email"),m(""),t("")};return g?e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx(Vr,{size:64})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:r==="email"?`欢迎使用 ${Ve}`:"创建管理员账户"}),e.jsx("p",{className:"text-muted-foreground mt-2",children:r==="email"?"输入邮箱创建管理员账户":`验证码已发送至 ${l}`})]}),r==="email"&&e.jsxs("form",{onSubmit:v,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"email",className:"block text-sm font-medium text-foreground mb-1",children:"邮箱地址"}),e.jsxs("div",{className:"relative",children:[e.jsx(Yr,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"email",id:"email",value:l,onChange:f=>u(f.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入邮箱地址",required:!0,disabled:d,autoComplete:"email"})]})]}),p&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:p})}),e.jsx("button",{type:"submit",disabled:d||x>0,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:d?"发送中...":x>0?`${x}秒后可重新发送`:"获取验证码"})]}),r==="code"&&e.jsxs("form",{onSubmit:k,className:"space-y-4",children:[e.jsxs("button",{type:"button",onClick:j,className:"flex items-center text-sm text-muted-foreground hover:text-foreground",children:[e.jsx(Qt,{className:"w-4 h-4 mr-1"}),"返回修改邮箱"]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"code",className:"block text-sm font-medium text-foreground mb-1",children:"验证码"}),e.jsx("input",{type:"text",id:"code",value:c,onChange:f=>m(f.target.value.replace(/\D/g,"").slice(0,6)),className:"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground text-center text-2xl tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"000000",required:!0,disabled:d,maxLength:6,autoComplete:"one-time-code"})]}),p&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:p})}),e.jsx("button",{type:"submit",disabled:d||c.length!==6,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:d?"创建中...":"创建管理员账户"}),e.jsx("div",{className:"text-center",children:e.jsx("button",{type:"button",onClick:b,disabled:x>0||d,className:"text-sm text-blue-500 hover:text-blue-600 disabled:text-muted-foreground",children:x>0?`${x}秒后可重新发送`:"重新发送验证码"})})]}),e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"首个注册的用户将成为管理员"})})]})})}):e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx(Vr,{size:64})}),e.jsxs("h1",{className:"text-2xl font-bold text-foreground",children:["欢迎使用 ",Ve]}),e.jsx("p",{className:"text-muted-foreground mt-2",children:"系统初始化"})]}),e.jsxs("div",{className:"p-4 bg-yellow-100 dark:bg-yellow-900/20 border border-yellow-300 dark:border-yellow-800 rounded-md",children:[e.jsx("p",{className:"text-sm text-yellow-700 dark:text-yellow-400",children:"SMTP 邮件服务未配置。请联系管理员配置以下环境变量后重启服务:"}),e.jsxs("ul",{className:"mt-2 text-sm text-yellow-700 dark:text-yellow-400 list-disc list-inside",children:[e.jsx("li",{children:"SMTP_SERVER"}),e.jsx("li",{children:"SMTP_PORT"}),e.jsx("li",{children:"SMTP_USERNAME"}),e.jsx("li",{children:"SMTP_PASSWORD"})]})]})]})})})},Kc=()=>{const[r,o]=n.useState("email"),[l,u]=n.useState("email"),[c,m]=n.useState(""),[d,s]=n.useState(""),[p,t]=n.useState(""),[x,h]=n.useState(""),[a,i]=n.useState(!1),[g,v]=n.useState(""),[k,b]=n.useState(0),[j,f]=n.useState(!1),{login:w,sendCode:S,verifyCode:z,smtpConfigured:D}=Ot();n.useEffect(()=>{if(k>0){const _=setTimeout(()=>b(k-1),1e3);return()=>clearTimeout(_)}},[k]),n.useEffect(()=>{D||o("password")},[D]);const N=async _=>{if(_.preventDefault(),v(""),!c||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(c)){v("请输入有效的邮箱地址");return}i(!0);const ne=await S(c);ne.success?(u("code"),b(60),f(ne.type==="register")):(v(ne.error),ne.waitSeconds&&b(ne.waitSeconds)),i(!1)},R=async _=>{if(_.preventDefault(),v(""),!d||d.length!==6){v("请输入6位验证码");return}i(!0);const te=await z(c,d);te.success||v(te.error),i(!1)},M=async()=>{if(k>0)return;v(""),i(!0);const _=await S(c);_.success?b(60):v(_.error),i(!1)},E=async _=>{if(_.preventDefault(),v(""),!p||!x){v("请输入用户名和密码");return}i(!0);const te=await w(p,x);te.success||v(te.error),i(!1)},$=()=>{u("email"),s(""),v("")},T=()=>{o("email"),u("email"),v("")},X=()=>{o("password"),v("")};return e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx("img",{src:"/logo.svg",className:"w-16 h-16",alt:Ve})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:r==="email"?l==="email"?`欢迎使用 ${Ve}`:j?"创建您的账户":"验证您的身份":"欢迎回来"}),e.jsx("p",{className:"text-muted-foreground mt-2",children:r==="email"?l==="email"?"输入邮箱以接收验证码":`验证码已发送至 ${c}`:"使用账号密码登录"})]}),r==="email"&&l==="email"&&e.jsxs("form",{onSubmit:N,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"email",className:"block text-sm font-medium text-foreground mb-1",children:"邮箱地址"}),e.jsxs("div",{className:"relative",children:[e.jsx(Yr,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"email",id:"email",value:c,onChange:_=>m(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入邮箱地址",required:!0,disabled:a,autoComplete:"email"})]})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a||k>0,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"发送中...":k>0?`${k}秒后可重新发送`:"获取验证码"})]}),r==="email"&&l==="code"&&e.jsxs("form",{onSubmit:R,className:"space-y-4",children:[e.jsxs("button",{type:"button",onClick:$,className:"flex items-center text-sm text-muted-foreground hover:text-foreground",children:[e.jsx(Qt,{className:"w-4 h-4 mr-1"}),"返回修改邮箱"]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"code",className:"block text-sm font-medium text-foreground mb-1",children:"验证码"}),e.jsx("input",{type:"text",id:"code",value:d,onChange:_=>s(_.target.value.replace(/\D/g,"").slice(0,6)),className:"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground text-center text-2xl tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"000000",required:!0,disabled:a,maxLength:6,autoComplete:"one-time-code"})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a||d.length!==6,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"验证中...":j?"创建账户并登录":"登录"}),e.jsx("div",{className:"text-center",children:e.jsx("button",{type:"button",onClick:M,disabled:k>0||a,className:"text-sm text-blue-500 hover:text-blue-600 disabled:text-muted-foreground",children:k>0?`${k}秒后可重新发送`:"重新发送验证码"})})]}),r==="password"&&e.jsxs("form",{onSubmit:E,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"username",className:"block text-sm font-medium text-foreground mb-1",children:"用户名"}),e.jsxs("div",{className:"relative",children:[e.jsx(An,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"text",id:"username",value:p,onChange:_=>t(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入用户名",required:!0,disabled:a})]})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"password",className:"block text-sm font-medium text-foreground mb-1",children:"密码"}),e.jsxs("div",{className:"relative",children:[e.jsx(Ka,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"password",id:"password",value:x,onChange:_=>h(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入密码",required:!0,disabled:a})]})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"登录中...":"登录"})]}),e.jsx("div",{className:"text-center pt-4 border-t border-border",children:r==="email"&&D?e.jsx("button",{type:"button",onClick:X,className:"text-sm text-muted-foreground hover:text-foreground",children:"使用账号密码登录"}):r==="password"&&D?e.jsx("button",{type:"button",onClick:T,className:"text-sm text-muted-foreground hover:text-foreground",children:"使用邮箱验证码登录"}):null})]})})})},Vc=()=>e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx("img",{src:"/logo.svg",alt:Ve,className:"w-16 h-16"})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground mb-2",children:Ve}),e.jsxs("div",{className:"flex items-center justify-center space-x-2",children:[e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce"}),e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce",style:{animationDelay:"0.1s"}}),e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce",style:{animationDelay:"0.2s"}})]}),e.jsx("p",{className:"text-muted-foreground mt-2",children:"加载中..."})]})}),Zc=({children:r})=>{const{user:o,isLoading:l,needsSetup:u}=Ot();return l?e.jsx(Vc,{}):u?e.jsx(qc,{}):o?r:e.jsx(Kc,{})};function Mn(r,o){const[l,u]=n.useState(()=>{if(typeof window>"u")return o;try{const m=window.localStorage.getItem(r);return m?JSON.parse(m):o}catch(m){return console.log(m),o}});return[l,m=>{if(!(typeof window>"u"))try{const d=m instanceof Function?m(l):m;window.localStorage.setItem(r,JSON.stringify(d)),u(d)}catch(d){console.log(d)}}]}function Ko(){const r=Qr(),{sessionId:o}=Vo(),{limitStatus:l,setLimitStatus:u,checkLimitStatus:c,user:m,isAdmin:d}=Ot(),[s,p]=n.useState([]),[t,x]=n.useState(null),[h,a]=n.useState(null),[i,g]=n.useState("chat"),[v,k]=n.useState(!1),[b,j]=n.useState(!1),[f,w]=n.useState(!0),[S,z]=n.useState(!1),[D,N]=n.useState(!1),[R,M]=n.useState(!1),[E,$]=n.useState("shared_projects"),[T,X]=Mn("autoScrollToBottom",!0),[_,te]=Mn("sendByCtrlEnter",!1),[ne,G]=Mn("sidebarVisible",!0),[le,de]=n.useState(!1),[fe,Ee]=n.useState(null),ge=mt.useRef(null),[Me,Fe]=n.useState(new Set),[ae,Ne]=n.useState(new Set),[He,Be]=n.useState(0),{ws:he,sendMessage:Oe,messages:De}=Ps(),Ye=n.useCallback(Y=>{Ee(Y),de(!0)},[]),[Te,Je]=n.useState(!1);n.useEffect(()=>{const Y=()=>{const ie=window.matchMedia("(display-mode: standalone)").matches||window.navigator.standalone||document.referrer.includes("android-app://");Je(ie),document.addEventListener("touchstart",{}),ie?(document.documentElement.classList.add("pwa-mode"),document.body.classList.add("pwa-mode")):(document.documentElement.classList.remove("pwa-mode"),document.body.classList.remove("pwa-mode"))};return Y(),window.matchMedia("(display-mode: standalone)").addEventListener("change",Y),()=>{window.matchMedia("(display-mode: standalone)").removeEventListener("change",Y)}},[]),n.useEffect(()=>{const Y=()=>{k(window.innerWidth<768)};return Y(),window.addEventListener("resize",Y),()=>window.removeEventListener("resize",Y)},[]),n.useEffect(()=>{Re()},[]);const Ce=(Y,ie,ce,Ae)=>{if(!ce||!Ae)return!0;const Xe=Y?.find(Pe=>Pe.name===ce.name),Le=ie?.find(Pe=>Pe.name===ce.name);if(!Xe||!Le)return!1;const oe=Xe.sessions?.find(Pe=>Pe.id===Ae.id),ye=Le.sessions?.find(Pe=>Pe.id===Ae.id);return!oe||!ye?!1:oe.id===ye.id&&oe.title===ye.title&&oe.created_at===ye.created_at&&oe.updated_at===ye.updated_at};n.useEffect(()=>{if(De.length>0){const Y=De[De.length-1];if(Y.type==="projects_updated"){const ie=Y.timestamp;if(ie&&ie===ge.current)return;if(ge.current=ie||null,Y.changedFile&&h&&t){const Le=Y.changedFile.replace(/\\/g,"/").split("/");Le.length>=2&&Le[Le.length-1].replace(".jsonl","")===h.id&&(Me.has(h.id)||Be(Pe=>Pe+1))}if(h&&Me.has(h.id)||Me.size>0&&Array.from(Me).some(Xe=>Xe.startsWith("new-session-"))){const Xe=Y.projects;if(!Ce(s,Xe,t,h))return}const Ae=Y.projects;if(p(Ae),t){const Xe=Ae.find(Le=>Le.name===t.name);Xe&&(JSON.stringify(Xe)!==JSON.stringify(t)&&x(Xe),h&&([...Xe.sessions||[]].find(ye=>ye.id===h.id)||a(null)))}}}},[De,t,h,Me]);const Re=async()=>{try{w(!0);const ie=await(await me.projects()).json();p(ce=>ce.length===0||ie.some((Xe,Le)=>{const oe=ce[Le];return oe?Xe.name!==oe.name||Xe.displayName!==oe.displayName||Xe.fullPath!==oe.fullPath||JSON.stringify(Xe.sessionMeta)!==JSON.stringify(oe.sessionMeta)||JSON.stringify(Xe.sessions)!==JSON.stringify(oe.sessions)||JSON.stringify(Xe.agentInfo)!==JSON.stringify(oe.agentInfo):!0})||ie.length!==ce.length?ie:ce)}catch(Y){console.error("Error fetching projects:",Y)}finally{w(!1)}};window.refreshProjects=Re,window.openSettings=n.useCallback((Y="tools")=>{$(Y),N(!0)},[]),window.openAdminPanel=n.useCallback(()=>{M(!0)},[]),n.useEffect(()=>{if(o&&s.length>0){const Y=!h||h.id!==o;for(const ie of s){let ce=ie.sessions?.find(Ae=>Ae.id===o);if(ce){x(ie),a({...ce,__provider:"claude"}),Y&&g("chat");return}}}},[o,s,r]);const $e=Y=>{x(Y),a(null),r("/app"),v&&j(!1)},Ie=Y=>{if(a(Y),i!=="git"&&i!=="preview"&&g("chat"),v){const ie=Y.__projectName,ce=t?.name;ie!==ce&&j(!1)}r(`/app/session/${Y.id}`)},ze=Y=>{x(Y),a(null),g("chat"),r("/app"),v&&j(!1)},Ze=Y=>{h?.id===Y&&(a(null),r("/app")),p(ie=>ie.map(ce=>({...ce,sessions:ce.sessions?.filter(Ae=>Ae.id!==Y)||[],sessionMeta:{...ce.sessionMeta,total:Math.max(0,(ce.sessionMeta?.total||0)-1)}})))},Qe=async()=>{try{const ie=await(await me.projects()).json();if(p(ce=>ie.some((Xe,Le)=>{const oe=ce[Le];return oe?Xe.name!==oe.name||Xe.displayName!==oe.displayName||Xe.fullPath!==oe.fullPath||JSON.stringify(Xe.sessionMeta)!==JSON.stringify(oe.sessionMeta)||JSON.stringify(Xe.sessions)!==JSON.stringify(oe.sessions):!0})||ie.length!==ce.length?ie:ce),t){const ce=ie.find(Ae=>Ae.name===t.name);if(ce&&(JSON.stringify(ce)!==JSON.stringify(t)&&x(ce),h)){const Ae=ce.sessions?.find(Xe=>Xe.id===h.id);Ae&&JSON.stringify(Ae)!==JSON.stringify(h)&&a(Ae)}}}catch(Y){console.error("Error refreshing sidebar:",Y)}},K=Y=>{t?.name===Y&&(x(null),a(null),r("/app")),p(ie=>ie.filter(ce=>ce.name!==Y))},B=n.useCallback(Y=>{Y&&Fe(ie=>new Set([...ie,Y]))},[]),C=n.useCallback(Y=>{Y&&Fe(ie=>{const ce=new Set(ie);return ce.delete(Y),ce})},[]),V=n.useCallback(Y=>{Y&&Ne(ie=>new Set([...ie,Y]))},[]),I=n.useCallback(Y=>{Y&&Ne(ie=>{const ce=new Set(ie);return ce.delete(Y),ce})},[]),re=n.useCallback(Y=>{Y&&Fe(ie=>{const ce=new Set;for(const Ae of ie)Ae.startsWith("new-session-")||ce.add(Ae);return ce.add(Y),ce})},[]);return e.jsxs("div",{className:"fixed inset-0 flex bg-background",children:[!v&&e.jsx("div",{className:`h-full flex-shrink-0 border-r border-border bg-card transition-all duration-300 ${ne?"w-80":"w-14"}`,children:e.jsx("div",{className:"h-full overflow-hidden",children:ne?e.jsx(So,{projects:s,selectedProject:t,selectedSession:h,onProjectSelect:$e,onSessionSelect:Ie,onNewSession:ze,onSessionDelete:Ze,onProjectDelete:K,isLoading:f,onRefresh:Qe,onShowSettings:()=>N(!0),onShowAdmin:()=>M(!0),isPWA:Te,isMobile:v,onToggleSidebar:()=>G(!1)}):e.jsxs("div",{className:"h-full flex flex-col items-center py-4 gap-4",children:[e.jsx("button",{onClick:()=>G(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200 group","aria-label":"Show sidebar",title:"Show sidebar",children:e.jsx("svg",{className:"w-5 h-5 text-foreground group-hover:scale-110 transition-transform",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 5l7 7-7 7M5 5l7 7-7 7"})})}),e.jsx("button",{onClick:()=>N(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200","aria-label":"Settings",title:"Settings",children:e.jsx(Ut,{className:"w-5 h-5 text-muted-foreground hover:text-foreground transition-colors"})}),d&&e.jsx("button",{onClick:()=>M(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200","aria-label":"Admin",title:"管理",children:e.jsx(Gt,{className:"w-5 h-5 text-muted-foreground hover:text-foreground transition-colors"})})]})})}),v&&e.jsxs("div",{className:`fixed inset-0 z-50 flex transition-all duration-150 ease-out ${b?"opacity-100 visible":"opacity-0 invisible"}`,children:[e.jsx("button",{className:"fixed inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-150 ease-out",onClick:Y=>{Y.stopPropagation(),j(!1)},onTouchStart:Y=>{Y.preventDefault(),Y.stopPropagation(),j(!1)},"aria-label":"Close sidebar"}),e.jsx("div",{className:`relative w-[85vw] max-w-sm sm:w-80 h-full bg-card border-r border-border transform transition-transform duration-150 ease-out ${b?"translate-x-0":"-translate-x-full"}`,onClick:Y=>Y.stopPropagation(),onTouchStart:Y=>Y.stopPropagation(),children:e.jsx(So,{projects:s,selectedProject:t,selectedSession:h,onProjectSelect:$e,onSessionSelect:Ie,onNewSession:ze,onSessionDelete:Ze,onProjectDelete:K,isLoading:f,onRefresh:Qe,onShowSettings:()=>N(!0),onShowAdmin:()=>M(!0),isPWA:Te,isMobile:v,onToggleSidebar:()=>G(!1)})})]}),e.jsx("div",{className:`flex-1 flex flex-col min-w-0 ${v&&!S?"pb-mobile-nav":""}`,children:e.jsx(Fl,{selectedProject:t,selectedSession:h,activeTab:i,setActiveTab:g,ws:he,sendMessage:Oe,messages:De,isMobile:v,isPWA:Te,onMenuClick:()=>j(!0),isLoading:f,onInputFocusChange:z,onSessionActive:B,onSessionInactive:C,onSessionProcessing:V,onSessionNotProcessing:I,processingSessions:ae,onReplaceTemporarySession:re,onNavigateToSession:Y=>r(`/app/session/${Y}`),onShowSettings:()=>N(!0),autoScrollToBottom:T,sendByCtrlEnter:_,externalMessageUpdate:He,limitStatus:l,onLimitBlocked:Ye,checkLimitStatus:c})}),v&&e.jsx(Hl,{activeTab:i,setActiveTab:g,isInputFocused:S}),e.jsx(jc,{isOpen:D,onClose:()=>N(!1),projects:s,initialTab:E,autoScrollToBottom:T,onAutoScrollChange:X,sendByCtrlEnter:_,onSendByCtrlEnterChange:te}),e.jsx(zc,{isOpen:R,onClose:()=>M(!1)}),e.jsx(Rc,{isOpen:le,limitType:fe,onClose:()=>de(!1)})]})}function Qc(){return e.jsx(fi,{children:e.jsx($l,{children:e.jsx(pi,{children:e.jsx(Zc,{children:e.jsxs(Zo,{children:[e.jsx(dr,{index:!0,element:e.jsx(Ko,{})}),e.jsx(dr,{path:"session/:sessionId",element:e.jsx(Ko,{})})]})})})})})}function ed(){return e.jsx(Bl,{children:e.jsx(ka,{children:e.jsxs(Zo,{children:[e.jsx(dr,{path:"/",element:e.jsx(Hc,{})}),e.jsx(dr,{path:"/demo",element:e.jsx(Gc,{})}),e.jsx(dr,{path:"/share/:userUuid/:sessionId",element:e.jsx(Yc,{})}),e.jsx(dr,{path:"/app/*",element:e.jsx(Qc,{})})]})})})}si.createRoot(document.getElementById("root")).render(e.jsx(mt.StrictMode,{children:e.jsx(ed,{})}));
199
+ `).map((u,c)=>e.jsxs(mt.Fragment,{children:[c>0&&e.jsx("br",{}),u]},c))})]},l))})]})}function Gc(){const r=Qr(),{isDarkMode:o,toggleDarkMode:l}=no(),[u,c]=n.useState(!1);return n.useEffect(()=>{const m=()=>c(window.scrollY>50);return window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]),n.useEffect(()=>{window.scrollTo(0,0)},[]),n.useEffect(()=>{const m=new IntersectionObserver(d=>{d.forEach(s=>{s.isIntersecting&&(s.target.classList.add("visible"),m.unobserve(s.target))})},{threshold:.1});return document.querySelectorAll(".lp-fade-up").forEach(d=>m.observe(d)),()=>m.disconnect()},[]),e.jsxs("div",{className:"landing-page",children:[e.jsx("div",{className:"bg-orb orb-1"}),e.jsx("div",{className:"bg-orb orb-2"}),e.jsx("div",{className:"bg-grid"}),e.jsxs("nav",{className:`lp-navbar${u?" scrolled":""}`,children:[e.jsxs(qt,{to:"/",className:"lp-logo",children:[e.jsx("img",{className:"lp-logo-icon",src:"/logo.svg",alt:"AgentHub"}),e.jsx("span",{children:"AgentHub"})]}),e.jsx("ul",{className:"lp-nav-links",children:e.jsx("li",{children:e.jsxs(qt,{to:"/",style:{display:"inline-flex",alignItems:"center",gap:"0.4rem"},children:[e.jsx(Qt,{size:16})," 返回首页"]})})}),e.jsxs("div",{className:"lp-nav-right",children:[e.jsx("button",{className:"lp-theme-toggle",onClick:l,title:o?"切换到亮色":"切换到暗色",children:o?e.jsx(Gr,{size:18}):e.jsx(Ur,{size:18})}),e.jsx("button",{className:"lp-btn lp-btn-primary",onClick:()=>r("/app"),children:"开始使用"})]})]}),e.jsxs("main",{children:[e.jsxs("section",{className:"demo-hero",children:[e.jsxs("h1",{children:["看看 ",e.jsx("span",{className:"gradient-text",children:"AgentHub"})," 能做什么"]}),e.jsx("p",{children:"以下是几个真实的使用场景,展示 AI Agent 如何帮你解决工作中的实际问题。"})]}),e.jsx("section",{className:"demo-scenarios",children:Bc.map((m,d)=>e.jsxs("div",{className:"demo-scenario lp-fade-up",children:[e.jsxs("div",{className:"demo-scenario-info",children:[e.jsx("span",{className:`demo-scenario-tag ${m.tagClass}`,children:m.tag}),e.jsx("h2",{children:m.title}),e.jsx("p",{children:m.description}),e.jsx("ul",{className:"demo-highlights",children:m.highlights.map((s,p)=>e.jsx("li",{children:s},p))})]}),e.jsx(Uc,{messages:m.messages})]},d))}),e.jsxs("section",{className:"demo-cta",children:[e.jsx("h2",{children:"准备好开始了吗?"}),e.jsx("p",{children:"立即体验 AgentHub,让 AI 成为你的超级助手。"}),e.jsx("button",{className:"lp-btn lp-btn-primary lp-btn-large",onClick:()=>r("/app"),children:"开始使用"})]})]}),e.jsx("footer",{className:"lp-footer",children:e.jsxs("div",{className:"lp-footer-content",children:[e.jsxs(qt,{to:"/",className:"lp-logo",children:[e.jsx("img",{className:"lp-logo-icon",src:"/logo.svg",alt:"AgentHub"}),e.jsx("span",{children:"AgentHub"})]}),e.jsxs("p",{className:"lp-copyright",children:["© ",new Date().getFullYear()," AgentHub. All rights reserved."]})]})})]})}function Yc(){const{userUuid:r,sessionId:o}=Vo(),[l,u]=n.useState(null),[c,m]=n.useState(null),[d,s]=n.useState(!0);if(n.useEffect(()=>{fetch(`/api/share/${r}/${o}`).then(g=>g.ok?g.json():Promise.reject(g.status)).then(g=>{u(g),document.title=`${g.title||"对话分享"} - ${Ve}`}).catch(g=>{m(g===404?"not_found":"error")}).finally(()=>s(!1))},[r,o]),d)return e.jsx("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-3"}),e.jsx("p",{className:"text-gray-500 text-sm",children:"加载中..."})]})});if(c)return e.jsx("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center",children:e.jsxs("div",{className:"text-center px-6 max-w-sm",children:[e.jsx("div",{className:"w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4",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:1.5,d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"})})}),e.jsx("h1",{className:"text-lg font-semibold text-gray-900 mb-2",children:c==="not_found"?"分享已关闭或不存在":"加载失败"}),e.jsx("p",{className:"text-sm text-gray-500",children:c==="not_found"?"该对话分享链接已失效或被关闭。":"加载分享内容时发生错误,请稍后重试。"}),e.jsxs("a",{href:jo,className:"mt-6 inline-block text-sm text-blue-600 hover:underline",children:["前往 ",Ve]})]})});const{mode:p,title:t,projectName:x,messages:h=[],sharerName:a,generatedAt:i}=l;return e.jsxs("div",{className:"min-h-screen bg-gray-50 font-sans",children:[e.jsx("div",{className:"bg-white border-b border-gray-200 sticky top-0 z-10",children:e.jsxs("div",{className:"max-w-3xl mx-auto px-4 py-3 flex items-center justify-between",children:[e.jsxs("div",{className:"min-w-0",children:[x&&e.jsx("p",{className:"text-xs text-gray-400 mb-0.5 truncate",children:x}),e.jsx("h1",{className:"text-base font-semibold text-gray-900 truncate",children:t||"对话分享"}),p==="static"&&i&&e.jsxs("p",{className:"text-xs text-gray-400 mt-0.5",children:["静态快照 · ",new Date(i).toLocaleString("zh-CN")]})]}),e.jsxs("span",{className:`ml-3 flex-shrink-0 inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium ${p==="realtime"?"bg-green-100 text-green-700":"bg-blue-100 text-blue-700"}`,children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-current"}),p==="realtime"?"实时":"快照"]})]})}),e.jsx("div",{className:"max-w-3xl mx-auto px-4 py-6 space-y-4",children:h.length===0?e.jsx("div",{className:"text-center text-gray-400 py-16 text-sm",children:"暂无消息"}):h.map((g,v)=>e.jsx(Kc,{message:g,userUuid:r,sessionId:o},g.uuid||v))}),e.jsx("div",{className:"text-center pb-10 pt-4",children:e.jsxs("p",{className:"text-xs text-gray-400",children:[a?`由 ${a} 分享 · `:"","Powered by"," ",e.jsx("a",{href:jo,target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",children:Ve})]})})]})}function Jc(r){if(!r||!r.startsWith("<command-name>")&&!r.startsWith("<command-message>"))return r;const o=r.match(/<command-message>([\s\S]*?)<\/command-message>/);return o?`/${o[1].trim()}`:r}function qc({src:r,alt:o}){const[l,u]=n.useState(!1);return l?e.jsx("div",{className:"rounded-lg bg-blue-500 flex items-center justify-center text-blue-200 text-xs p-4 min-h-[60px]",children:"图片已过期"}):e.jsx("img",{src:r,alt:o,className:"rounded-lg max-w-full h-auto cursor-pointer hover:opacity-90 transition-opacity",onClick:()=>window.open(r,"_blank"),onError:()=>u(!0)})}function Kc({message:r,userUuid:o,sessionId:l}){const u=r.role==="user",c=u?Jc(r.content):r.content,m=r.timestamp?new Date(r.timestamp).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"}):null;return e.jsx("div",{className:`flex ${u?"justify-end":"justify-start"}`,children:e.jsxs("div",{className:`max-w-[96%] ${u?"order-2":"order-1"}`,children:[e.jsxs("div",{className:`flex items-center gap-2 mb-1 ${u?"justify-end":"justify-start"}`,children:[e.jsx("span",{className:`text-xs font-medium ${u?"text-gray-500":"text-blue-600"}`,children:u?"用户":Ve}),m&&e.jsx("span",{className:"text-xs text-gray-400",children:m})]}),e.jsx("div",{className:`rounded-2xl px-4 py-3 ${u?"bg-blue-600 text-white rounded-tr-sm":"bg-white border border-gray-200 text-gray-900 rounded-tl-sm shadow-sm"}`,children:u?e.jsxs(e.Fragment,{children:[c&&e.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:c}),r.images&&r.images.length>0&&e.jsx("div",{className:`grid gap-2 ${r.images.length>1?"grid-cols-2":"grid-cols-1"} ${c?"mt-2":""}`,children:r.images.map(d=>e.jsx(qc,{src:`/api/share/${o}/${l}/images/${d.id}`,alt:d.name||"image"},d.id))})]}):e.jsx("div",{className:"prose prose-sm max-w-none prose-p:my-1 prose-headings:my-2 prose-pre:my-2 prose-ul:my-1 prose-ol:my-1 prose-li:my-0 prose-table:my-2",children:e.jsx(ds,{remarkPlugins:[cs],components:{code({node:d,className:s,children:p,...t}){if(d?.position?.start?.line!==d?.position?.end?.line||String(p).includes(`
200
+ `)){const h=s?.replace("language-","")||"";return e.jsxs("div",{className:"relative group my-2",children:[h&&h!=="text"&&e.jsx("div",{className:"absolute top-2 left-3 z-10 text-xs text-gray-400 font-medium uppercase",children:h}),e.jsx(us,{language:h||"text",style:ys,customStyle:{margin:0,borderRadius:"0.5rem",fontSize:"0.8125rem",padding:h&&h!=="text"?"2rem 1rem 1rem 1rem":"1rem"},codeTagProps:{style:{fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"}},children:String(p).replace(/\n$/,"")})]})}return e.jsx("code",{className:"bg-gray-100 text-gray-800 rounded px-1 py-0.5 text-xs font-mono",...t,children:p})},a({children:d,href:s,...p}){return e.jsx("a",{href:s,target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",...p,children:d})},table({children:d}){return e.jsx("div",{className:"overflow-x-auto",children:e.jsx("table",{className:"min-w-full border-collapse text-xs",children:d})})},th({children:d}){return e.jsx("th",{className:"border border-gray-300 px-2 py-1 bg-gray-50 font-semibold text-left",children:d})},td({children:d}){return e.jsx("td",{className:"border border-gray-300 px-2 py-1",children:d})}},children:r.content})})})]})})}const Vc=()=>{const[r,o]=n.useState("email"),[l,u]=n.useState(""),[c,m]=n.useState(""),[d,s]=n.useState(!1),[p,t]=n.useState(""),[x,h]=n.useState(0),{sendCode:a,verifyCode:i,smtpConfigured:g}=Ot();n.useEffect(()=>{if(x>0){const f=setTimeout(()=>h(x-1),1e3);return()=>clearTimeout(f)}},[x]);const v=async f=>{if(f.preventDefault(),t(""),!l||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(l)){t("请输入有效的邮箱地址");return}s(!0);const S=await a(l);S.success?(o("code"),h(60)):(t(S.error),S.waitSeconds&&h(S.waitSeconds)),s(!1)},k=async f=>{if(f.preventDefault(),t(""),!c||c.length!==6){t("请输入6位验证码");return}s(!0);const w=await i(l,c);w.success||t(w.error),s(!1)},b=async()=>{if(x>0)return;t(""),s(!0);const f=await a(l);f.success?h(60):t(f.error),s(!1)},j=()=>{o("email"),m(""),t("")};return g?e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx(Vr,{size:64})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:r==="email"?`欢迎使用 ${Ve}`:"创建管理员账户"}),e.jsx("p",{className:"text-muted-foreground mt-2",children:r==="email"?"输入邮箱创建管理员账户":`验证码已发送至 ${l}`})]}),r==="email"&&e.jsxs("form",{onSubmit:v,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"email",className:"block text-sm font-medium text-foreground mb-1",children:"邮箱地址"}),e.jsxs("div",{className:"relative",children:[e.jsx(Yr,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"email",id:"email",value:l,onChange:f=>u(f.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入邮箱地址",required:!0,disabled:d,autoComplete:"email"})]})]}),p&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:p})}),e.jsx("button",{type:"submit",disabled:d||x>0,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:d?"发送中...":x>0?`${x}秒后可重新发送`:"获取验证码"})]}),r==="code"&&e.jsxs("form",{onSubmit:k,className:"space-y-4",children:[e.jsxs("button",{type:"button",onClick:j,className:"flex items-center text-sm text-muted-foreground hover:text-foreground",children:[e.jsx(Qt,{className:"w-4 h-4 mr-1"}),"返回修改邮箱"]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"code",className:"block text-sm font-medium text-foreground mb-1",children:"验证码"}),e.jsx("input",{type:"text",id:"code",value:c,onChange:f=>m(f.target.value.replace(/\D/g,"").slice(0,6)),className:"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground text-center text-2xl tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"000000",required:!0,disabled:d,maxLength:6,autoComplete:"one-time-code"})]}),p&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:p})}),e.jsx("button",{type:"submit",disabled:d||c.length!==6,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:d?"创建中...":"创建管理员账户"}),e.jsx("div",{className:"text-center",children:e.jsx("button",{type:"button",onClick:b,disabled:x>0||d,className:"text-sm text-blue-500 hover:text-blue-600 disabled:text-muted-foreground",children:x>0?`${x}秒后可重新发送`:"重新发送验证码"})})]}),e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"首个注册的用户将成为管理员"})})]})})}):e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx(Vr,{size:64})}),e.jsxs("h1",{className:"text-2xl font-bold text-foreground",children:["欢迎使用 ",Ve]}),e.jsx("p",{className:"text-muted-foreground mt-2",children:"系统初始化"})]}),e.jsxs("div",{className:"p-4 bg-yellow-100 dark:bg-yellow-900/20 border border-yellow-300 dark:border-yellow-800 rounded-md",children:[e.jsx("p",{className:"text-sm text-yellow-700 dark:text-yellow-400",children:"SMTP 邮件服务未配置。请联系管理员配置以下环境变量后重启服务:"}),e.jsxs("ul",{className:"mt-2 text-sm text-yellow-700 dark:text-yellow-400 list-disc list-inside",children:[e.jsx("li",{children:"SMTP_SERVER"}),e.jsx("li",{children:"SMTP_PORT"}),e.jsx("li",{children:"SMTP_USERNAME"}),e.jsx("li",{children:"SMTP_PASSWORD"})]})]})]})})})},Zc=()=>{const[r,o]=n.useState("email"),[l,u]=n.useState("email"),[c,m]=n.useState(""),[d,s]=n.useState(""),[p,t]=n.useState(""),[x,h]=n.useState(""),[a,i]=n.useState(!1),[g,v]=n.useState(""),[k,b]=n.useState(0),[j,f]=n.useState(!1),{login:w,sendCode:S,verifyCode:z,smtpConfigured:D}=Ot();n.useEffect(()=>{if(k>0){const _=setTimeout(()=>b(k-1),1e3);return()=>clearTimeout(_)}},[k]),n.useEffect(()=>{D||o("password")},[D]);const N=async _=>{if(_.preventDefault(),v(""),!c||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(c)){v("请输入有效的邮箱地址");return}i(!0);const ne=await S(c);ne.success?(u("code"),b(60),f(ne.type==="register")):(v(ne.error),ne.waitSeconds&&b(ne.waitSeconds)),i(!1)},R=async _=>{if(_.preventDefault(),v(""),!d||d.length!==6){v("请输入6位验证码");return}i(!0);const te=await z(c,d);te.success||v(te.error),i(!1)},M=async()=>{if(k>0)return;v(""),i(!0);const _=await S(c);_.success?b(60):v(_.error),i(!1)},E=async _=>{if(_.preventDefault(),v(""),!p||!x){v("请输入用户名和密码");return}i(!0);const te=await w(p,x);te.success||v(te.error),i(!1)},$=()=>{u("email"),s(""),v("")},T=()=>{o("email"),u("email"),v("")},X=()=>{o("password"),v("")};return e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsx("div",{className:"w-full max-w-md",children:e.jsxs("div",{className:"bg-card rounded-lg shadow-lg border border-border p-8 space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx("img",{src:"/logo.svg",className:"w-16 h-16",alt:Ve})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:r==="email"?l==="email"?`欢迎使用 ${Ve}`:j?"创建您的账户":"验证您的身份":"欢迎回来"}),e.jsx("p",{className:"text-muted-foreground mt-2",children:r==="email"?l==="email"?"输入邮箱以接收验证码":`验证码已发送至 ${c}`:"使用账号密码登录"})]}),r==="email"&&l==="email"&&e.jsxs("form",{onSubmit:N,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"email",className:"block text-sm font-medium text-foreground mb-1",children:"邮箱地址"}),e.jsxs("div",{className:"relative",children:[e.jsx(Yr,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"email",id:"email",value:c,onChange:_=>m(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入邮箱地址",required:!0,disabled:a,autoComplete:"email"})]})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a||k>0,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"发送中...":k>0?`${k}秒后可重新发送`:"获取验证码"})]}),r==="email"&&l==="code"&&e.jsxs("form",{onSubmit:R,className:"space-y-4",children:[e.jsxs("button",{type:"button",onClick:$,className:"flex items-center text-sm text-muted-foreground hover:text-foreground",children:[e.jsx(Qt,{className:"w-4 h-4 mr-1"}),"返回修改邮箱"]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"code",className:"block text-sm font-medium text-foreground mb-1",children:"验证码"}),e.jsx("input",{type:"text",id:"code",value:d,onChange:_=>s(_.target.value.replace(/\D/g,"").slice(0,6)),className:"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground text-center text-2xl tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"000000",required:!0,disabled:a,maxLength:6,autoComplete:"one-time-code"})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a||d.length!==6,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"验证中...":j?"创建账户并登录":"登录"}),e.jsx("div",{className:"text-center",children:e.jsx("button",{type:"button",onClick:M,disabled:k>0||a,className:"text-sm text-blue-500 hover:text-blue-600 disabled:text-muted-foreground",children:k>0?`${k}秒后可重新发送`:"重新发送验证码"})})]}),r==="password"&&e.jsxs("form",{onSubmit:E,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"username",className:"block text-sm font-medium text-foreground mb-1",children:"用户名"}),e.jsxs("div",{className:"relative",children:[e.jsx(An,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"text",id:"username",value:p,onChange:_=>t(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入用户名",required:!0,disabled:a})]})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"password",className:"block text-sm font-medium text-foreground mb-1",children:"密码"}),e.jsxs("div",{className:"relative",children:[e.jsx(Ka,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-muted-foreground"}),e.jsx("input",{type:"password",id:"password",value:x,onChange:_=>h(_.target.value),className:"w-full pl-10 pr-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"请输入密码",required:!0,disabled:a})]})]}),g&&e.jsx("div",{className:"p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-md",children:e.jsx("p",{className:"text-sm text-red-700 dark:text-red-400",children:g})}),e.jsx("button",{type:"submit",disabled:a,className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200",children:a?"登录中...":"登录"})]}),e.jsx("div",{className:"text-center pt-4 border-t border-border",children:r==="email"&&D?e.jsx("button",{type:"button",onClick:X,className:"text-sm text-muted-foreground hover:text-foreground",children:"使用账号密码登录"}):r==="password"&&D?e.jsx("button",{type:"button",onClick:T,className:"text-sm text-muted-foreground hover:text-foreground",children:"使用邮箱验证码登录"}):null})]})})})},Qc=()=>e.jsx("div",{className:"min-h-screen bg-background flex items-center justify-center p-4",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx("img",{src:"/logo.svg",alt:Ve,className:"w-16 h-16"})}),e.jsx("h1",{className:"text-2xl font-bold text-foreground mb-2",children:Ve}),e.jsxs("div",{className:"flex items-center justify-center space-x-2",children:[e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce"}),e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce",style:{animationDelay:"0.1s"}}),e.jsx("div",{className:"w-2 h-2 bg-blue-500 rounded-full animate-bounce",style:{animationDelay:"0.2s"}})]}),e.jsx("p",{className:"text-muted-foreground mt-2",children:"加载中..."})]})}),ed=({children:r})=>{const{user:o,isLoading:l,needsSetup:u}=Ot();return l?e.jsx(Qc,{}):u?e.jsx(Vc,{}):o?r:e.jsx(Zc,{})};function Mn(r,o){const[l,u]=n.useState(()=>{if(typeof window>"u")return o;try{const m=window.localStorage.getItem(r);return m?JSON.parse(m):o}catch(m){return console.log(m),o}});return[l,m=>{if(!(typeof window>"u"))try{const d=m instanceof Function?m(l):m;window.localStorage.setItem(r,JSON.stringify(d)),u(d)}catch(d){console.log(d)}}]}function Ko(){const r=Qr(),{sessionId:o}=Vo(),{limitStatus:l,setLimitStatus:u,checkLimitStatus:c,user:m,isAdmin:d}=Ot(),[s,p]=n.useState([]),[t,x]=n.useState(null),[h,a]=n.useState(null),[i,g]=n.useState("chat"),[v,k]=n.useState(!1),[b,j]=n.useState(!1),[f,w]=n.useState(!0),[S,z]=n.useState(!1),[D,N]=n.useState(!1),[R,M]=n.useState(!1),[E,$]=n.useState("shared_projects"),[T,X]=Mn("autoScrollToBottom",!0),[_,te]=Mn("sendByCtrlEnter",!1),[ne,G]=Mn("sidebarVisible",!0),[le,de]=n.useState(!1),[fe,Ee]=n.useState(null),ge=mt.useRef(null),[Me,Fe]=n.useState(new Set),[ae,Ne]=n.useState(new Set),[He,Be]=n.useState(0),{ws:he,sendMessage:Oe,messages:De}=Ps(),Ye=n.useCallback(Y=>{Ee(Y),de(!0)},[]),[Te,Je]=n.useState(!1);n.useEffect(()=>{const Y=()=>{const ie=window.matchMedia("(display-mode: standalone)").matches||window.navigator.standalone||document.referrer.includes("android-app://");Je(ie),document.addEventListener("touchstart",{}),ie?(document.documentElement.classList.add("pwa-mode"),document.body.classList.add("pwa-mode")):(document.documentElement.classList.remove("pwa-mode"),document.body.classList.remove("pwa-mode"))};return Y(),window.matchMedia("(display-mode: standalone)").addEventListener("change",Y),()=>{window.matchMedia("(display-mode: standalone)").removeEventListener("change",Y)}},[]),n.useEffect(()=>{const Y=()=>{k(window.innerWidth<768)};return Y(),window.addEventListener("resize",Y),()=>window.removeEventListener("resize",Y)},[]),n.useEffect(()=>{Re()},[]);const Ce=(Y,ie,ce,Ae)=>{if(!ce||!Ae)return!0;const Xe=Y?.find(Pe=>Pe.name===ce.name),Le=ie?.find(Pe=>Pe.name===ce.name);if(!Xe||!Le)return!1;const oe=Xe.sessions?.find(Pe=>Pe.id===Ae.id),ye=Le.sessions?.find(Pe=>Pe.id===Ae.id);return!oe||!ye?!1:oe.id===ye.id&&oe.title===ye.title&&oe.created_at===ye.created_at&&oe.updated_at===ye.updated_at};n.useEffect(()=>{if(De.length>0){const Y=De[De.length-1];if(Y.type==="projects_updated"){const ie=Y.timestamp;if(ie&&ie===ge.current)return;if(ge.current=ie||null,Y.changedFile&&h&&t){const Le=Y.changedFile.replace(/\\/g,"/").split("/");Le.length>=2&&Le[Le.length-1].replace(".jsonl","")===h.id&&(Me.has(h.id)||Be(Pe=>Pe+1))}if(h&&Me.has(h.id)||Me.size>0&&Array.from(Me).some(Xe=>Xe.startsWith("new-session-"))){const Xe=Y.projects;if(!Ce(s,Xe,t,h))return}const Ae=Y.projects;if(p(Ae),t){const Xe=Ae.find(Le=>Le.name===t.name);Xe&&(JSON.stringify(Xe)!==JSON.stringify(t)&&x(Xe),h&&([...Xe.sessions||[]].find(ye=>ye.id===h.id)||a(null)))}}}},[De,t,h,Me]);const Re=async()=>{try{w(!0);const ie=await(await me.projects()).json();p(ce=>ce.length===0||ie.some((Xe,Le)=>{const oe=ce[Le];return oe?Xe.name!==oe.name||Xe.displayName!==oe.displayName||Xe.fullPath!==oe.fullPath||JSON.stringify(Xe.sessionMeta)!==JSON.stringify(oe.sessionMeta)||JSON.stringify(Xe.sessions)!==JSON.stringify(oe.sessions)||JSON.stringify(Xe.agentInfo)!==JSON.stringify(oe.agentInfo):!0})||ie.length!==ce.length?ie:ce)}catch(Y){console.error("Error fetching projects:",Y)}finally{w(!1)}};window.refreshProjects=Re,window.openSettings=n.useCallback((Y="tools")=>{$(Y),N(!0)},[]),window.openAdminPanel=n.useCallback(()=>{M(!0)},[]),n.useEffect(()=>{if(o&&s.length>0){const Y=!h||h.id!==o;for(const ie of s){let ce=ie.sessions?.find(Ae=>Ae.id===o);if(ce){x(ie),a({...ce,__provider:"claude"}),Y&&g("chat");return}}}},[o,s,r]);const $e=Y=>{x(Y),a(null),r("/app"),v&&j(!1)},Ie=Y=>{if(a(Y),i!=="git"&&i!=="preview"&&g("chat"),v){const ie=Y.__projectName,ce=t?.name;ie!==ce&&j(!1)}r(`/app/session/${Y.id}`)},ze=Y=>{x(Y),a(null),g("chat"),r("/app"),v&&j(!1)},Ze=Y=>{h?.id===Y&&(a(null),r("/app")),p(ie=>ie.map(ce=>({...ce,sessions:ce.sessions?.filter(Ae=>Ae.id!==Y)||[],sessionMeta:{...ce.sessionMeta,total:Math.max(0,(ce.sessionMeta?.total||0)-1)}})))},Qe=async()=>{try{const ie=await(await me.projects()).json();if(p(ce=>ie.some((Xe,Le)=>{const oe=ce[Le];return oe?Xe.name!==oe.name||Xe.displayName!==oe.displayName||Xe.fullPath!==oe.fullPath||JSON.stringify(Xe.sessionMeta)!==JSON.stringify(oe.sessionMeta)||JSON.stringify(Xe.sessions)!==JSON.stringify(oe.sessions):!0})||ie.length!==ce.length?ie:ce),t){const ce=ie.find(Ae=>Ae.name===t.name);if(ce&&(JSON.stringify(ce)!==JSON.stringify(t)&&x(ce),h)){const Ae=ce.sessions?.find(Xe=>Xe.id===h.id);Ae&&JSON.stringify(Ae)!==JSON.stringify(h)&&a(Ae)}}}catch(Y){console.error("Error refreshing sidebar:",Y)}},K=Y=>{t?.name===Y&&(x(null),a(null),r("/app")),p(ie=>ie.filter(ce=>ce.name!==Y))},B=n.useCallback(Y=>{Y&&Fe(ie=>new Set([...ie,Y]))},[]),C=n.useCallback(Y=>{Y&&Fe(ie=>{const ce=new Set(ie);return ce.delete(Y),ce})},[]),V=n.useCallback(Y=>{Y&&Ne(ie=>new Set([...ie,Y]))},[]),I=n.useCallback(Y=>{Y&&Ne(ie=>{const ce=new Set(ie);return ce.delete(Y),ce})},[]),re=n.useCallback(Y=>{Y&&Fe(ie=>{const ce=new Set;for(const Ae of ie)Ae.startsWith("new-session-")||ce.add(Ae);return ce.add(Y),ce})},[]);return e.jsxs("div",{className:"fixed inset-0 flex bg-background",children:[!v&&e.jsx("div",{className:`h-full flex-shrink-0 border-r border-border bg-card transition-all duration-300 ${ne?"w-80":"w-14"}`,children:e.jsx("div",{className:"h-full overflow-hidden",children:ne?e.jsx(So,{projects:s,selectedProject:t,selectedSession:h,onProjectSelect:$e,onSessionSelect:Ie,onNewSession:ze,onSessionDelete:Ze,onProjectDelete:K,isLoading:f,onRefresh:Qe,onShowSettings:()=>N(!0),onShowAdmin:()=>M(!0),isPWA:Te,isMobile:v,onToggleSidebar:()=>G(!1)}):e.jsxs("div",{className:"h-full flex flex-col items-center py-4 gap-4",children:[e.jsx("button",{onClick:()=>G(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200 group","aria-label":"Show sidebar",title:"Show sidebar",children:e.jsx("svg",{className:"w-5 h-5 text-foreground group-hover:scale-110 transition-transform",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 5l7 7-7 7M5 5l7 7-7 7"})})}),e.jsx("button",{onClick:()=>N(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200","aria-label":"Settings",title:"Settings",children:e.jsx(Ut,{className:"w-5 h-5 text-muted-foreground hover:text-foreground transition-colors"})}),d&&e.jsx("button",{onClick:()=>M(!0),className:"p-2 hover:bg-accent rounded-md transition-colors duration-200","aria-label":"Admin",title:"管理",children:e.jsx(Gt,{className:"w-5 h-5 text-muted-foreground hover:text-foreground transition-colors"})})]})})}),v&&e.jsxs("div",{className:`fixed inset-0 z-50 flex transition-all duration-150 ease-out ${b?"opacity-100 visible":"opacity-0 invisible"}`,children:[e.jsx("button",{className:"fixed inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-150 ease-out",onClick:Y=>{Y.stopPropagation(),j(!1)},onTouchStart:Y=>{Y.preventDefault(),Y.stopPropagation(),j(!1)},"aria-label":"Close sidebar"}),e.jsx("div",{className:`relative w-[85vw] max-w-sm sm:w-80 h-full bg-card border-r border-border transform transition-transform duration-150 ease-out ${b?"translate-x-0":"-translate-x-full"}`,onClick:Y=>Y.stopPropagation(),onTouchStart:Y=>Y.stopPropagation(),children:e.jsx(So,{projects:s,selectedProject:t,selectedSession:h,onProjectSelect:$e,onSessionSelect:Ie,onNewSession:ze,onSessionDelete:Ze,onProjectDelete:K,isLoading:f,onRefresh:Qe,onShowSettings:()=>N(!0),onShowAdmin:()=>M(!0),isPWA:Te,isMobile:v,onToggleSidebar:()=>G(!1)})})]}),e.jsx("div",{className:`flex-1 flex flex-col min-w-0 ${v&&!S?"pb-mobile-nav":""}`,children:e.jsx(Fl,{selectedProject:t,selectedSession:h,activeTab:i,setActiveTab:g,ws:he,sendMessage:Oe,messages:De,isMobile:v,isPWA:Te,onMenuClick:()=>j(!0),isLoading:f,onInputFocusChange:z,onSessionActive:B,onSessionInactive:C,onSessionProcessing:V,onSessionNotProcessing:I,processingSessions:ae,onReplaceTemporarySession:re,onNavigateToSession:Y=>r(`/app/session/${Y}`),onShowSettings:()=>N(!0),autoScrollToBottom:T,sendByCtrlEnter:_,externalMessageUpdate:He,limitStatus:l,onLimitBlocked:Ye,checkLimitStatus:c})}),v&&e.jsx(Hl,{activeTab:i,setActiveTab:g,isInputFocused:S}),e.jsx(jc,{isOpen:D,onClose:()=>N(!1),projects:s,initialTab:E,autoScrollToBottom:T,onAutoScrollChange:X,sendByCtrlEnter:_,onSendByCtrlEnterChange:te}),e.jsx(zc,{isOpen:R,onClose:()=>M(!1)}),e.jsx(Rc,{isOpen:le,limitType:fe,onClose:()=>de(!1)})]})}function td(){return e.jsx(fi,{children:e.jsx($l,{children:e.jsx(pi,{children:e.jsx(ed,{children:e.jsxs(Zo,{children:[e.jsx(dr,{index:!0,element:e.jsx(Ko,{})}),e.jsx(dr,{path:"session/:sessionId",element:e.jsx(Ko,{})})]})})})})})}function rd(){return e.jsx(Bl,{children:e.jsx(ka,{children:e.jsxs(Zo,{children:[e.jsx(dr,{path:"/",element:e.jsx(Hc,{})}),e.jsx(dr,{path:"/demo",element:e.jsx(Gc,{})}),e.jsx(dr,{path:"/share/:userUuid/:sessionId",element:e.jsx(Yc,{})}),e.jsx(dr,{path:"/app/*",element:e.jsx(td,{})})]})})})}si.createRoot(document.getElementById("root")).render(e.jsx(mt.StrictMode,{children:e.jsx(rd,{})}));
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-GDRRo6D8.js"></script>
28
+ <script type="module" crossorigin src="/assets/index-aCmB0EwO.js"></script>
29
29
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-C_uEg43g.js">
30
30
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-B2saKA4-.js">
31
31
  <link rel="modulepreload" crossorigin href="/assets/vendor-utils-00TdZexr.js">
@@ -34,7 +34,7 @@
34
34
  <link rel="modulepreload" crossorigin href="/assets/vendor-markdown-Ok8-Lurq.js">
35
35
  <link rel="modulepreload" crossorigin href="/assets/vendor-syntax-CEC-Nb_2.js">
36
36
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-CvdiG4-n.js">
37
- <link rel="stylesheet" crossorigin href="/assets/index-XUGiJSMZ.css">
37
+ <link rel="stylesheet" crossorigin href="/assets/index-BwzA6mGc.css">
38
38
  </head>
39
39
  <body>
40
40
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ian2018cs/agenthub",
3
- "version": "0.1.88",
3
+ "version": "0.1.90",
4
4
  "description": "A web-based UI for AI Agents",
5
5
  "type": "module",
6
6
  "main": "server/index.js",
@@ -1,11 +1,48 @@
1
1
  import express from 'express';
2
- import { shareDb, userDb } from '../database/db.js';
2
+ import fs from 'fs';
3
+ import { shareDb, userDb, imageDb } from '../database/db.js';
4
+ import { getImagePath } from '../services/image-storage.js';
3
5
  import { getSessionMessages, loadProjectConfig } from '../projects.js';
4
- import { extractShareMessages, saveStaticSnapshot, readStaticSnapshot } from '../services/share-renderer.js';
6
+ import { extractShareMessages, saveStaticSnapshot, readStaticSnapshot, stripImagePaths } from '../services/share-renderer.js';
5
7
  import { authenticateToken } from '../middleware/auth.js';
6
8
 
7
9
  const router = express.Router();
8
10
 
11
+ /**
12
+ * 将 imageDb.getImagesBySession 的结果附加到提取后的消息上。
13
+ * message_images 表中 message_content 存储的是原始用户文本(未追加图片路径);
14
+ * 提取后的 msg.content 已经过 stripImagePaths 清洗,两者可直接比较。
15
+ */
16
+ function attachImagesToMessages(messages, sessionImages) {
17
+ if (!sessionImages || sessionImages.length === 0) return;
18
+
19
+ // 按 message_content 分组(可能有多张图片属于同一条消息)
20
+ const contentMap = new Map(); // message_content -> [{id, name}]
21
+ for (const img of sessionImages) {
22
+ const key = img.message_content || '';
23
+ if (!contentMap.has(key)) contentMap.set(key, []);
24
+ contentMap.get(key).push({ id: img.id, name: img.original_name });
25
+ }
26
+
27
+ const usedKeys = new Set();
28
+ for (const msg of messages) {
29
+ if (msg.role !== 'user') continue;
30
+ const content = msg.content || '';
31
+ for (const [mcKey, images] of contentMap) {
32
+ if (usedKeys.has(mcKey)) continue;
33
+ // mcKey 是原始文本(最多 500 字符),content 是完整原始文本(已清洗)
34
+ const matched = mcKey.length > 0
35
+ ? content.startsWith(mcKey) || mcKey.startsWith(content.substring(0, 500))
36
+ : content.length === 0;
37
+ if (matched) {
38
+ msg.images = images;
39
+ usedKeys.add(mcKey);
40
+ break;
41
+ }
42
+ }
43
+ }
44
+ }
45
+
9
46
  // GET /api/share/info/:sessionId — 获取当前用户的分享状态(需要鉴权,必须在 /:userUuid/:sessionId 前定义)
10
47
  router.get('/info/:sessionId', authenticateToken, (req, res) => {
11
48
  const { sessionId } = req.params;
@@ -41,6 +78,8 @@ router.get('/:userUuid/:sessionId', async (req, res) => {
41
78
  try {
42
79
  const rawMessages = await getSessionMessages(share.project_name, sessionId, null, 0, userUuid);
43
80
  const messages = extractShareMessages(rawMessages);
81
+ const sessionImages = imageDb.getImagesBySession(sessionId);
82
+ attachImagesToMessages(messages, sessionImages);
44
83
  return res.json({
45
84
  mode: 'realtime',
46
85
  title: share.session_title || '对话分享',
@@ -59,11 +98,14 @@ router.get('/:userUuid/:sessionId', async (req, res) => {
59
98
  if (!snapshot) {
60
99
  return res.status(500).json({ error: '读取快照失败' });
61
100
  }
101
+ const messages = snapshot.messages || [];
102
+ const sessionImages = imageDb.getImagesBySession(sessionId);
103
+ attachImagesToMessages(messages, sessionImages);
62
104
  return res.json({
63
105
  mode: 'static',
64
106
  title: share.session_title || snapshot.title || '对话分享',
65
107
  projectName: share.project_name,
66
- messages: snapshot.messages || [],
108
+ messages,
67
109
  generatedAt: snapshot.generatedAt,
68
110
  sharerName,
69
111
  });
@@ -113,4 +155,31 @@ router.delete('/:sessionId', authenticateToken, (req, res) => {
113
155
  res.json({ ok: true });
114
156
  });
115
157
 
158
+ // GET /api/share/:userUuid/:sessionId/images/:imageId — 公开访问,分享页图片
159
+ router.get('/:userUuid/:sessionId/images/:imageId', (req, res) => {
160
+ const { userUuid, sessionId, imageId } = req.params;
161
+
162
+ const share = shareDb.getShare(userUuid, sessionId);
163
+ if (!share || share.status !== 'active') {
164
+ return res.status(404).json({ error: '分享不存在或已关闭' });
165
+ }
166
+
167
+ const imgId = parseInt(imageId, 10);
168
+ if (isNaN(imgId)) return res.status(400).json({ error: 'Invalid image ID' });
169
+
170
+ const image = imageDb.getImageById(imgId);
171
+ if (!image || image.user_uuid !== userUuid) {
172
+ return res.status(404).json({ error: 'Image not found' });
173
+ }
174
+
175
+ const filePath = getImagePath(image.user_uuid, image.file_hash, image.file_ext);
176
+ if (!fs.existsSync(filePath)) {
177
+ return res.status(410).json({ error: 'Image expired' });
178
+ }
179
+
180
+ res.setHeader('Content-Type', image.mime_type);
181
+ res.setHeader('Cache-Control', 'public, max-age=3600');
182
+ res.sendFile(filePath);
183
+ });
184
+
116
185
  export default router;
@@ -4,6 +4,20 @@ import fs from 'fs';
4
4
  const DATA_DIR = process.env.DATA_DIR || path.join(process.cwd(), 'data');
5
5
  const SHARE_DIR = path.join(DATA_DIR, 'sharepage');
6
6
 
7
+ const IMAGE_NOTE_MARKER = '\n\n[Images provided at the following paths:]';
8
+ const IMAGE_NOTE_MARKER_ALT = '[Images provided at the following paths:]';
9
+
10
+ /**
11
+ * 去除用户消息文本中由 handleImages 追加的图片路径注释
12
+ */
13
+ export function stripImagePaths(text) {
14
+ if (!text) return text;
15
+ const idx = text.indexOf(IMAGE_NOTE_MARKER);
16
+ if (idx !== -1) return text.slice(0, idx);
17
+ if (text.startsWith(IMAGE_NOTE_MARKER_ALT)) return '';
18
+ return text;
19
+ }
20
+
7
21
  const SKIP_USER_PREFIXES = [
8
22
  '<command-args>',
9
23
  '<local-command-stdout>',
@@ -49,10 +63,13 @@ export function extractShareMessages(rawMessages) {
49
63
  }
50
64
  if (!text) continue;
51
65
  if (SKIP_USER_PREFIXES.some(prefix => text.startsWith(prefix))) continue;
52
- if (text.startsWith('<command-message>')) {
66
+ if (text.startsWith('<command-message>') || text.startsWith('<command-name>')) {
53
67
  const cmd = extractCommandMessage(text);
54
68
  if (!cmd) continue;
55
69
  text = `/${cmd}`;
70
+ } else {
71
+ text = stripImagePaths(text);
72
+ if (!text) continue;
56
73
  }
57
74
 
58
75
  results.push({ role: 'user', content: text, timestamp: msg.timestamp, uuid: msg.uuid });
package/shared/brand.js CHANGED
@@ -17,7 +17,7 @@ export const PRODUCT_FEISHU_CARD_TITLE = `🤖 ${PRODUCT_NAME}`;
17
17
  // 产品 Web 地址(飞书绑定引导文案使用),通过环境变量配置
18
18
  export const PRODUCT_WEB_URL =
19
19
  (typeof process !== 'undefined' && process.env?.PRODUCT_WEB_URL) ||
20
- 'http://localhost:6175';
20
+ 'http://10.0.1.133:6175';
21
21
 
22
22
  // 对话空白页示例提示词(点击后自动填充到输入框)
23
23
  export const CHAT_EXAMPLE_PROMPTS = [