@deepseekcode/cli 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1014 -1004
- package/package.json +2 -2
- package/web/dist/assets/{AgentFlowView-D-nPVDb9.js → AgentFlowView-qR01S0jV.js} +1 -1
- package/web/dist/assets/{AgentsView-DHNgV13S.js → AgentsView-CLvG8aae.js} +1 -1
- package/web/dist/assets/{AuditView-ZCIV7Q0I.js → AuditView-CMYlGV9S.js} +1 -1
- package/web/dist/assets/{AutomationView-By6rBhla.js → AutomationView-wrcdqhJY.js} +1 -1
- package/web/dist/assets/{ChannelConfigView-_cIgiA-O.js → ChannelConfigView-DM70m5RE.js} +1 -1
- package/web/dist/assets/{ConnectorsView-BQQ_k_7I.js → ConnectorsView-B5ndd8pU.js} +1 -1
- package/web/dist/assets/{FileTreeView-DKUEkVqn.js → FileTreeView-DL66cxki.js} +1 -1
- package/web/dist/assets/{HookConfigView-DbkxVuAs.js → HookConfigView-BugHBHlO.js} +2 -2
- package/web/dist/assets/{InboxView-B3ddpq78.js → InboxView-DLPWNrqG.js} +1 -1
- package/web/dist/assets/ModelsView-CwhL9YPX.js +2 -0
- package/web/dist/assets/SessionGrid-CC1NAZ45.js +26 -0
- package/web/dist/assets/SettingsPanel-n1UbEjzX.js +4 -0
- package/web/dist/assets/{SkillsView-BwJowYXS.js → SkillsView-DznSS50I.js} +1 -1
- package/web/dist/assets/{TemplatesTab-BB-6z4z4.js → TemplatesTab-BPD0hvrG.js} +1 -1
- package/web/dist/assets/{TerminalView-D9e8fyOS.js → TerminalView-B4WUBGzA.js} +1 -1
- package/web/dist/assets/{ToolsView-CQ3hybgP.js → ToolsView-CQgPyD6U.js} +1 -1
- package/web/dist/assets/{icons-B5yCkBjC.js → icons-CrV0VGFQ.js} +107 -82
- package/web/dist/assets/index-DMxlsuNM.js +20 -0
- package/web/dist/assets/index-DjWfcgLQ.css +1 -0
- package/web/dist/assets/{markdown-D0iUI0Yw.js → markdown-CaPdHFK5.js} +1 -1
- package/web/dist/assets/panels-B3UcQJtY.js +1 -0
- package/web/dist/assets/{react-vendor-Bxu3r3ox.js → react-vendor-DnYXnA42.js} +1 -1
- package/web/dist/assets/{state-C80Yzgl0.js → state-BHmvnECu.js} +1 -1
- package/web/dist/index.html +6 -6
- package/web/dist/assets/AskQuestionModal-BKkh6JlF.js +0 -1
- package/web/dist/assets/HookApprovalModal-DC_q-If8.js +0 -1
- package/web/dist/assets/HookApprovalPreview-C8fU_Umi.js +0 -3
- package/web/dist/assets/ModelsView-B2N4jMxM.js +0 -1
- package/web/dist/assets/SessionGrid-CnK6naC_.js +0 -23
- package/web/dist/assets/SettingsPanel-czOfv9mx.js +0 -3
- package/web/dist/assets/index-DVZ3Ws5S.css +0 -1
- package/web/dist/assets/index-YAnKQ1Q6.js +0 -20
- package/web/dist/assets/panels-DOT_5rsR.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-
|
|
2
|
-
import{a as j,_ as L}from"./index-YAnKQ1Q6.js";import{j as e}from"./markdown-D0iUI0Yw.js";import{r as N,ap as z,aq as F,ar as M,a4 as U,X as I,ao as $,C as Y,b as G,as as J,ac as B,ad as W,R as q,ak as V,D as X,P as K}from"./icons-B5yCkBjC.js";import{c as Q}from"./state-C80Yzgl0.js";import"./react-vendor-Bxu3r3ox.js";const P=Q((l,o)=>({rules:[],stats:null,events:[],agents:[],loading:!1,error:null,fieldErrors:null,formOpen:!1,editingRule:null,dryRunResult:null,loadRules:async()=>{const s=await j.hooks.list();s.success&&Array.isArray(s.data)?l({rules:s.data}):s.success&&s.data&&!Array.isArray(s.data)?l({error:"服务端返回的规则数据格式异常"}):l({error:s.error||"Failed to load rules"})},loadStats:async()=>{const s=await j.hooks.stats();s.success&&s.data&&l({stats:s.data})},loadEvents:async()=>{const s=await j.hooks.events();s.success&&Array.isArray(s.data)?l({events:s.data}):s.success&&s.data&&!Array.isArray(s.data)&&l({error:"服务端返回的事件数据格式异常"})},loadAgents:async()=>{const s=await j.hooks.agents();s.success&&Array.isArray(s.data)?l({agents:s.data}):s.success&&s.data&&!Array.isArray(s.data)&&l({error:"服务端返回的Agent数据格式异常"})},loadAll:async()=>{l({loading:!0,error:null});try{await Promise.all([o().loadRules(),o().loadStats(),o().loadEvents(),o().loadAgents()])}catch(s){l({error:String(s)})}finally{l({loading:!1})}},createRule:async s=>{l({fieldErrors:null});const r=await j.hooks.create(s);if(r.success)return await o().loadRules(),await o().loadStats(),l({formOpen:!1,editingRule:null}),!0;if(r.error){l({error:r.error});try{const m=JSON.parse(r.error);m.fieldErrors&&l({fieldErrors:m.fieldErrors})}catch{}}return!1},updateRule:async(s,r)=>{l({fieldErrors:null});const m=await j.hooks.update(s,r);return m.success?(await o().loadRules(),l({formOpen:!1,editingRule:null}),!0):(l({error:m.error||"Update failed"}),!1)},deleteRule:async s=>{const r=await j.hooks.delete(s);return r.success?(await o().loadRules(),await o().loadStats(),!0):(l({error:r.error||"Delete failed"}),!1)},batchDelete:async s=>{const r=await j.hooks.batchDelete(s);return r.success?(await o().loadRules(),await o().loadStats(),!0):(l({error:r.error||"Batch delete failed"}),!1)},toggleRule:async(s,r)=>(await j.hooks.toggle(s,r)).success?(l(v=>({rules:v.rules.map(d=>d.name===s?{...d,enabled:r}:d)})),!0):(await o().loadRules(),!1),batchToggle:async(s,r)=>(await j.hooks.batchToggle(s,r)).success?(l(v=>({rules:v.rules.map(d=>s.includes(d.name)?{...d,enabled:r}:d)})),!0):(await o().loadRules(),!1),dryRun:async s=>{const r=await j.hooks.dryRun(s);return r.success&&r.data?(l({dryRunResult:r.data}),r.data):(l({error:r.error||"Dry-run failed"}),null)},openForm:s=>l({formOpen:!0,editingRule:s||null,dryRunResult:null,fieldErrors:null}),closeForm:()=>l({formOpen:!1,editingRule:null,dryRunResult:null,fieldErrors:null}),setDryRunResult:s=>l({dryRunResult:s}),clearError:()=>l({error:null}),clearFieldErrors:()=>l({fieldErrors:null})})),Z={SYSTEM:"bg-accent-red/15 text-accent-red",SECURITY:"bg-accent-orange/15 text-accent-orange",PROJECT:"bg-accent-blue/15 text-accent-blue",USER:"bg-accent-green/15 text-accent-green",PLUGIN:"bg-accent-purple/15 text-accent-purple"},ee={SHELL:"bg-accent-yellow/15 text-accent-yellow",HTTP:"bg-accent-cyan/15 text-accent-cyan",PROMPT:"bg-accent-purple/15 text-accent-purple",AGENT:"bg-accent-blue/15 text-accent-blue"};function te({rules:l,onEdit:o}){const{toggleRule:s,deleteRule:r,batchDelete:m,batchToggle:v}=P(),[d,h]=N.useState(new Set),[T,k]=N.useState(!1),y=Array.isArray(l)?l:[];if(y.length===0)return e.jsxs("div",{className:"flex flex-1 flex-col items-center justify-center gap-3 py-16 text-dark-muted",children:[e.jsx("div",{className:"text-4xl opacity-60",children:"🪝"}),e.jsx("p",{className:"text-sm",children:"暂无 Hook 规则"}),e.jsx("p",{className:"text-xs text-dark-muted/70",children:'点击右上角"新增规则"创建第一个 Hook'})]});const S=t=>{const i=new Set(d);i.has(t)?i.delete(t):i.add(t),h(i),k(i.size===y.length)},f=()=>{T?(h(new Set),k(!1)):(h(new Set(y.map(t=>t.name))),k(!0))},x=()=>{d.size!==0&&confirm(`确认删除 ${d.size} 条规则?`)&&(m(Array.from(d)),h(new Set),k(!1))},p=t=>{d.size!==0&&(v(Array.from(d),t),h(new Set),k(!1))};return e.jsxs("div",{className:"flex flex-1 flex-col min-h-0",children:[d.size>0&&e.jsxs("div",{className:"mb-2 flex items-center gap-2 rounded-lg border border-accent-blue/30 bg-accent-blue/5 px-3 py-1.5 text-sm",children:[e.jsxs("span",{className:"text-dark-muted",children:["已选 ",d.size," 项"]}),e.jsx("button",{onClick:()=>p(!0),className:"rounded bg-accent-green/15 px-2 py-0.5 text-accent-green transition-colors hover:bg-accent-green/25",children:"全部启用"}),e.jsx("button",{onClick:()=>p(!1),className:"rounded bg-dark-hover px-2 py-0.5 text-dark-text transition-colors hover:bg-dark-border",children:"全部禁用"}),e.jsx("button",{onClick:x,className:"rounded bg-accent-red/15 px-2 py-0.5 text-accent-red transition-colors hover:bg-accent-red/25",children:"删除"})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto custom-scrollbar rounded-xl border border-dark-border",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"sticky top-0 bg-dark-hover text-dark-muted",children:e.jsxs("tr",{children:[e.jsx("th",{className:"w-8 p-2.5",children:e.jsx("button",{onClick:f,children:T?e.jsx(z,{size:14}):e.jsx(F,{size:14})})}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"名称"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"事件"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"类型"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"优先级"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"状态"}),e.jsx("th",{className:"p-2.5 text-right font-medium",children:"操作"})]})}),e.jsx("tbody",{className:"divide-y divide-dark-border",children:y.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-dark-hover/50",children:[e.jsx("td",{className:"p-2.5",children:e.jsx("button",{onClick:()=>S(t.name),children:d.has(t.name)?e.jsx(z,{size:14,className:"text-accent-blue"}):e.jsx(F,{size:14,className:"text-dark-muted"})})}),e.jsxs("td",{className:"p-2.5",children:[e.jsx("div",{className:"font-medium text-dark-text",children:t.name}),t.description&&e.jsx("div",{className:"mt-0.5 max-w-[220px] truncate text-xs text-dark-muted",children:t.description})]}),e.jsx("td",{className:"p-2.5",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[Array.isArray(t.events)&&t.events.slice(0,3).map(i=>e.jsx("span",{className:"rounded bg-dark-hover px-1.5 py-0.5 text-xs text-dark-text",children:i},i)),Array.isArray(t.events)&&t.events.length>3&&e.jsxs("span",{className:"px-1 py-0.5 text-xs text-dark-muted",children:["+",t.events.length-3]})]})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:`rounded px-1.5 py-0.5 text-xs font-medium ${ee[t.implementationType]||"bg-dark-hover text-dark-muted"}`,children:t.implementationType})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:`rounded px-1.5 py-0.5 text-xs font-medium ${Z[t.priority]||"bg-dark-hover text-dark-muted"}`,children:t.priority})}),e.jsx("td",{className:"p-2.5",children:e.jsx("button",{onClick:()=>s(t.name,!t.enabled),className:`relative h-5 w-9 rounded-full transition-colors ${t.enabled?"bg-accent-green":"bg-dark-border"}`,title:t.enabled?"点击禁用":"点击启用",children:e.jsx("span",{className:`absolute top-0.5 block h-3.5 w-3.5 rounded-full bg-white transition-all ${t.enabled?"left-[18px]":"left-[2px]"}`})})}),e.jsx("td",{className:"p-2.5",children:e.jsxs("div",{className:"flex items-center justify-end gap-1",children:[e.jsx("button",{onClick:()=>o(t),className:"rounded p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-accent-blue",title:"编辑",children:e.jsx(M,{size:14})}),e.jsx("button",{onClick:()=>{confirm(`删除规则 "${t.name}"?`)&&r(t.name)},className:"rounded p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-accent-red",title:"删除",children:e.jsx(U,{size:14})})]})})]},t.name))})]})})]})}const ae={name:"",description:"",events:[],implementationType:"SHELL",command:"",url:"",promptTemplate:"",agentName:"",priority:"USER",tools:[],matcherToolNamePattern:"",matcherFromState:"",matcherToState:"",timeoutMs:3e4,enabled:!0,failOpen:!0,scope:"project"},se=[{value:"SHELL",label:"Shell 脚本",desc:"执行外部脚本,stdin 接收 JSON,stdout 返回决策"},{value:"HTTP",label:"HTTP 端点",desc:"POST JSON 到外部端点"},{value:"PROMPT",label:"LLM Prompt",desc:"发送单轮 Prompt 给 LLM 做风险评估"},{value:"AGENT",label:"AI Agent",desc:"启动只读子代理做深度调查"}],re=[{value:"SYSTEM",label:"SYSTEM (100)"},{value:"SECURITY",label:"SECURITY (80)"},{value:"PROJECT",label:"PROJECT (60)"},{value:"USER",label:"USER (40)"},{value:"PLUGIN",label:"PLUGIN (20)"}],b=l=>`w-full rounded-lg border bg-dark-bg px-3 py-2 text-sm text-dark-text placeholder-dark-muted/60 transition-colors focus:outline-none focus:ring-2 ${l?"border-accent-red focus:border-accent-red focus:ring-accent-red/20":"border-dark-border focus:border-accent-blue focus:ring-accent-blue/20"}`,g="mb-1 block text-xs font-medium text-dark-muted";function le({events:l,agents:o}){const{editingRule:s,fieldErrors:r,dryRunResult:m,createRule:v,updateRule:d,closeForm:h,dryRun:T,setDryRunResult:k,clearFieldErrors:y}=P(),S=Array.isArray(l)?l:[],f=Array.isArray(o)?o:[],[x,p]=N.useState(0),[t,i]=N.useState(ae),[w,C]=N.useState("");N.useEffect(()=>{var a,n,c;s&&i({name:s.name,description:s.description||"",events:s.events,implementationType:s.implementationType,command:s.command||"",url:s.url||"",promptTemplate:s.promptTemplate||"",agentName:s.agentName||"",priority:s.priority,tools:s.tools||[],matcherToolNamePattern:((a=s.matchers)==null?void 0:a.toolNamePattern)||"",matcherFromState:((n=s.matchers)==null?void 0:n.fromState)||"",matcherToState:((c=s.matchers)==null?void 0:c.toState)||"",timeoutMs:s.timeoutMs,enabled:s.enabled,failOpen:s.failOpen,scope:s.scope||"project"})},[s]);const u=(a,n)=>{i(c=>({...c,[a]:n})),y()},O=a=>{i(n=>({...n,events:n.events.includes(a)?n.events.filter(c=>c!==a):[...n.events,a]}))},A=a=>{const n=a.every(c=>t.events.includes(c));i(n?c=>({...c,events:c.events.filter(R=>!a.includes(R))}):c=>({...c,events:[...new Set([...c.events,...a])]}))},E=async()=>{const a={};t.matcherToolNamePattern&&(a.toolNamePattern=t.matcherToolNamePattern),t.matcherFromState&&(a.fromState=t.matcherFromState),t.matcherToState&&(a.toState=t.matcherToState);const c={...{...t,tools:t.tools.length>0?t.tools:[]}};c.matchers=a,delete c.matcherToolNamePattern,delete c.matcherFromState,delete c.matcherToState,s?await d(s.name,c):await v(c)},_=async()=>{k(null);const a={};t.matcherToolNamePattern&&(a.toolNamePattern=t.matcherToolNamePattern),await T({hook:{name:t.name||"dry-run",description:t.description,events:t.events,implementationType:t.implementationType,command:t.command,url:t.url,promptTemplate:t.promptTemplate,agentName:t.agentName,priority:t.priority,tools:t.tools,matchers:a,timeoutMs:t.timeoutMs,enabled:!0,failOpen:t.failOpen,scope:t.scope},eventType:t.events[0]||"PRE_TOOL_USE",toolName:"",toolInput:""})},D=w?S.map(a=>({...a,events:Array.isArray(a.events)?a.events.filter(n=>n.name.toLowerCase().includes(w.toLowerCase())||n.summary.includes(w)):[]})).filter(a=>a.events.length>0):S,H=[{title:"基本信息",desc:"名称、描述、事件"},{title:"实现配置",desc:"执行方式与参数"},{title:"高级选项",desc:"优先级、过滤、测试"}];return e.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",children:[e.jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm",onClick:h}),e.jsxs("div",{className:"relative flex h-full w-[560px] flex-col border-l border-dark-border bg-dark-bg shadow-2xl animate-slide-in-right",children:[e.jsxs("div",{className:"flex flex-shrink-0 items-center justify-between border-b border-dark-border px-4 py-3.5",children:[e.jsx("h3",{className:"text-base font-semibold text-dark-text",children:s?`编辑: ${s.name}`:"添加 Hook 规则"}),e.jsx("button",{onClick:h,className:"rounded-lg p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-dark-text",children:e.jsx(I,{size:18})})]}),e.jsx("div",{className:"flex flex-shrink-0 border-b border-dark-border",children:H.map((a,n)=>{const c=n===x,R=n<x;return e.jsxs("button",{onClick:()=>p(n),className:`relative flex-1 border-b-2 px-2 py-2.5 text-center text-xs transition-colors ${c?"border-accent-blue bg-accent-blue/5 text-accent-blue":R?"border-transparent text-dark-text":"border-transparent text-dark-muted hover:text-dark-text"}`,children:[e.jsx("span",{className:`mr-1 inline-flex h-4 w-4 items-center justify-center rounded-full text-[10px] ${c?"bg-accent-blue text-white":R?"bg-accent-green text-white":"bg-dark-hover text-dark-muted"}`,children:R?"✓":n+1}),e.jsx("span",{className:"font-medium",children:a.title})]},a.title)})}),e.jsxs("div",{className:"flex-1 min-h-0 space-y-4 overflow-auto custom-scrollbar p-4",children:[r&&Object.keys(r).length>0&&e.jsx("div",{className:"rounded-lg border border-accent-red/40 bg-accent-red/10 p-2.5 text-xs text-accent-red",children:Object.entries(r).map(([a,n])=>e.jsxs("div",{children:[e.jsxs("strong",{children:[a,":"]})," ",n]},a))}),x===0&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"名称 *"}),e.jsx("input",{value:t.name,onChange:a=>u("name",a.target.value),placeholder:"my-custom-hook",className:b(r==null?void 0:r.name)})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"描述"}),e.jsx("textarea",{value:t.description,onChange:a=>u("description",a.target.value),placeholder:"这个 Hook 的作用...",rows:2,className:b()})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Scope"}),e.jsxs("select",{value:t.scope,onChange:a=>u("scope",a.target.value),className:b(),children:[e.jsx("option",{value:"project",children:"project (.agent/hooks.json)"}),e.jsx("option",{value:"user",children:"user (~/.agent/hooks.json)"}),e.jsx("option",{value:"local",children:"local (.agent/hooks.local.json)"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-1 flex items-center justify-between",children:[e.jsx("label",{className:"text-xs font-medium text-dark-muted",children:"事件 *"}),e.jsxs("span",{className:"text-xs text-accent-blue",children:[t.events.length," 已选"]})]}),e.jsx("input",{value:w,onChange:a=>C(a.target.value),placeholder:"搜索事件...",className:b()+" mb-2"}),e.jsx("div",{className:"max-h-[280px] space-y-2 overflow-auto custom-scrollbar rounded-lg border border-dark-border bg-dark-surface p-2",children:D.map(a=>e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>A(a.events.map(n=>n.name)),className:"mb-1 text-xs font-medium text-dark-muted transition-colors hover:text-dark-text",children:[a.category," — 全选/取消"]}),a.events.map(n=>{const c=t.events.includes(n.name);return e.jsxs("label",{className:"flex cursor-pointer items-center gap-2 rounded px-1 py-1 transition-colors hover:bg-dark-hover",children:[e.jsx("input",{type:"checkbox",checked:c,onChange:()=>O(n.name),className:"h-3.5 w-3.5 accent-accent-blue"}),e.jsx("span",{className:"text-xs text-dark-text",children:n.name}),e.jsxs("span",{className:"truncate text-xs text-dark-muted",children:["— ",n.summary]})]},n.name)})]},a.category))})]})]}),x===1&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"实现类型 *"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:se.map(a=>{const n=t.implementationType===a.value;return e.jsxs("button",{onClick:()=>u("implementationType",a.value),className:`rounded-lg border p-3 text-left transition-colors ${n?"border-accent-blue bg-accent-blue/10 ring-1 ring-accent-blue/30":"border-dark-border bg-dark-surface hover:bg-dark-hover"}`,children:[e.jsx("div",{className:`text-sm font-medium ${n?"text-accent-blue":"text-dark-text"}`,children:a.label}),e.jsx("div",{className:"mt-1 text-xs text-dark-muted",children:a.desc})]},a.value)})})]}),t.implementationType==="SHELL"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"命令 *"}),e.jsx("input",{value:t.command,onChange:a=>u("command",a.target.value),placeholder:"python3 .agent/hooks/audit.py",className:`font-mono ${b(r==null?void 0:r.command)}`})]}),t.implementationType==="HTTP"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"URL *"}),e.jsx("input",{value:t.url,onChange:a=>u("url",a.target.value),placeholder:"https://example.com/hooks/audit",className:b(r==null?void 0:r.url)})]}),t.implementationType==="PROMPT"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Prompt 模板 *"}),e.jsx("textarea",{value:t.promptTemplate,onChange:a=>u("promptTemplate",a.target.value),placeholder:"你是一个安全审计专家,请分析以下工具调用...",rows:5,className:`font-mono ${b(r==null?void 0:r.promptTemplate)}`})]}),t.implementationType==="AGENT"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Agent *"}),e.jsxs("select",{value:t.agentName,onChange:a=>u("agentName",a.target.value),className:b(r==null?void 0:r.agentName),children:[e.jsx("option",{value:"",children:"选择 Agent..."}),f.map(a=>e.jsxs("option",{value:a.id,children:[a.name," (",a.description,")"]},a.id))]}),e.jsx("p",{className:"mt-1 text-xs text-dark-muted",children:"Agent 将以只读模式运行(Read/Grep/Glob),不会修改文件"})]})]}),x===2&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"优先级"}),e.jsx("select",{value:t.priority,onChange:a=>u("priority",a.target.value),className:b(),children:re.map(a=>e.jsx("option",{value:a.value,children:a.label},a.value))})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"超时 (ms)"}),e.jsx("input",{type:"number",value:t.timeoutMs,onChange:a=>u("timeoutMs",parseInt(a.target.value)||3e4),min:100,max:3e5,step:1e3,className:b()})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm text-dark-text",children:[e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:a=>u("enabled",a.target.checked),className:"h-3.5 w-3.5 accent-accent-blue"}),"启用"]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-dark-text",children:[e.jsx("input",{type:"checkbox",checked:t.failOpen,onChange:a=>u("failOpen",a.target.checked),className:"h-3.5 w-3.5 accent-accent-blue"}),"Fail-open(超时放行)"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"工具过滤(正则,可选)"}),e.jsx("input",{value:t.matcherToolNamePattern,onChange:a=>u("matcherToolNamePattern",a.target.value),placeholder:"Bash.*|FileWrite.*",className:`font-mono ${b()}`})]}),t.events.some(a=>a.includes("STATE"))&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"From State"}),e.jsx("input",{value:t.matcherFromState,onChange:a=>u("matcherFromState",a.target.value),className:b()})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"To State"}),e.jsx("input",{value:t.matcherToState,onChange:a=>u("matcherToState",a.target.value),className:b()})]})]}),m&&e.jsxs("div",{className:"rounded-lg border border-dark-border bg-dark-surface p-3",children:[e.jsx("div",{className:"mb-2 text-xs font-medium text-dark-text",children:"Dry-run 结果"}),e.jsxs("div",{className:"space-y-1 text-xs",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"决策: "}),e.jsx("span",{className:m.decision==="ALLOW"?"text-accent-green":m.decision==="DENY"?"text-accent-red":"text-accent-yellow",children:m.decision})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"原因: "}),e.jsx("span",{className:"text-dark-text",children:m.reason})]}),m.contextOutput&&e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"输出: "}),e.jsx("span",{className:"text-dark-text",children:m.contextOutput})]})]})]}),e.jsxs("button",{onClick:_,className:"inline-flex items-center gap-1.5 rounded-lg border border-dark-border bg-dark-surface px-3 py-1.5 text-xs text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx($,{size:12})," 试运行 (Dry Run)"]})]})]}),e.jsxs("div",{className:"flex flex-shrink-0 items-center justify-between border-t border-dark-border px-4 py-3",children:[e.jsx("div",{className:"flex gap-2",children:x>0&&e.jsxs("button",{onClick:()=>p(x-1),className:"inline-flex items-center gap-1 rounded-lg border border-dark-border bg-dark-surface px-3 py-1.5 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx(Y,{size:14})," 上一步"]})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:h,className:"rounded-lg border border-dark-border bg-dark-surface px-4 py-1.5 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:"取消"}),x<2?e.jsxs("button",{onClick:()=>p(x+1),className:"inline-flex items-center gap-1 rounded-lg bg-accent-blue px-4 py-1.5 text-sm text-white transition-colors hover:bg-accent-blue/90",children:["下一步 ",e.jsx(G,{size:14})]}):e.jsx("button",{onClick:E,className:"rounded-lg bg-accent-blue px-4 py-1.5 text-sm text-white transition-colors hover:bg-accent-blue/90",children:s?"保存修改":"创建规则"})]})]})]})]})}function ne({stats:l}){if(!l)return null;const o=[{label:"总规则数",value:l.totalHooks,icon:J,iconWrap:"bg-accent-blue/15 text-accent-blue"},{label:"已启用",value:l.enabledCount,icon:B,iconWrap:"bg-accent-green/15 text-accent-green"},{label:"已禁用",value:l.disabledCount,icon:W,iconWrap:"bg-dark-hover text-dark-muted"}];return e.jsx("div",{className:"grid grid-cols-3 gap-3",children:o.map(s=>{const r=s.icon;return e.jsxs("div",{className:"flex items-center gap-3 rounded-xl border border-dark-border bg-dark-surface px-4 py-3",children:[e.jsx("span",{className:`flex h-9 w-9 shrink-0 items-center justify-center rounded-lg ${s.iconWrap}`,children:e.jsx(r,{size:18})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-xl font-bold text-dark-text",children:s.value}),e.jsx("div",{className:"text-xs text-dark-muted",children:s.label})]})]},s.label)})})}function xe(){const{rules:l,stats:o,events:s,agents:r,loading:m,error:v,formOpen:d,loadAll:h,openForm:T,clearError:k}=P();N.useEffect(()=>{h()},[]);const y=N.useCallback(async()=>{const{api:f}=await L(async()=>{const{api:p}=await import("./index-YAnKQ1Q6.js").then(t=>t.F);return{api:p}},__vite__mapDeps([0,1,2,3,4,5])),x=await f.hooks.export();if(x.success&&x.data){const p=new Blob([JSON.stringify(x.data,null,2)],{type:"application/json"}),t=URL.createObjectURL(p),i=document.createElement("a");i.href=t,i.download="hooks-export.json",i.click(),URL.revokeObjectURL(t)}},[]),S=N.useCallback(()=>{const f=document.createElement("input");f.type="file",f.accept=".json",f.onchange=async x=>{var i;const p=(i=x.target.files)==null?void 0:i[0];if(!p)return;const t=await p.text();try{const w=JSON.parse(t),{api:C}=await L(async()=>{const{api:A}=await import("./index-YAnKQ1Q6.js").then(E=>E.F);return{api:A}},__vite__mapDeps([0,1,2,3,4,5])),u=confirm(`合并到现有配置吗?
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DMxlsuNM.js","assets/markdown-CaPdHFK5.js","assets/icons-CrV0VGFQ.js","assets/react-vendor-DnYXnA42.js","assets/state-BHmvnECu.js","assets/index-DjWfcgLQ.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{a as j,_ as L}from"./index-DMxlsuNM.js";import{j as e}from"./markdown-CaPdHFK5.js";import{r as N,ap as z,aq as F,ar as M,a4 as U,X as I,ao as $,C as Y,b as G,as as J,ac as B,ad as W,R as q,ak as V,D as X,P as K}from"./icons-CrV0VGFQ.js";import{c as Q}from"./state-BHmvnECu.js";import"./react-vendor-DnYXnA42.js";const P=Q((l,o)=>({rules:[],stats:null,events:[],agents:[],loading:!1,error:null,fieldErrors:null,formOpen:!1,editingRule:null,dryRunResult:null,loadRules:async()=>{const s=await j.hooks.list();s.success&&Array.isArray(s.data)?l({rules:s.data}):s.success&&s.data&&!Array.isArray(s.data)?l({error:"服务端返回的规则数据格式异常"}):l({error:s.error||"Failed to load rules"})},loadStats:async()=>{const s=await j.hooks.stats();s.success&&s.data&&l({stats:s.data})},loadEvents:async()=>{const s=await j.hooks.events();s.success&&Array.isArray(s.data)?l({events:s.data}):s.success&&s.data&&!Array.isArray(s.data)&&l({error:"服务端返回的事件数据格式异常"})},loadAgents:async()=>{const s=await j.hooks.agents();s.success&&Array.isArray(s.data)?l({agents:s.data}):s.success&&s.data&&!Array.isArray(s.data)&&l({error:"服务端返回的Agent数据格式异常"})},loadAll:async()=>{l({loading:!0,error:null});try{await Promise.all([o().loadRules(),o().loadStats(),o().loadEvents(),o().loadAgents()])}catch(s){l({error:String(s)})}finally{l({loading:!1})}},createRule:async s=>{l({fieldErrors:null});const r=await j.hooks.create(s);if(r.success)return await o().loadRules(),await o().loadStats(),l({formOpen:!1,editingRule:null}),!0;if(r.error){l({error:r.error});try{const m=JSON.parse(r.error);m.fieldErrors&&l({fieldErrors:m.fieldErrors})}catch{}}return!1},updateRule:async(s,r)=>{l({fieldErrors:null});const m=await j.hooks.update(s,r);return m.success?(await o().loadRules(),l({formOpen:!1,editingRule:null}),!0):(l({error:m.error||"Update failed"}),!1)},deleteRule:async s=>{const r=await j.hooks.delete(s);return r.success?(await o().loadRules(),await o().loadStats(),!0):(l({error:r.error||"Delete failed"}),!1)},batchDelete:async s=>{const r=await j.hooks.batchDelete(s);return r.success?(await o().loadRules(),await o().loadStats(),!0):(l({error:r.error||"Batch delete failed"}),!1)},toggleRule:async(s,r)=>(await j.hooks.toggle(s,r)).success?(l(v=>({rules:v.rules.map(d=>d.name===s?{...d,enabled:r}:d)})),!0):(await o().loadRules(),!1),batchToggle:async(s,r)=>(await j.hooks.batchToggle(s,r)).success?(l(v=>({rules:v.rules.map(d=>s.includes(d.name)?{...d,enabled:r}:d)})),!0):(await o().loadRules(),!1),dryRun:async s=>{const r=await j.hooks.dryRun(s);return r.success&&r.data?(l({dryRunResult:r.data}),r.data):(l({error:r.error||"Dry-run failed"}),null)},openForm:s=>l({formOpen:!0,editingRule:s||null,dryRunResult:null,fieldErrors:null}),closeForm:()=>l({formOpen:!1,editingRule:null,dryRunResult:null,fieldErrors:null}),setDryRunResult:s=>l({dryRunResult:s}),clearError:()=>l({error:null}),clearFieldErrors:()=>l({fieldErrors:null})})),Z={SYSTEM:"bg-accent-red/15 text-accent-red",SECURITY:"bg-accent-orange/15 text-accent-orange",PROJECT:"bg-accent-blue/15 text-accent-blue",USER:"bg-accent-green/15 text-accent-green",PLUGIN:"bg-accent-purple/15 text-accent-purple"},ee={SHELL:"bg-accent-yellow/15 text-accent-yellow",HTTP:"bg-accent-cyan/15 text-accent-cyan",PROMPT:"bg-accent-purple/15 text-accent-purple",AGENT:"bg-accent-blue/15 text-accent-blue"};function te({rules:l,onEdit:o}){const{toggleRule:s,deleteRule:r,batchDelete:m,batchToggle:v}=P(),[d,h]=N.useState(new Set),[T,k]=N.useState(!1),y=Array.isArray(l)?l:[];if(y.length===0)return e.jsxs("div",{className:"flex flex-1 flex-col items-center justify-center gap-3 py-16 text-dark-muted",children:[e.jsx("div",{className:"text-4xl opacity-60",children:"🪝"}),e.jsx("p",{className:"text-sm",children:"暂无 Hook 规则"}),e.jsx("p",{className:"text-xs text-dark-muted/70",children:'点击右上角"新增规则"创建第一个 Hook'})]});const S=t=>{const i=new Set(d);i.has(t)?i.delete(t):i.add(t),h(i),k(i.size===y.length)},f=()=>{T?(h(new Set),k(!1)):(h(new Set(y.map(t=>t.name))),k(!0))},x=()=>{d.size!==0&&confirm(`确认删除 ${d.size} 条规则?`)&&(m(Array.from(d)),h(new Set),k(!1))},p=t=>{d.size!==0&&(v(Array.from(d),t),h(new Set),k(!1))};return e.jsxs("div",{className:"flex flex-1 flex-col min-h-0",children:[d.size>0&&e.jsxs("div",{className:"mb-2 flex items-center gap-2 rounded-lg border border-accent-blue/30 bg-accent-blue/5 px-3 py-1.5 text-sm",children:[e.jsxs("span",{className:"text-dark-muted",children:["已选 ",d.size," 项"]}),e.jsx("button",{onClick:()=>p(!0),className:"rounded bg-accent-green/15 px-2 py-0.5 text-accent-green transition-colors hover:bg-accent-green/25",children:"全部启用"}),e.jsx("button",{onClick:()=>p(!1),className:"rounded bg-dark-hover px-2 py-0.5 text-dark-text transition-colors hover:bg-dark-border",children:"全部禁用"}),e.jsx("button",{onClick:x,className:"rounded bg-accent-red/15 px-2 py-0.5 text-accent-red transition-colors hover:bg-accent-red/25",children:"删除"})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto custom-scrollbar rounded-xl border border-dark-border",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"sticky top-0 bg-dark-hover text-dark-muted",children:e.jsxs("tr",{children:[e.jsx("th",{className:"w-8 p-2.5",children:e.jsx("button",{onClick:f,children:T?e.jsx(z,{size:14}):e.jsx(F,{size:14})})}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"名称"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"事件"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"类型"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"优先级"}),e.jsx("th",{className:"p-2.5 text-left font-medium",children:"状态"}),e.jsx("th",{className:"p-2.5 text-right font-medium",children:"操作"})]})}),e.jsx("tbody",{className:"divide-y divide-dark-border",children:y.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-dark-hover/50",children:[e.jsx("td",{className:"p-2.5",children:e.jsx("button",{onClick:()=>S(t.name),children:d.has(t.name)?e.jsx(z,{size:14,className:"text-accent-blue"}):e.jsx(F,{size:14,className:"text-dark-muted"})})}),e.jsxs("td",{className:"p-2.5",children:[e.jsx("div",{className:"font-medium text-dark-text",children:t.name}),t.description&&e.jsx("div",{className:"mt-0.5 max-w-[220px] truncate text-xs text-dark-muted",children:t.description})]}),e.jsx("td",{className:"p-2.5",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[Array.isArray(t.events)&&t.events.slice(0,3).map(i=>e.jsx("span",{className:"rounded bg-dark-hover px-1.5 py-0.5 text-xs text-dark-text",children:i},i)),Array.isArray(t.events)&&t.events.length>3&&e.jsxs("span",{className:"px-1 py-0.5 text-xs text-dark-muted",children:["+",t.events.length-3]})]})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:`rounded px-1.5 py-0.5 text-xs font-medium ${ee[t.implementationType]||"bg-dark-hover text-dark-muted"}`,children:t.implementationType})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:`rounded px-1.5 py-0.5 text-xs font-medium ${Z[t.priority]||"bg-dark-hover text-dark-muted"}`,children:t.priority})}),e.jsx("td",{className:"p-2.5",children:e.jsx("button",{onClick:()=>s(t.name,!t.enabled),className:`relative h-5 w-9 rounded-full transition-colors ${t.enabled?"bg-accent-green":"bg-dark-border"}`,title:t.enabled?"点击禁用":"点击启用",children:e.jsx("span",{className:`absolute top-0.5 block h-3.5 w-3.5 rounded-full bg-white transition-all ${t.enabled?"left-[18px]":"left-[2px]"}`})})}),e.jsx("td",{className:"p-2.5",children:e.jsxs("div",{className:"flex items-center justify-end gap-1",children:[e.jsx("button",{onClick:()=>o(t),className:"rounded p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-accent-blue",title:"编辑",children:e.jsx(M,{size:14})}),e.jsx("button",{onClick:()=>{confirm(`删除规则 "${t.name}"?`)&&r(t.name)},className:"rounded p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-accent-red",title:"删除",children:e.jsx(U,{size:14})})]})})]},t.name))})]})})]})}const ae={name:"",description:"",events:[],implementationType:"SHELL",command:"",url:"",promptTemplate:"",agentName:"",priority:"USER",tools:[],matcherToolNamePattern:"",matcherFromState:"",matcherToState:"",timeoutMs:3e4,enabled:!0,failOpen:!0,scope:"project"},se=[{value:"SHELL",label:"Shell 脚本",desc:"执行外部脚本,stdin 接收 JSON,stdout 返回决策"},{value:"HTTP",label:"HTTP 端点",desc:"POST JSON 到外部端点"},{value:"PROMPT",label:"LLM Prompt",desc:"发送单轮 Prompt 给 LLM 做风险评估"},{value:"AGENT",label:"AI Agent",desc:"启动只读子代理做深度调查"}],re=[{value:"SYSTEM",label:"SYSTEM (100)"},{value:"SECURITY",label:"SECURITY (80)"},{value:"PROJECT",label:"PROJECT (60)"},{value:"USER",label:"USER (40)"},{value:"PLUGIN",label:"PLUGIN (20)"}],b=l=>`w-full rounded-lg border bg-dark-bg px-3 py-2 text-sm text-dark-text placeholder-dark-muted/60 transition-colors focus:outline-none focus:ring-2 ${l?"border-accent-red focus:border-accent-red focus:ring-accent-red/20":"border-dark-border focus:border-accent-blue focus:ring-accent-blue/20"}`,g="mb-1 block text-xs font-medium text-dark-muted";function le({events:l,agents:o}){const{editingRule:s,fieldErrors:r,dryRunResult:m,createRule:v,updateRule:d,closeForm:h,dryRun:T,setDryRunResult:k,clearFieldErrors:y}=P(),S=Array.isArray(l)?l:[],f=Array.isArray(o)?o:[],[x,p]=N.useState(0),[t,i]=N.useState(ae),[w,C]=N.useState("");N.useEffect(()=>{var a,n,c;s&&i({name:s.name,description:s.description||"",events:s.events,implementationType:s.implementationType,command:s.command||"",url:s.url||"",promptTemplate:s.promptTemplate||"",agentName:s.agentName||"",priority:s.priority,tools:s.tools||[],matcherToolNamePattern:((a=s.matchers)==null?void 0:a.toolNamePattern)||"",matcherFromState:((n=s.matchers)==null?void 0:n.fromState)||"",matcherToState:((c=s.matchers)==null?void 0:c.toState)||"",timeoutMs:s.timeoutMs,enabled:s.enabled,failOpen:s.failOpen,scope:s.scope||"project"})},[s]);const u=(a,n)=>{i(c=>({...c,[a]:n})),y()},O=a=>{i(n=>({...n,events:n.events.includes(a)?n.events.filter(c=>c!==a):[...n.events,a]}))},A=a=>{const n=a.every(c=>t.events.includes(c));i(n?c=>({...c,events:c.events.filter(R=>!a.includes(R))}):c=>({...c,events:[...new Set([...c.events,...a])]}))},E=async()=>{const a={};t.matcherToolNamePattern&&(a.toolNamePattern=t.matcherToolNamePattern),t.matcherFromState&&(a.fromState=t.matcherFromState),t.matcherToState&&(a.toState=t.matcherToState);const c={...{...t,tools:t.tools.length>0?t.tools:[]}};c.matchers=a,delete c.matcherToolNamePattern,delete c.matcherFromState,delete c.matcherToState,s?await d(s.name,c):await v(c)},_=async()=>{k(null);const a={};t.matcherToolNamePattern&&(a.toolNamePattern=t.matcherToolNamePattern),await T({hook:{name:t.name||"dry-run",description:t.description,events:t.events,implementationType:t.implementationType,command:t.command,url:t.url,promptTemplate:t.promptTemplate,agentName:t.agentName,priority:t.priority,tools:t.tools,matchers:a,timeoutMs:t.timeoutMs,enabled:!0,failOpen:t.failOpen,scope:t.scope},eventType:t.events[0]||"PRE_TOOL_USE",toolName:"",toolInput:""})},D=w?S.map(a=>({...a,events:Array.isArray(a.events)?a.events.filter(n=>n.name.toLowerCase().includes(w.toLowerCase())||n.summary.includes(w)):[]})).filter(a=>a.events.length>0):S,H=[{title:"基本信息",desc:"名称、描述、事件"},{title:"实现配置",desc:"执行方式与参数"},{title:"高级选项",desc:"优先级、过滤、测试"}];return e.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",children:[e.jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm",onClick:h}),e.jsxs("div",{className:"relative flex h-full w-[560px] flex-col border-l border-dark-border bg-dark-bg shadow-2xl animate-slide-in-right",children:[e.jsxs("div",{className:"flex flex-shrink-0 items-center justify-between border-b border-dark-border px-4 py-3.5",children:[e.jsx("h3",{className:"text-base font-semibold text-dark-text",children:s?`编辑: ${s.name}`:"添加 Hook 规则"}),e.jsx("button",{onClick:h,className:"rounded-lg p-1 text-dark-muted transition-colors hover:bg-dark-hover hover:text-dark-text",children:e.jsx(I,{size:18})})]}),e.jsx("div",{className:"flex flex-shrink-0 border-b border-dark-border",children:H.map((a,n)=>{const c=n===x,R=n<x;return e.jsxs("button",{onClick:()=>p(n),className:`relative flex-1 border-b-2 px-2 py-2.5 text-center text-xs transition-colors ${c?"border-accent-blue bg-accent-blue/5 text-accent-blue":R?"border-transparent text-dark-text":"border-transparent text-dark-muted hover:text-dark-text"}`,children:[e.jsx("span",{className:`mr-1 inline-flex h-4 w-4 items-center justify-center rounded-full text-[10px] ${c?"bg-accent-blue text-white":R?"bg-accent-green text-white":"bg-dark-hover text-dark-muted"}`,children:R?"✓":n+1}),e.jsx("span",{className:"font-medium",children:a.title})]},a.title)})}),e.jsxs("div",{className:"flex-1 min-h-0 space-y-4 overflow-auto custom-scrollbar p-4",children:[r&&Object.keys(r).length>0&&e.jsx("div",{className:"rounded-lg border border-accent-red/40 bg-accent-red/10 p-2.5 text-xs text-accent-red",children:Object.entries(r).map(([a,n])=>e.jsxs("div",{children:[e.jsxs("strong",{children:[a,":"]})," ",n]},a))}),x===0&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"名称 *"}),e.jsx("input",{value:t.name,onChange:a=>u("name",a.target.value),placeholder:"my-custom-hook",className:b(r==null?void 0:r.name)})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"描述"}),e.jsx("textarea",{value:t.description,onChange:a=>u("description",a.target.value),placeholder:"这个 Hook 的作用...",rows:2,className:b()})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Scope"}),e.jsxs("select",{value:t.scope,onChange:a=>u("scope",a.target.value),className:b(),children:[e.jsx("option",{value:"project",children:"project (.agent/hooks.json)"}),e.jsx("option",{value:"user",children:"user (~/.agent/hooks.json)"}),e.jsx("option",{value:"local",children:"local (.agent/hooks.local.json)"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-1 flex items-center justify-between",children:[e.jsx("label",{className:"text-xs font-medium text-dark-muted",children:"事件 *"}),e.jsxs("span",{className:"text-xs text-accent-blue",children:[t.events.length," 已选"]})]}),e.jsx("input",{value:w,onChange:a=>C(a.target.value),placeholder:"搜索事件...",className:b()+" mb-2"}),e.jsx("div",{className:"max-h-[280px] space-y-2 overflow-auto custom-scrollbar rounded-lg border border-dark-border bg-dark-surface p-2",children:D.map(a=>e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>A(a.events.map(n=>n.name)),className:"mb-1 text-xs font-medium text-dark-muted transition-colors hover:text-dark-text",children:[a.category," — 全选/取消"]}),a.events.map(n=>{const c=t.events.includes(n.name);return e.jsxs("label",{className:"flex cursor-pointer items-center gap-2 rounded px-1 py-1 transition-colors hover:bg-dark-hover",children:[e.jsx("input",{type:"checkbox",checked:c,onChange:()=>O(n.name),className:"h-3.5 w-3.5 accent-accent-blue"}),e.jsx("span",{className:"text-xs text-dark-text",children:n.name}),e.jsxs("span",{className:"truncate text-xs text-dark-muted",children:["— ",n.summary]})]},n.name)})]},a.category))})]})]}),x===1&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"实现类型 *"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:se.map(a=>{const n=t.implementationType===a.value;return e.jsxs("button",{onClick:()=>u("implementationType",a.value),className:`rounded-lg border p-3 text-left transition-colors ${n?"border-accent-blue bg-accent-blue/10 ring-1 ring-accent-blue/30":"border-dark-border bg-dark-surface hover:bg-dark-hover"}`,children:[e.jsx("div",{className:`text-sm font-medium ${n?"text-accent-blue":"text-dark-text"}`,children:a.label}),e.jsx("div",{className:"mt-1 text-xs text-dark-muted",children:a.desc})]},a.value)})})]}),t.implementationType==="SHELL"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"命令 *"}),e.jsx("input",{value:t.command,onChange:a=>u("command",a.target.value),placeholder:"python3 .agent/hooks/audit.py",className:`font-mono ${b(r==null?void 0:r.command)}`})]}),t.implementationType==="HTTP"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"URL *"}),e.jsx("input",{value:t.url,onChange:a=>u("url",a.target.value),placeholder:"https://example.com/hooks/audit",className:b(r==null?void 0:r.url)})]}),t.implementationType==="PROMPT"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Prompt 模板 *"}),e.jsx("textarea",{value:t.promptTemplate,onChange:a=>u("promptTemplate",a.target.value),placeholder:"你是一个安全审计专家,请分析以下工具调用...",rows:5,className:`font-mono ${b(r==null?void 0:r.promptTemplate)}`})]}),t.implementationType==="AGENT"&&e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Agent *"}),e.jsxs("select",{value:t.agentName,onChange:a=>u("agentName",a.target.value),className:b(r==null?void 0:r.agentName),children:[e.jsx("option",{value:"",children:"选择 Agent..."}),f.map(a=>e.jsxs("option",{value:a.id,children:[a.name," (",a.description,")"]},a.id))]}),e.jsx("p",{className:"mt-1 text-xs text-dark-muted",children:"Agent 将以只读模式运行(Read/Grep/Glob),不会修改文件"})]})]}),x===2&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"优先级"}),e.jsx("select",{value:t.priority,onChange:a=>u("priority",a.target.value),className:b(),children:re.map(a=>e.jsx("option",{value:a.value,children:a.label},a.value))})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"超时 (ms)"}),e.jsx("input",{type:"number",value:t.timeoutMs,onChange:a=>u("timeoutMs",parseInt(a.target.value)||3e4),min:100,max:3e5,step:1e3,className:b()})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm text-dark-text",children:[e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:a=>u("enabled",a.target.checked),className:"h-3.5 w-3.5 accent-accent-blue"}),"启用"]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-dark-text",children:[e.jsx("input",{type:"checkbox",checked:t.failOpen,onChange:a=>u("failOpen",a.target.checked),className:"h-3.5 w-3.5 accent-accent-blue"}),"Fail-open(超时放行)"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"工具过滤(正则,可选)"}),e.jsx("input",{value:t.matcherToolNamePattern,onChange:a=>u("matcherToolNamePattern",a.target.value),placeholder:"Bash.*|FileWrite.*",className:`font-mono ${b()}`})]}),t.events.some(a=>a.includes("STATE"))&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"From State"}),e.jsx("input",{value:t.matcherFromState,onChange:a=>u("matcherFromState",a.target.value),className:b()})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"To State"}),e.jsx("input",{value:t.matcherToState,onChange:a=>u("matcherToState",a.target.value),className:b()})]})]}),m&&e.jsxs("div",{className:"rounded-lg border border-dark-border bg-dark-surface p-3",children:[e.jsx("div",{className:"mb-2 text-xs font-medium text-dark-text",children:"Dry-run 结果"}),e.jsxs("div",{className:"space-y-1 text-xs",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"决策: "}),e.jsx("span",{className:m.decision==="ALLOW"?"text-accent-green":m.decision==="DENY"?"text-accent-red":"text-accent-yellow",children:m.decision})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"原因: "}),e.jsx("span",{className:"text-dark-text",children:m.reason})]}),m.contextOutput&&e.jsxs("div",{children:[e.jsx("span",{className:"text-dark-muted",children:"输出: "}),e.jsx("span",{className:"text-dark-text",children:m.contextOutput})]})]})]}),e.jsxs("button",{onClick:_,className:"inline-flex items-center gap-1.5 rounded-lg border border-dark-border bg-dark-surface px-3 py-1.5 text-xs text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx($,{size:12})," 试运行 (Dry Run)"]})]})]}),e.jsxs("div",{className:"flex flex-shrink-0 items-center justify-between border-t border-dark-border px-4 py-3",children:[e.jsx("div",{className:"flex gap-2",children:x>0&&e.jsxs("button",{onClick:()=>p(x-1),className:"inline-flex items-center gap-1 rounded-lg border border-dark-border bg-dark-surface px-3 py-1.5 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx(Y,{size:14})," 上一步"]})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:h,className:"rounded-lg border border-dark-border bg-dark-surface px-4 py-1.5 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:"取消"}),x<2?e.jsxs("button",{onClick:()=>p(x+1),className:"inline-flex items-center gap-1 rounded-lg bg-accent-blue px-4 py-1.5 text-sm text-white transition-colors hover:bg-accent-blue/90",children:["下一步 ",e.jsx(G,{size:14})]}):e.jsx("button",{onClick:E,className:"rounded-lg bg-accent-blue px-4 py-1.5 text-sm text-white transition-colors hover:bg-accent-blue/90",children:s?"保存修改":"创建规则"})]})]})]})]})}function ne({stats:l}){if(!l)return null;const o=[{label:"总规则数",value:l.totalHooks,icon:J,iconWrap:"bg-accent-blue/15 text-accent-blue"},{label:"已启用",value:l.enabledCount,icon:B,iconWrap:"bg-accent-green/15 text-accent-green"},{label:"已禁用",value:l.disabledCount,icon:W,iconWrap:"bg-dark-hover text-dark-muted"}];return e.jsx("div",{className:"grid grid-cols-3 gap-3",children:o.map(s=>{const r=s.icon;return e.jsxs("div",{className:"flex items-center gap-3 rounded-xl border border-dark-border bg-dark-surface px-4 py-3",children:[e.jsx("span",{className:`flex h-9 w-9 shrink-0 items-center justify-center rounded-lg ${s.iconWrap}`,children:e.jsx(r,{size:18})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-xl font-bold text-dark-text",children:s.value}),e.jsx("div",{className:"text-xs text-dark-muted",children:s.label})]})]},s.label)})})}function xe(){const{rules:l,stats:o,events:s,agents:r,loading:m,error:v,formOpen:d,loadAll:h,openForm:T,clearError:k}=P();N.useEffect(()=>{h()},[]);const y=N.useCallback(async()=>{const{api:f}=await L(async()=>{const{api:p}=await import("./index-DMxlsuNM.js").then(t=>t.F);return{api:p}},__vite__mapDeps([0,1,2,3,4,5])),x=await f.hooks.export();if(x.success&&x.data){const p=new Blob([JSON.stringify(x.data,null,2)],{type:"application/json"}),t=URL.createObjectURL(p),i=document.createElement("a");i.href=t,i.download="hooks-export.json",i.click(),URL.revokeObjectURL(t)}},[]),S=N.useCallback(()=>{const f=document.createElement("input");f.type="file",f.accept=".json",f.onchange=async x=>{var i;const p=(i=x.target.files)==null?void 0:i[0];if(!p)return;const t=await p.text();try{const w=JSON.parse(t),{api:C}=await L(async()=>{const{api:A}=await import("./index-DMxlsuNM.js").then(E=>E.F);return{api:A}},__vite__mapDeps([0,1,2,3,4,5])),u=confirm(`合并到现有配置吗?
|
|
3
3
|
"确定"=合并 / "取消"=替换`)?"merge":"replace";(await C.hooks.import({...w,mergeMode:u})).success&&h()}catch(w){console.error("Import failed:",w)}},f.click()},[h]);return e.jsxs("div",{className:"flex h-full min-h-0 flex-col bg-dark-bg text-dark-text",children:[e.jsxs("div",{className:"flex shrink-0 flex-wrap items-center justify-between gap-3 border-b border-dark-border px-6 py-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold text-dark-text",children:"Hook 配置"}),e.jsx("p",{className:"mt-0.5 text-xs text-dark-muted",children:"在工具执行、任务流转等生命周期事件上挂载拦截器,实现审批与自定义逻辑"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:h,title:"刷新",className:"rounded-lg p-2 text-dark-muted transition-colors hover:bg-dark-hover hover:text-dark-text",children:e.jsx(q,{size:16,className:m?"animate-spin":""})}),e.jsxs("button",{onClick:S,className:"inline-flex items-center gap-1.5 rounded-lg border border-dark-border bg-dark-surface px-3 py-2 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx(V,{size:14}),"导入"]}),e.jsxs("button",{onClick:y,className:"inline-flex items-center gap-1.5 rounded-lg border border-dark-border bg-dark-surface px-3 py-2 text-sm text-dark-text transition-colors hover:bg-dark-hover",children:[e.jsx(X,{size:14}),"导出"]}),e.jsxs("button",{onClick:()=>T(),className:"inline-flex items-center gap-1.5 rounded-lg bg-accent-blue px-3 py-2 text-sm text-white transition-colors hover:bg-accent-blue/90",children:[e.jsx(K,{size:14}),"新增规则"]})]})]}),e.jsxs("div",{className:"flex-1 min-h-0 overflow-auto custom-scrollbar px-6 py-4",children:[v&&e.jsxs("div",{className:"mb-3 flex items-center justify-between rounded-lg border border-accent-red/40 bg-accent-red/10 px-4 py-2 text-sm text-accent-red",children:[e.jsx("span",{children:v}),e.jsx("button",{onClick:k,className:"text-accent-red/70 transition-colors hover:text-accent-red",children:e.jsx(I,{size:16})})]}),e.jsx(ne,{stats:o}),e.jsxs("section",{className:"mt-4 min-w-0 rounded-xl border border-dark-border bg-dark-surface p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-semibold text-dark-text",children:"规则列表"}),e.jsxs("span",{className:"text-xs text-dark-muted",children:[l.length," 条"]})]}),m&&l.length===0?e.jsx("div",{className:"flex h-[520px] items-center justify-center text-dark-muted",children:"加载中..."}):e.jsx("div",{className:"min-h-[520px]",children:e.jsx(te,{rules:l,onEdit:f=>T(f)})})]})]}),d&&e.jsx(le,{events:s,agents:r})]})}export{xe as HookConfigView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./markdown-
|
|
1
|
+
import{j as t}from"./markdown-CaPdHFK5.js";import{r as c,V as m,R as f,m as j,ai as k,X as v,a_ as N,a$ as y,h as w}from"./icons-CrV0VGFQ.js";import{E as C}from"./index-DMxlsuNM.js";import"./react-vendor-DnYXnA42.js";import"./state-BHmvnECu.js";function R(){const{items:i,pendingCount:x,fetchInbox:l,resolveInbox:d,loading:p,error:u}=C(),[r,g]=c.useState("pending");c.useEffect(()=>{l()},[l]);const o=c.useMemo(()=>i.filter(e=>r==="all"||e.state===r),[i,r]),h=e=>e.kind==="approval"?{label:"需要批准",icon:y,color:"text-accent-yellow"}:e.kind==="question"?{label:"需要回答",icon:w,color:"text-accent-blue"}:{label:"通知",icon:m,color:"text-dark-muted"},b=e=>{var n;if(e.kind!=="approval")return null;const a=((n=e.data)==null?void 0:n.payload)||{};for(const s of["target","recipient","channel","url"])if(typeof a[s]=="string"&&a[s])return a[s];for(const s of["path","filePath"])if(typeof a[s]=="string"&&a[s])return a[s];return null};return t.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden p-4",children:[t.jsxs("div",{className:"flex items-center justify-between mb-4",children:[t.jsxs("h2",{className:"text-lg font-semibold flex items-center gap-2",children:[t.jsx(m,{size:20,className:"text-accent-blue"}),"Inbox",x>0&&t.jsxs("span",{className:"ml-1 px-2 py-0.5 rounded-full bg-accent-yellow/20 text-accent-yellow text-xs",children:[x," 待处理"]})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"flex rounded-lg bg-dark-hover p-0.5 text-sm",children:["pending","resolved","all"].map(e=>t.jsx("button",{onClick:()=>g(e),className:`px-3 py-1 rounded-md transition-colors ${r===e?"bg-accent-blue/20 text-accent-blue":"text-dark-muted hover:text-dark-text"}`,children:e==="pending"?"待处理":e==="resolved"?"已解决":"全部"},e))}),t.jsx("button",{onClick:()=>void l(),className:"p-2 rounded-lg hover:bg-dark-hover text-dark-muted",title:"刷新",children:t.jsx(f,{size:16})})]})]}),u&&t.jsxs("div",{className:"mb-3 p-3 rounded-lg bg-accent-red/10 text-accent-red text-sm flex items-center gap-2",children:[t.jsx(j,{size:16})," ",u]}),t.jsxs("div",{className:"flex-1 overflow-y-auto space-y-2",children:[p&&o.length===0&&t.jsx("p",{className:"text-dark-muted text-center py-8",children:"加载中..."}),!p&&o.length===0&&t.jsxs("p",{className:"text-dark-muted text-center py-8",children:["没有",r==="pending"?"待处理":"","事项"]}),o.map(e=>{const a=h(e),n=a.icon;return t.jsxs("div",{className:"rounded-lg border border-dark-border bg-dark-surface p-3",children:[t.jsxs("div",{className:"flex items-start justify-between gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[t.jsx(n,{size:16,className:`${a.color} shrink-0`}),t.jsx("span",{className:"font-medium text-sm truncate",children:e.title}),t.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-dark-hover text-dark-muted shrink-0",children:e.kind})]}),t.jsx("span",{className:`text-xs shrink-0 ${e.state==="pending"?"text-accent-yellow":"text-accent-green"}`,children:e.state==="pending"?"pending":e.resolution||"resolved"})]}),e.body&&t.jsx("p",{className:"mt-1 text-xs text-dark-muted break-all",children:e.body}),e.data&&typeof e.data.toolName=="string"&&e.data.toolName&&t.jsxs("div",{className:"mt-2 p-2 rounded bg-dark-bg border border-dark-border",children:[t.jsxs("code",{className:"text-xs text-accent-blue",children:["工具: ",String(e.data.toolName)]}),typeof e.data.payload=="object"&&e.data.payload!==null&&t.jsx("pre",{className:"mt-1 text-[11px] text-dark-muted whitespace-pre-wrap max-h-24 overflow-y-auto",children:JSON.stringify(e.data.payload,null,2).slice(0,800)})]}),e.state==="pending"&&t.jsxs("div",{className:"mt-2 flex gap-2",children:[t.jsxs("button",{onClick:()=>void d(e.id,"allow"),className:"flex items-center gap-1 px-3 py-1.5 rounded-lg bg-accent-green/20 text-accent-green hover:bg-accent-green/30 text-xs font-medium",children:[t.jsx(k,{size:14})," 批准"]}),t.jsxs("button",{onClick:()=>void d(e.id,"deny"),className:"flex items-center gap-1 px-3 py-1.5 rounded-lg bg-accent-red/20 text-accent-red hover:bg-accent-red/30 text-xs font-medium",children:[t.jsx(v,{size:14})," 拒绝"]}),e.kind==="approval"&&(()=>{const s=b(e);return t.jsxs("button",{onClick:()=>void d(e.id,"always"),className:"flex items-center gap-1 px-3 py-1.5 rounded-lg bg-dark-hover text-dark-muted hover:text-dark-text text-xs font-medium",title:s?`此目标后续自动放行:${s}`:"此工具本次会话后续自动放行",children:[t.jsx(N,{size:14})," 总是允许",s?` ${s}`:""]})})()]})]},e.id)})]})]})}export{R as InboxView};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as t}from"./markdown-CaPdHFK5.js";import{r,R as de,a2 as pt,P as Fe,x as Oe,X as Be,a3 as bt,v as ie,a4 as _e,a5 as mt,a6 as ht,B as ft,K as gt,a7 as vt,a8 as kt,D as yt,a9 as We,m as jt,aa as Nt}from"./icons-CrV0VGFQ.js";import{a as p,t as I,M as Ge,P as wt}from"./index-DMxlsuNM.js";import"./react-vendor-DnYXnA42.js";import"./state-BHmvnECu.js";function Ct(){const[k,y]=r.useState([]),[j,m]=r.useState("1.0"),[F,d]=r.useState(!0),[E,G]=r.useState(!0),[Y,$]=r.useState(null),N=r.useCallback(async()=>{G(!0),$(null);try{const v=await p.providers.presets();v.success&&v.data?(y(Array.isArray(v.data.providers)?v.data.providers:[]),m(v.data.version||"1.0"),d(v.data.customSupported!==!1)):$(v.error||"获取 Provider 列表失败")}catch(v){$(v instanceof Error?v.message:"未知错误")}finally{G(!1)}},[]);return r.useEffect(()=>{N()},[N]),{presets:k,loading:E,error:Y,version:j,customSupported:F,reload:N}}const ue={provider:"",modelId:"",modelName:"",apiKey:"",temperature:1,maxTokens:32768,contextWindow:1e6},Pt={providerKey:"",apiKeys:"",modelIds:"",baseUrl:"",apiType:"openai-completions",setDefault:!1},Tt=wt,It={"openai-chat-completions":"OpenAI Chat","openai-completions":"OpenAI Compatible","openai-responses":"OpenAI Responses","anthropic-messages":"Anthropic Messages"},Ye={deepseek:10,moonshotai:20,"moonshotai-cn":21,"kimi-for-coding":22,zhipuai:30,zai:31,"alibaba-cn":40,alibaba:41,minimax:50,"minimax-cn":51,moark:60,siliconflow:70,"siliconflow-cn":71,"stepfun-ai":80,stepfun:81,modelscope:90,openai:100,anthropic:110,google:120,"google-vertex":121,meta:130,mistral:140,groq:150,xai:160,cohere:170,openrouter:180,huggingface:190};function Et(){var Ke,De,Ae,Me,Se,Ee,$e,ze,Re,Le;const{presets:k,loading:y,reload:j}=Ct(),[m,F]=r.useState([]),[d,E]=r.useState(null),[G,Y]=r.useState(!0),[$,N]=r.useState(null),[v,pe]=r.useState(null),[Ve,q]=r.useState(!1),[w,V]=r.useState(null),[b,C]=r.useState(ue),[be,me]=r.useState(!1),[he,O]=r.useState(null),[n,He]=r.useState(null),[Xe,z]=r.useState(!1),[fe,B]=r.useState("select"),[g,R]=r.useState(null),[u,T]=r.useState(Pt),[ge,ve]=r.useState(!1),[ke,K]=r.useState(null),[Je,ne]=r.useState(!1),[H,ye]=r.useState(!1),[_,X]=r.useState(""),[je,Ne]=r.useState({}),[le,we]=r.useState(!1),[J,W]=r.useState([]),[Q,D]=r.useState(new Set),[Ce,L]=r.useState(null),[Z,oe]=r.useState(""),A=r.useCallback(async()=>{try{const e=await p.config.provider.get();e.success&&e.data&&He(e.data)}catch{}},[]),h=r.useCallback(async()=>{Y(!0),N(null);try{const[e,s]=await Promise.all([p.models.list(),p.system.status()]);if(await A(),e.success&&e.data&&Array.isArray(e.data.models)&&F(e.data.models),s.success&&s.data){const a=s.data.models||{total:0,online:0,offline:0};E({overallStatus:a.offline===0?"healthy":a.online>0?"degraded":"unhealthy",healthRate:a.total>0?a.online/a.total:0,healthyInstances:a.online,totalInstances:a.total,totalRequests:0})}}catch{N("加载模型失败")}finally{Y(!1)}},[A]);r.useEffect(()=>{h()},[h]),r.useEffect(()=>{const e=()=>{h(),A()};return window.addEventListener("models-updated",e),()=>window.removeEventListener("models-updated",e)},[h,A]);const M=r.useCallback(e=>`${e.provider}:${e.id}`,[]),Qe=r.useCallback(e=>je[M(e)]||{inputTokens:0,outputTokens:0},[M,je]),Pe=r.useCallback((e,s,a)=>{const l=M(e);Ne(c=>{var o,i;return{...c,[l]:{inputTokens:s==="inputTokens"?a:((o=c[l])==null?void 0:o.inputTokens)||0,outputTokens:s==="outputTokens"?a:((i=c[l])==null?void 0:i.outputTokens)||0}}})},[M]),Ze=r.useCallback(e=>{Ne(s=>({...s,[M(e)]:{inputTokens:0,outputTokens:0}}))},[M]),S=r.useMemo(()=>{const e=[...k];return e.find(s=>s.key==="custom")||e.push({key:"custom",name:"Custom",baseUrl:"",apiType:"openai-completions",defaultModel:"",isCustom:!0}),e},[k]),ee=r.useMemo(()=>[...S].sort((e,s)=>{if(e.isCustom)return-1;if(s.isCustom)return 1;const a=Ye[e.key],l=Ye[s.key];return a!==void 0&&l!==void 0?a-l:a!==void 0?-1:l!==void 0?1:e.name.localeCompare(s.name)}),[S]),Te=r.useMemo(()=>{const e=_.trim().toLowerCase();return e?ee.filter(s=>s.name.toLowerCase().includes(e)||s.key.toLowerCase().includes(e)||(s.defaultModel||"").toLowerCase().includes(e)||(s.baseUrl||"").toLowerCase().includes(e)||(s.models||[]).some(a=>String(a).toLowerCase().includes(e))):ee},[ee,_]),P=r.useMemo(()=>{var l,c,o,i;const e=(n==null?void 0:n.providers)||{},s=new Set(S.map(x=>x.key)),a=Object.entries(e).filter(([x])=>!s.has(x));if(a.length!==0)return{keys:a.map(([x])=>x),modelCount:a.reduce((x,[,te])=>x+(te.modelCount||0),0),hasApiKey:a.some(([,x])=>x.hasApiKey),baseUrl:((c=(l=a.find(([,x])=>x.baseUrl))==null?void 0:l[1])==null?void 0:c.baseUrl)||"",apiType:((i=(o=a.find(([,x])=>x.apiType))==null?void 0:o[1])==null?void 0:i.apiType)||"openai-completions"}},[n,S]),Ie=r.useCallback(e=>{var o,i;const s=(o=n==null?void 0:n.providers)==null?void 0:o[e.key],a=m.filter(x=>x.provider===e.key).map(x=>x.id),l=((i=e.models)==null?void 0:i.slice(0,3).join(", "))||e.defaultModel,c=a.length>0?a.join(", "):l;R(e.key),T({providerKey:e.key,apiKeys:"",modelIds:c,baseUrl:(s==null?void 0:s.baseUrl)||e.baseUrl,apiType:(s==null?void 0:s.apiType)||e.apiType,setDefault:(n==null?void 0:n.defaultProvider)!==e.key}),B("form"),z(!0),K(null),ne(!1),W([]),D(new Set),L(null),oe("")},[m,n]),ce=r.useCallback(()=>{var l,c;R("custom");const e=(l=P==null?void 0:P.keys)==null?void 0:l[0],s=e?(c=n==null?void 0:n.providers)==null?void 0:c[e]:void 0,a=e?m.filter(o=>o.provider===e).map(o=>o.id).join(", "):"";T({providerKey:e||"",apiKeys:"",modelIds:a,baseUrl:(s==null?void 0:s.baseUrl)||"",apiType:(s==null?void 0:s.apiType)||"openai-completions",setDefault:!(n!=null&&n.configured)}),B("form"),z(!0),K(null),ne(!1),W([]),D(new Set),L(null),oe("")},[n,P,m]),et=r.useCallback(async()=>{var s;const e=u.baseUrl;if(!e){L("请先填写 Base URL");return}we(!0),L(null),W([]),D(new Set);try{const a=(u.apiKeys||"").split(/\r?\n|,/).map(o=>o.trim()).filter(Boolean)[0]||"",l=a.replace(/[^\x00-\xFF]/g,"");l!==a&&I.warning("API Key 包含非法字符,已自动过滤");const c=await p.models.fetch(e,l);if(c.success&&((s=c.data)!=null&&s.models)){W(c.data.models);const o=new Set(u.modelIds.split(",").map(i=>i.trim()).filter(Boolean));D(o),I.success(`获取到 ${c.data.models.length} 个模型`)}else L(c.error||"获取模型列表失败,请检查 Base URL 和 API Key")}catch(a){L(a instanceof Error?a.message:"请求失败")}finally{we(!1)}},[u.baseUrl,u.apiKeys,u.modelIds]),tt=r.useCallback(e=>{const s=new Set(Q);s.has(e)?s.delete(e):s.add(e),D(s),T(a=>({...a,modelIds:Array.from(s).join(", ")}))},[Q]),st=async e=>{const s=m.find(o=>o.id===e);if(!s)return;const a=s.enabled!==!1,l=s.name||e,c=o=>a&&/default model/i.test(o);try{const o=await p.models.toggle(s.provider,e);if(o.success){await h();return}const i=o.error||"";c(i)?I.error(`“${l}” 是默认模型,无法直接禁用。请先在「Provider 配置」中更换默认模型,再进行禁用。`):I.error(i||"操作失败,请重试")}catch(o){const i=o instanceof Error?o.message:"";c(i)?I.error(`“${l}” 是默认模型,无法直接禁用。请先在「Provider 配置」中更换默认模型,再进行禁用。`):I.error(i||"操作失败,请重试")}},at=async e=>{pe(e);try{await p.models.test(e),await h()}finally{pe(null)}},rt=async(e,s)=>{if(confirm(`确定要删除模型 "${s}" 吗?此操作不可撤销。`))try{(await p.models.delete(e,s)).success&&await h()}catch{}},nt=e=>{V({provider:e.provider,modelId:e.id}),C({provider:e.provider,modelId:e.id,modelName:e.name,apiKey:"",temperature:e.temperature??1,maxTokens:e.maxTokens??32768,contextWindow:e.contextWindow??1e6}),O(null),q(!0)},lt=async()=>{var x,te;const e=S.find(f=>f.key===g)||null,s=g==="custom"?u.providerKey.trim():(e==null?void 0:e.key)||"";if(!s){K("请先输入 Provider 名称");return}const a=(u.apiKeys||"").split(/\r?\n|,/).map(f=>f.trim()).filter(Boolean),l=!!((te=(x=n==null?void 0:n.providers)==null?void 0:x[s])!=null&&te.hasApiKey);if(a.length===0&&!l){K("请至少输入一把 API Key");return}const c=e||{baseUrl:"",apiType:"openai-completions",defaultModel:""},o=a.map(f=>f.replace(/[^\x00-\xFF]/g,"")).filter(Boolean),i={provider:s,name:s,baseUrl:u.baseUrl||c.baseUrl,apiType:u.apiType||c.apiType,models:(u.modelIds||c.defaultModel||"").split(",").map((f,ut)=>{const se=f.trim().split("|").map(xt=>xt.trim()).filter(Boolean),Ue=se[0]||"";return{id:Ue,name:se[1]||Ue,aliases:se.length>2?se.slice(2):void 0,enabled:!0,priority:10+ut}}).filter(f=>f.id.length>0)};o.length>0&&(i.apiKeys=o),(!(n!=null&&n.configured)||u.setDefault)&&(i.setDefault=!0),ve(!0),K(null);try{const f=await p.config.provider.save(i);f.success?(z(!1),B("select"),R(null),await A(),await h()):K(f.error||"保存失败")}catch(f){K(f instanceof Error?f.message:"未知错误")}finally{ve(!1)}},ot=async e=>{if(confirm(`确定要移除 "${e}" 的配置吗?这将删除其 API Key 和模型。`))try{await p.config.provider.delete(e),await A(),await h()}catch{}},ct=async()=>{if(w){if(!b.provider.trim()||!b.modelId.trim()){O("提供商名称和模型 ID 不能为空");return}me(!0),O(null);try{const e={name:b.modelName.trim()||b.modelId.trim(),temperature:b.temperature,maxTokens:b.maxTokens,contextWindow:b.contextWindow,...b.apiKey.trim()?{apiKey:b.apiKey.trim()}:{}},s=await p.models.update(w.provider,w.modelId,{model:e});s.success?(q(!1),V(null),C(ue),await h()):O(s.error||"保存失败")}catch(e){O(e instanceof Error?e.message:"未知错误")}finally{me(!1)}}},dt=e=>{switch(e){case"online":return"text-accent-green";case"offline":return"text-dark-muted";case"error":return"text-accent-red";default:return"text-dark-muted"}},it=e=>{switch(e){case"online":return t.jsx(Nt,{size:14});case"offline":return t.jsx(We,{size:14});case"error":return t.jsx(jt,{size:14});default:return t.jsx(We,{size:14})}},U=r.useMemo(()=>S.find(e=>e.key===g)||null,[g,S]);return G?t.jsx("div",{className:"flex h-64 items-center justify-center text-dark-muted",children:"加载中..."}):$?t.jsx("div",{className:"flex h-64 items-center justify-center text-accent-red",children:$}):t.jsxs("div",{className:"p-6 space-y-6 flex-1 min-h-0 overflow-y-auto custom-scrollbar",children:[t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center justify-between mb-3",children:[t.jsx("h2",{className:"text-base font-semibold",children:"Provider 配置"}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs("button",{onClick:async()=>{try{await p.providers.refresh(),I.success("Provider 列表已刷新"),ye(!0),await j(),setTimeout(()=>{j()},3e3)}catch{I.error("刷新失败,请稍后重试")}},className:"inline-flex items-center gap-1.5 px-2.5 py-1 text-xs border border-dark-border rounded hover:bg-dark-hover",title:"从远端刷新 Provider 列表",children:[t.jsx(de,{size:12}),"刷新列表"]}),t.jsxs("button",{onClick:()=>{H&&X(""),ye(e=>!e)},className:"inline-flex items-center gap-1.5 px-2.5 py-1 text-xs bg-accent-blue text-white rounded hover:opacity-90",children:[H?t.jsx(pt,{size:12}):t.jsx(Fe,{size:12}),H?"收起":"新增 Provider"]})]})]}),H&&t.jsxs("div",{children:[t.jsxs("div",{className:"relative mb-3 max-w-md",children:[t.jsx(Oe,{size:13,className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-dark-muted"}),t.jsx("input",{value:_,onChange:e=>X(e.target.value),className:"w-full pl-8 pr-8 py-1.5 text-xs bg-dark-bg border border-dark-border rounded focus:outline-none focus:border-accent-blue",placeholder:"搜索 Provider 名称 / 模型..."}),_&&t.jsx("button",{onClick:()=>X(""),className:"absolute right-2 top-1/2 -translate-y-1/2 text-dark-muted hover:text-white",title:"清除","aria-label":"清除搜索",children:t.jsx(Be,{size:13})})]}),t.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3 max-h-[420px] overflow-y-auto custom-scrollbar pr-1",children:y?t.jsxs("div",{className:"col-span-full flex items-center justify-center py-4 text-dark-muted text-sm",children:[t.jsx(bt,{size:14,className:"mr-2 animate-spin"}),"加载 Provider 列表..."]}):Te.length===0?t.jsxs("div",{className:"col-span-full border border-accent-red/30 bg-accent-red/10 rounded-lg p-4 text-center",children:[t.jsx("div",{className:"text-sm text-accent-red font-medium mb-1",children:"未找到匹配的 Provider"}),t.jsxs("div",{className:"text-xs text-dark-muted mb-3",children:["没有与「",_,"」匹配的 Provider,请检查拼写或改用完整列表"]}),t.jsxs("div",{className:"flex items-center justify-center gap-2",children:[t.jsxs("button",{onClick:()=>X(""),className:"inline-flex items-center gap-1 px-2.5 py-1 text-xs border border-dark-border rounded hover:bg-dark-hover",children:[t.jsx(Be,{size:12}),"清除搜索"]}),t.jsxs("button",{onClick:ce,className:"inline-flex items-center gap-1 px-2.5 py-1 text-xs bg-accent-blue text-white rounded hover:opacity-90",children:[t.jsx(Fe,{size:12}),"添加自定义 Provider"]})]})]}):Te.map(e=>{var o,i;const s=e.key==="custom",a=s?P:(o=n==null?void 0:n.providers)==null?void 0:o[e.key],l=a==null?void 0:a.hasApiKey,c=s?!!(n!=null&&n.defaultProvider)&&((P==null?void 0:P.keys)||[]).includes(n.defaultProvider):(n==null?void 0:n.defaultProvider)===e.key;return t.jsxs("div",{className:`text-left p-3 rounded-lg border transition-colors relative ${l?"border-accent-green/30 bg-dark-surface hover:border-accent-green/50":"border-dark-border bg-dark-surface hover:border-dark-hover"}`,children:[t.jsxs("div",{onClick:()=>e.key==="custom"?ce():Ie(e),className:"cursor-pointer",children:[t.jsxs("div",{className:"flex items-center justify-between mb-1",children:[t.jsx("span",{className:"text-sm font-medium",children:e.name}),l&&t.jsx(ie,{size:14,className:"text-accent-green"})]}),t.jsxs("div",{className:"text-[10px] text-dark-muted space-y-0.5",children:[t.jsx("div",{className:"truncate",children:s?(a==null?void 0:a.baseUrl)||"自定义地址":e.baseUrl||"自定义地址"}),t.jsx("div",{className:"truncate",children:s&&P?`${P.keys.join(", ")}`:e.defaultModel||"无默认模型"}),t.jsxs("div",{children:[a?`${a.modelCount} 已配置`:`${((i=e.models)==null?void 0:i.length)||0} 可用`,e.models&&e.models.length>0&&!a&&t.jsx("span",{className:"text-accent-blue",children:" ✓"})]})]}),c&&t.jsx("div",{className:"mt-1 text-[10px] text-accent-blue",children:"默认 Provider"})]}),l&&e.key!=="custom"&&t.jsx("button",{onClick:x=>{x.stopPropagation(),ot(e.key)},className:"absolute top-1.5 right-1.5 p-1 rounded text-dark-muted hover:bg-accent-red/10 hover:text-accent-red transition-colors",title:"删除 Provider","aria-label":`删除 ${e.name}`,children:t.jsx(_e,{size:13})})]})})})]})]}),d&&t.jsxs("div",{className:"grid grid-cols-4 gap-4",children:[t.jsx(ae,{title:"总体状态",value:d.totalInstances===0?"未配置":d.overallStatus==="healthy"?"健康":d.overallStatus==="degraded"?"降级":"异常",color:d.totalInstances===0?"blue":d.overallStatus==="healthy"?"green":d.overallStatus==="degraded"?"yellow":"red"}),t.jsx(ae,{title:"健康率",value:d.totalInstances===0?"N/A":`${(d.healthRate*100).toFixed(0)}%`,color:d.totalInstances===0?"blue":d.healthRate>.8?"green":d.healthRate>.5?"yellow":"red"}),t.jsx(ae,{title:"在线实例",value:d.totalInstances===0?"无":`${d.healthyInstances}/${d.totalInstances}`,color:d.healthyInstances>0?"green":"red"}),t.jsx(ae,{title:"总请求数",value:d.totalRequests>0?d.totalRequests.toLocaleString():"0",color:"blue"})]}),t.jsxs("div",{children:[t.jsx("div",{className:"flex items-center justify-between mb-3",children:t.jsx("h3",{className:"text-sm font-medium",children:"已配置模型"})}),t.jsxs("div",{className:"space-y-2 max-h-[480px] overflow-y-auto custom-scrollbar pr-1",children:[m.map(e=>{const s=Qe(e),a=s.inputTokens+s.outputTokens;return t.jsx("div",{className:`bg-dark-surface border rounded-lg p-3 ${e.status==="online"?"border-accent-green":"border-dark-border opacity-70"}`,children:t.jsxs("div",{className:"flex items-start justify-between gap-4",children:[t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[t.jsx("span",{className:dt(e.status),children:it(e.status)}),t.jsx("span",{className:"font-medium text-sm",children:e.name}),t.jsx("span",{className:"text-[10px] text-dark-muted px-1.5 py-0.5 bg-dark-bg rounded",children:e.provider}),e.apiType&&t.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded ${e.apiType==="anthropic-messages"?"bg-accent-purple/20 text-accent-purple":"bg-accent-blue/20 text-accent-blue"}`,children:e.apiType==="anthropic-messages"?"Anthropic":"OpenAI"}),e.isGlobalDefault&&t.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-accent-green/20 text-accent-green font-medium",children:"全局默认"}),e.isPlanDefault&&t.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-accent-blue/20 text-accent-blue font-medium",children:"Plan 默认"}),e.isActDefault&&t.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-accent-yellow/20 text-accent-yellow font-medium",children:"Act 默认"}),e.isGoalDefault&&t.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-accent-purple/20 text-accent-purple font-medium",children:"Goal 默认"})]}),t.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs",children:[t.jsx(re,{label:"负载",value:`${e.load}/${e.maxLoad}`}),t.jsx(re,{label:"Token",value:`${e.tokens}/${e.maxTokens}`}),t.jsx(re,{label:"输入价格",value:`$${e.price.input}/1K`}),t.jsx(re,{label:"输出价格",value:`$${e.price.output}/1K`})]}),t.jsxs("div",{className:"mt-3 grid grid-cols-1 sm:grid-cols-4 gap-3 items-end",children:[t.jsx(qe,{label:"输入 token",value:s.inputTokens,onChange:l=>Pe(e,"inputTokens",l)}),t.jsx(qe,{label:"输出 token",value:s.outputTokens,onChange:l=>Pe(e,"outputTokens",l)}),t.jsxs("div",{children:[t.jsx("div",{className:"text-[11px] text-dark-muted mb-1",children:"总 token"}),t.jsx("div",{className:"px-3 py-2 rounded border border-dark-border bg-dark-bg text-sm font-mono",children:a.toLocaleString()})]}),t.jsxs("button",{onClick:()=>Ze(e),className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 rounded border border-dark-border text-sm text-dark-muted hover:bg-dark-hover",children:[t.jsx(mt,{size:13}),"重置"]})]})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[!e.isGlobalDefault&&e.enabled!==!1&&t.jsx("button",{onClick:async()=>{try{await p.models.setDefaults({global:`${e.provider}:${e.id}`}),await h()}catch(l){N(l instanceof Error?l.message:"设置全局默认失败")}},className:"px-2 py-1 rounded text-[10px] border border-accent-green/30 text-accent-green hover:bg-accent-green/10",title:"设为全局默认",children:"全局默认"}),!e.isPlanDefault&&e.enabled!==!1&&t.jsx("button",{onClick:async()=>{try{await p.models.setDefaults({plan:`${e.provider}:${e.id}`}),await h()}catch(l){N(l instanceof Error?l.message:"设置 Plan 默认失败")}},className:"px-2 py-1 rounded text-[10px] border border-accent-blue/30 text-accent-blue hover:bg-accent-blue/10",title:"设为 Plan 默认",children:"Plan 默认"}),!e.isActDefault&&e.enabled!==!1&&t.jsx("button",{onClick:async()=>{try{await p.models.setDefaults({act:`${e.provider}:${e.id}`}),await h()}catch(l){N(l instanceof Error?l.message:"设置 Act 默认失败")}},className:"px-2 py-1 rounded text-[10px] border border-accent-yellow/30 text-accent-yellow hover:bg-accent-yellow/10",title:"设为 Act 默认",children:"Act 默认"}),!e.isGoalDefault&&e.enabled!==!1&&t.jsx("button",{onClick:async()=>{try{await p.models.setDefaults({goal:`${e.provider}:${e.id}`}),await h()}catch(l){N(l instanceof Error?l.message:"设置 Goal 默认失败")}},className:"px-2 py-1 rounded text-[10px] border border-accent-purple/30 text-accent-purple hover:bg-accent-purple/10",title:"设为 Goal 默认",children:"Goal 默认"}),t.jsx("button",{onClick:()=>nt(e),className:"p-1.5 rounded hover:bg-accent-blue/10 text-dark-muted hover:text-accent-blue",title:"编辑模型",children:t.jsx(ht,{size:13})}),t.jsx("button",{onClick:()=>rt(e.provider,e.id),className:"p-1.5 rounded hover:bg-accent-red/10 text-dark-muted hover:text-accent-red",title:"删除模型",children:t.jsx(_e,{size:13})}),t.jsx("button",{onClick:()=>at(e.id),disabled:v===e.id,className:"p-1.5 rounded hover:bg-dark-hover disabled:opacity-50",title:"刷新",children:t.jsx(de,{size:13,className:v===e.id?"animate-spin":""})}),t.jsx("button",{onClick:()=>st(e.id),className:`px-2 py-0.5 rounded text-xs transition-colors ${e.status==="online"?"bg-accent-red/20 text-accent-red hover:bg-accent-red/30":"bg-accent-green/20 text-accent-green hover:bg-accent-green/30"}`,children:e.status==="online"?"禁用":"启用"})]})]})},M(e))}),m.length===0&&t.jsxs("div",{className:"text-center text-dark-muted py-6",children:[t.jsx(ft,{size:36,className:"mx-auto mb-2 opacity-40"}),t.jsx("p",{className:"text-sm",children:"暂无模型,请先在上方配置 Provider"})]})]})]}),t.jsx(Ge,{isOpen:Xe,onClose:()=>{z(!1),B("select"),R(null)},title:fe==="select"?"选择 Provider":(U==null?void 0:U.name)||"Provider 配置",size:"xl",children:fe==="select"?t.jsx("div",{className:"space-y-4",children:t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[ee.filter(e=>e.key!=="custom").map(e=>t.jsxs("button",{onClick:()=>Ie(e),className:"text-left p-3 rounded-lg border border-dark-border bg-dark-bg hover:border-accent-blue transition-colors",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[t.jsx(ie,{size:14,className:"text-accent-blue"}),t.jsx("span",{className:"text-sm font-medium",children:e.name})]}),t.jsx("div",{className:"text-xs text-dark-muted",children:e.defaultModel})]},e.key)),t.jsxs("button",{onClick:ce,className:"text-left p-3 rounded-lg border border-dashed border-dark-border bg-dark-bg hover:border-accent-blue transition-colors",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[t.jsx(gt,{size:14,className:"text-accent-blue"}),t.jsx("span",{className:"text-sm font-medium",children:"自定义 Provider"})]}),t.jsx("div",{className:"text-xs text-dark-muted",children:"手动填写 Provider 名称、Base URL 和模型 ID"})]})]})}):t.jsxs("div",{className:"space-y-3",children:[g==="custom"&&t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"Provider 名称 *"}),t.jsx("input",{value:u.providerKey,onChange:e=>T(s=>({...s,providerKey:e.target.value})),className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue",placeholder:"例如: my-provider"})]}),t.jsxs("div",{children:[t.jsxs("label",{className:"block text-sm text-dark-muted mb-1",children:["API Keys",(De=(Ke=n==null?void 0:n.providers)==null?void 0:Ke[g==="custom"?u.providerKey.trim():g||""])!=null&&De.hasApiKey?"":" *",t.jsxs("span",{className:"text-dark-muted/60 text-xs",children:["(每行一把,可多把",(Me=(Ae=n==null?void 0:n.providers)==null?void 0:Ae[g==="custom"?u.providerKey.trim():g||""])!=null&&Me.hasApiKey?",留空则保留已保存的 Key":"",")"]})]}),t.jsxs("div",{className:"relative",children:[t.jsx("textarea",{rows:3,value:u.apiKeys,onChange:e=>T(s=>({...s,apiKeys:e.target.value})),className:"w-full px-3 py-2 pr-10 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue resize-y custom-scrollbar",placeholder:`每行输入一把 API Key
|
|
2
|
+
支持多把(运行时取第一把,其余备用)`}),t.jsx("button",{onClick:()=>ne(e=>!e),className:"absolute right-2 top-2 text-dark-muted hover:text-white",children:Je?t.jsx(vt,{size:14}):t.jsx(kt,{size:14})})]})]}),t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"模型 ID"}),t.jsxs("div",{className:"flex gap-2",children:[t.jsx("input",{value:u.modelIds,onChange:e=>{const s=e.target.value;T(a=>({...a,modelIds:s})),D(()=>{const a=new Set;for(const l of s.split(",")){const c=l.trim().split("|")[0].trim();c&&J.some(o=>o.id===c)&&a.add(c)}return a})},className:"flex-1 px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue",placeholder:(U==null?void 0:U.defaultModel)||"gpt-4o, deepseek-chat (格式: id|名称|别名)"}),t.jsxs("button",{onClick:et,disabled:le||!u.baseUrl,className:"inline-flex items-center gap-1 px-3 py-2 rounded text-sm border border-accent-blue/30 text-accent-blue hover:bg-accent-blue/10 disabled:opacity-50 whitespace-nowrap",title:"从 API 获取模型列表",children:[le?t.jsx(de,{size:13,className:"animate-spin"}):t.jsx(yt,{size:13}),le?"获取中...":"获取模型列表"]})]}),Ce&&t.jsx("div",{className:"mt-1 text-xs text-accent-red",children:Ce}),J.length>0&&t.jsxs("div",{className:"mt-2 border border-dark-border rounded-lg bg-dark-bg p-2",children:[t.jsxs("div",{className:"flex items-center justify-between mb-2",children:[t.jsxs("span",{className:"text-xs text-dark-muted",children:["已获取 ",t.jsx("strong",{className:"text-dark-text",children:J.length})," 个模型, 已选 ",t.jsx("strong",{className:"text-accent-blue",children:Q.size})," 个",t.jsx("span",{className:"text-accent-blue/70",children:"(勾选即自动应用到「模型 ID」输入框)"})]}),t.jsx("button",{onClick:()=>{W([]),D(new Set)},className:"px-2 py-0.5 text-[10px] border border-dark-border rounded hover:bg-dark-hover",children:"关闭"})]}),t.jsxs("div",{className:"relative mb-2",children:[t.jsx(Oe,{size:12,className:"absolute left-2 top-1/2 -translate-y-1/2 text-dark-muted"}),t.jsx("input",{value:Z,onChange:e=>oe(e.target.value),className:"w-full pl-7 pr-2 py-1 text-xs bg-dark-bg border border-dark-border rounded focus:outline-none focus:border-accent-blue",placeholder:"搜索模型..."})]}),t.jsx("div",{className:"max-h-48 overflow-y-auto custom-scrollbar grid grid-cols-2 sm:grid-cols-3 gap-1",children:J.filter(e=>!Z||e.id.toLowerCase().includes(Z.toLowerCase())||e.name.toLowerCase().includes(Z.toLowerCase())).map(e=>{const s=Q.has(e.id);return t.jsxs("div",{role:"checkbox","aria-checked":s,tabIndex:-1,onMouseDown:a=>a.preventDefault(),onClick:()=>tt(e.id),className:`flex items-center gap-1.5 px-2 py-1 rounded cursor-pointer text-xs transition-colors select-none ${s?"bg-accent-blue/20 text-accent-blue border border-accent-blue/30":"hover:bg-dark-hover border border-transparent"}`,children:[s?t.jsx(ie,{size:10}):t.jsx("div",{className:"w-2.5 h-2.5 rounded border border-dark-border"}),t.jsx("span",{className:"truncate",children:e.id})]},e.id)})})]})]}),t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"Base URL"}),t.jsx("input",{value:u.baseUrl,onChange:e=>T(s=>({...s,baseUrl:e.target.value})),className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue",placeholder:"https://api.example.com/v1"})]}),t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"API 类型"}),t.jsx("div",{className:"grid grid-cols-2 gap-2",children:Tt.map(e=>t.jsx("div",{role:"radio","aria-checked":u.apiType===e,tabIndex:-1,onMouseDown:s=>s.preventDefault(),onClick:()=>T(s=>({...s,apiType:e})),className:`flex items-center justify-center gap-1.5 px-3 py-2 rounded text-sm cursor-pointer border transition-colors select-none ${u.apiType===e?"bg-accent-blue/20 border-accent-blue text-accent-blue":"bg-dark-bg border-dark-border text-dark-muted hover:border-dark-hover"}`,children:It[e]},e))})]}),t.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[t.jsx("input",{type:"checkbox",checked:u.setDefault,onChange:e=>T(s=>({...s,setDefault:e.target.checked})),className:"accent-accent-blue"}),t.jsx("span",{className:"text-sm text-dark-muted",children:"设为默认 Provider"})]}),ke&&t.jsx("div",{className:"text-sm text-accent-red",children:ke}),t.jsxs("div",{className:"flex justify-between gap-2 pt-2",children:[t.jsx("div",{children:g&&g!=="custom"&&((Ee=(Se=n==null?void 0:n.providers)==null?void 0:Se[g])==null?void 0:Ee.hasApiKey)&&t.jsx("button",{onClick:async()=>{if(confirm(`确定要删除 "${g}" 的配置吗?`))try{await p.config.provider.delete(g),z(!1),R(null),await A(),await h()}catch{}},className:"px-4 py-2 rounded border border-accent-red/30 text-accent-red hover:bg-accent-red/10 transition-colors text-sm",children:"删除 Provider"})}),t.jsx("button",{onClick:()=>{B("select"),R(null),z(!1)},className:"px-4 py-2 rounded border border-dark-border hover:bg-dark-hover transition-colors text-sm",children:"取消"}),t.jsx("button",{onClick:lt,disabled:ge,className:"px-4 py-2 bg-accent-blue text-white rounded hover:bg-accent-blue/80 transition-colors text-sm disabled:opacity-50",children:ge?"保存中...":"保存"})]})]})}),t.jsx(Ge,{isOpen:Ve,onClose:()=>{q(!1),V(null)},title:"编辑模型",size:"lg",children:t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"提供商名称 *"}),t.jsx("input",{value:b.provider,onChange:e=>C(s=>({...s,provider:e.target.value})),disabled:!!w,className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue disabled:opacity-50",placeholder:"例如: openai, deepseek"})]}),t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"模型 ID *"}),t.jsx("input",{value:b.modelId,onChange:e=>C(s=>({...s,modelId:e.target.value})),disabled:!!w,className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue disabled:opacity-50",placeholder:"例如: gpt-4o, deepseek-chat"})]}),t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:"模型名称"}),t.jsx("input",{value:b.modelName,onChange:e=>C(s=>({...s,modelName:e.target.value})),className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue",placeholder:"留空则使用模型 ID"})]}),t.jsxs("div",{children:[t.jsxs("label",{className:"block text-sm text-dark-muted mb-1",children:["API Key",w&&((ze=($e=n==null?void 0:n.providers)==null?void 0:$e[w.provider])==null?void 0:ze.hasApiKey)&&t.jsx("span",{className:"text-accent-green/80 text-xs ml-1",children:"已配置(留空则保持不变)"})]}),t.jsx("input",{type:"password",value:b.apiKey,onChange:e=>C(s=>({...s,apiKey:e.target.value})),className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue",placeholder:w&&((Le=(Re=n==null?void 0:n.providers)==null?void 0:Re[w.provider])!=null&&Le.hasApiKey)?"留空保持当前 API Key":"输入新的 API Key"})]}),t.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[t.jsx(xe,{label:"温度",value:b.temperature,step:"0.1",min:"0",max:"2",onChange:e=>C(s=>({...s,temperature:e}))}),t.jsx(xe,{label:"最大 Token",value:b.maxTokens,onChange:e=>C(s=>({...s,maxTokens:e}))}),t.jsx(xe,{label:"上下文窗",value:b.contextWindow,onChange:e=>C(s=>({...s,contextWindow:e}))})]}),he&&t.jsx("div",{className:"text-sm text-accent-red bg-accent-red/10 p-2 rounded",children:he}),t.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[t.jsx("button",{onClick:()=>{q(!1),V(null),C(ue)},className:"px-4 py-2 rounded border border-dark-border hover:bg-dark-hover transition-colors text-sm",children:"取消"}),t.jsx("button",{onClick:ct,disabled:be,className:"px-4 py-2 bg-accent-blue text-white rounded hover:bg-accent-blue/80 transition-colors text-sm disabled:opacity-50",children:be?"保存中...":"保存"})]})]})})]})}function ae({title:k,value:y,color:j}){const m={green:"bg-accent-green/10 text-accent-green",yellow:"bg-accent-yellow/10 text-accent-yellow",red:"bg-accent-red/10 text-accent-red",blue:"bg-accent-blue/10 text-accent-blue"};return t.jsxs("div",{className:`${m[j]} rounded-lg p-3`,children:[t.jsx("div",{className:"text-xs opacity-70",children:k}),t.jsx("div",{className:"text-xl font-semibold",children:y})]})}function re({label:k,value:y}){return t.jsxs("div",{children:[t.jsx("div",{className:"text-dark-muted",children:k}),t.jsx("div",{children:y})]})}function qe({label:k,value:y,onChange:j}){return t.jsxs("div",{children:[t.jsx("label",{className:"block text-[11px] text-dark-muted mb-1",children:k}),t.jsx("input",{type:"number",min:"0",value:y,onChange:m=>j(parseInt(m.target.value,10)||0),className:"w-full px-3 py-2 rounded border border-dark-border bg-dark-bg text-sm focus:outline-none focus:border-accent-blue"})]})}function xe({label:k,value:y,onChange:j,min:m,max:F,step:d}){return t.jsxs("div",{children:[t.jsx("label",{className:"block text-sm text-dark-muted mb-1",children:k}),t.jsx("input",{type:"number",value:y,min:m,max:F,step:d,onChange:E=>j(d?parseFloat(E.target.value)||0:parseInt(E.target.value,10)||0),className:"w-full px-3 py-2 bg-dark-bg border border-dark-border rounded text-sm focus:outline-none focus:border-accent-blue"})]})}export{Et as ModelsView,Et as default};
|